[cpp-sp] branch main updated: Initial purge of code from next-gen SP.
Scott Cantor
cantor.2 at osu.edu
Tue Oct 29 14:40:38 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=d1c57b40a17cf48c820d10ee1e730e5a798d1788
The following commit(s) were added to refs/heads/main by this push:
new d1c57b40 Initial purge of code from next-gen SP.
d1c57b40 is described below
commit d1c57b40a17cf48c820d10ee1e730e5a798d1788
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Oct 29 10:40:33 2024 -0400
Initial purge of code from next-gen SP.
---
Makefile.am | 20 -
adfs/Makefile.am | 47 --
adfs/adfs.cpp | 1118 -------------------------------------
adfs/adfs.rc | 109 ----
adfs/resource.h | 35 --
configure.ac | 228 +-------
doc/api/.gitkeep | 0
doxygen.am | 186 ------
doxygen.cfg | 255 ---------
isapi_shib/isapi_shib.cpp | 1105 ------------------------------------
isapi_shib/isapi_shib.rc | 96 ----
isapi_shib/resource.h | 35 --
m4/ax_cxx_compile_stdcxx.m4 | 1071 +++++++++++++++++++++++++++++++++++
m4/doxygen.m4 | 537 ------------------
memcache-store/Makefile.am | 29 -
memcache-store/memcache-store.cpp | 630 ---------------------
memcache-store/memcache-store.rc | 97 ----
memcache-store/resource.h | 34 --
nsapi_shib/Makefile.am | 23 -
nsapi_shib/nsapi_shib.cpp | 696 -----------------------
nsapi_shib/nsapi_shib.rc | 101 ----
nsapi_shib/resource.h | 35 --
odbc-store/Makefile.am | 30 -
odbc-store/odbc-store.cpp | 897 -----------------------------
odbc-store/odbc-store.rc | 97 ----
odbc-store/resource.h | 34 --
selinux/Makefile.am | 25 -
selinux/shibshar.fc.in | 4 -
selinux/shibshar.te | 33 --
shibboleth.spec.in | 646 ---------------------
shibd/Makefile.am | 22 -
shibd/resource.h | 35 --
shibd/shibd.cpp | 484 ----------------
shibd/shibd.rc | 101 ----
shibd/shibd_win32.cpp | 550 ------------------
35 files changed, 1076 insertions(+), 8369 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index cb551cfb..49de98a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,6 @@
AUTOMAKE_OPTIONS = foreign dist-zip dist-bzip2
ACLOCAL_AMFLAGS = -I m4
-include doxygen.am
-
-MOSTLYCLEANFILES = $(DX_CLEANFILES)
-
WANT_SUBDIRS = @WANT_SUBDIRS@
SUBDIRS = $(WANT_SUBDIRS)
@@ -14,30 +10,14 @@ DIST_SUBDIRS = \
schemas \
configs \
shibsp \
- shibd \
- adfs \
- plugins \
util \
apache \
- nsapi_shib \
fastcgi \
- odbc-store \
- memcache-store \
- selinux \
unittests
-if DX_COND_doc
-all-local: doxygen-doc
-else
-all-local:
-endif
-
pkgconfig_DATA = shibsp.pc shibsp-lite.pc
-GENFILES = @PACKAGE_NAME at .spec
-
EXTRA_DIST = $(DX_CONFIG) \
- isapi_shib \
iis7_shib \
Projects \
pkgconfig-workarounds \
diff --git a/adfs/Makefile.am b/adfs/Makefile.am
deleted file mode 100644
index 17c94162..00000000
--- a/adfs/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = adfs.la adfs-lite.la
-
-adfs_la_CXXFLAGS = \
- $(AM_CXXFLAGS) \
- $(BOOST_CPPFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(log4cpp_CFLAGS) \
- $(log4shib_CFLAGS) \
- $(opensaml_CFLAGS) \
- $(xmltooling_CFLAGS) \
- $(xerces_CFLAGS)
-adfs_la_LIBADD = \
- $(top_builddir)/shibsp/libshibsp.la \
- $(PTHREAD_LIBS) \
- $(log4cpp_LIBS) \
- $(log4shib_LIBS) \
- $(opensaml_LIBS) \
- $(xmltooling_LIBS) \
- $(xerces_LIBS)
-adfs_la_LDFLAGS = -module -avoid-version
-
-adfs_la_SOURCES = \
- adfs.cpp
-
-adfs_lite_la_SOURCES = \
- adfs.cpp
-
-adfs_lite_la_CXXFLAGS = -DSHIBSP_LITE \
- $(AM_CXXFLAGS) \
- $(BOOST_CPPFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(log4cpp_CFLAGS) \
- $(log4shib_CFLAGS) \
- $(xmltooling_lite_CFLAGS) \
- $(xerces_CFLAGS)
-adfs_lite_la_LIBADD = $(top_builddir)/shibsp/libshibsp-lite.la \
- $(PTHREAD_LIBS) \
- $(log4cpp_LIBS) \
- $(log4shib_LIBS) \
- $(xmltooling_lite_LIBS) \
- $(xerces_LIBS)
-adfs_lite_la_LDFLAGS = -module -avoid-version
-
-EXTRA_DIST = resource.h adfs.rc
diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp
deleted file mode 100644
index a3f7ee52..00000000
--- a/adfs/adfs.cpp
+++ /dev/null
@@ -1,1118 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-/**
- * adfs.cpp
- *
- * ADFSv1 extension library.
- */
-
-#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 ADFS_EXPORTS __declspec(dllexport)
-#else
-# define ADFS_EXPORTS
-#endif
-
-#include <shibsp/base.h>
-#include <shibsp/exceptions.h>
-#include <shibsp/Application.h>
-#include <shibsp/ServiceProvider.h>
-#include <shibsp/SessionCache.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/SPRequest.h>
-#include <shibsp/TransactionLog.h>
-#include <shibsp/handler/AssertionConsumerService.h>
-#include <shibsp/handler/LogoutInitiator.h>
-#include <shibsp/handler/SessionInitiator.h>
-#include <xmltooling/logging.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/URLEncoder.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <memory>
-
-#ifndef SHIBSP_LITE
-# include <shibsp/attribute/resolver/ResolutionContext.h>
-# include <shibsp/metadata/MetadataProviderCriteria.h>
-# include <saml/SAMLConfig.h>
-# include <saml/exceptions.h>
-# include <saml/binding/SecurityPolicy.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/EndpointManager.h>
-# include <xmltooling/XMLToolingConfig.h>
-# include <xmltooling/impl/AnyElement.h>
-# include <xmltooling/util/ParserPool.h>
-# include <xmltooling/validation/ValidatorSuite.h>
-using namespace opensaml::saml2md;
-# ifndef min
-# define min(a,b) (((a) < (b)) ? (a) : (b))
-# endif
-#endif
-using namespace shibsp;
-using namespace opensaml;
-using namespace xmltooling::logging;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-#define WSFED_NS "http://schemas.xmlsoap.org/ws/2003/07/secext"
-#define WSTRUST_NS "http://schemas.xmlsoap.org/ws/2005/02/trust"
-
-namespace {
-
-#ifndef SHIBSP_LITE
- class SHIBSP_DLLLOCAL ADFSDecoder : public MessageDecoder
- {
- auto_ptr_XMLCh m_ns;
- public:
- ADFSDecoder() : m_ns(WSTRUST_NS) {}
- virtual ~ADFSDecoder() {}
-
- const XMLCh* getProtocolFamily() const {
- return m_ns.get();
- }
-
- XMLObject* decode(
- string& relayState,
- const GenericRequest& genericRequest,
- const GenericResponse* genericResponse,
- SecurityPolicy& policy
- ) const;
-
- protected:
- void extractMessageDetails(
- const XMLObject& message, const GenericRequest& req, const XMLCh* protocol, SecurityPolicy& policy
- ) const {
- }
- };
-
- MessageDecoder* ADFSDecoderFactory(const DOMElement* const &, bool)
- {
- return new ADFSDecoder();
- }
-#endif
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class SHIBSP_DLLLOCAL ADFSSessionInitiator : public SessionInitiator, public AbstractHandler, public RemotedHandler
- {
- public:
- ADFSSessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.ADFS"), nullptr, this), m_appId(appId), m_binding(WSFED_NS) {
- SPConfig::getConfig().deprecation().warn("ADFS SessionInitiator");
-
- // If Location isn't set, defer address registration until the setParent call.
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::ADFSSI";
- setAddress(address.c_str());
- }
- }
- virtual ~ADFSSessionInitiator() {}
-
- void setParent(const PropertySet* parent) {
- DOMPropertySet::setParent(parent);
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::ADFSSI";
- setAddress(address.c_str());
- }
- else {
- m_log.warn("no Location property in ADFS SessionInitiator (or parent), can't register as remoted handler");
- }
- }
-
- void receive(DDF& in, ostream& out);
- pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
- pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
-
- const XMLCh* getProtocolFamily() const {
- return m_binding.get();
- }
-
-#ifndef SHIBSP_LITE
- void generateMetadata(saml2md::SPSSODescriptor& role, const char* handlerURL) const {
- doGenerateMetadata(role, handlerURL);
- }
-#endif
-
- private:
- pair<bool,long> doRequest(
- const Application& application,
- const HTTPRequest* httpRequest,
- HTTPResponse& httpResponse,
- const char* entityID,
- const char* acsLocation,
- const char* authnContextClassRef,
- string& relayState
- ) const;
- string m_appId;
- auto_ptr_XMLCh m_binding;
- };
-
- class SHIBSP_DLLLOCAL ADFSConsumer : public shibsp::AssertionConsumerService
- {
- auto_ptr_XMLCh m_protocol;
- public:
- ADFSConsumer(const DOMElement* e, const char* appId, bool deprecationSupport)
- : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT ".SSO.ADFS"), nullptr, nullptr, deprecationSupport),
- m_protocol(WSFED_NS) {
- SPConfig::getConfig().deprecation().warn("ADFS AssertionConsumerService");
- }
- virtual ~ADFSConsumer() {}
-
-#ifndef SHIBSP_LITE
- void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
- AssertionConsumerService::generateMetadata(role, handlerURL);
- role.addSupport(m_protocol.get());
- }
-
- private:
- const char* getProfile() const {
- return WSFED_NS;
- }
-
- void implementProtocol(
- const Application& application,
- const HTTPRequest& httpRequest,
- HTTPResponse& httpResponse,
- SecurityPolicy& policy,
- const PropertySet*,
- const XMLObject& xmlObject
- ) const;
-#else
- const XMLCh* getProtocolFamily() const {
- return m_protocol.get();
- }
-#endif
- };
-
- class SHIBSP_DLLLOCAL ADFSLogoutInitiator : public AbstractHandler, public LogoutInitiator
- {
- public:
- ADFSLogoutInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".LogoutInitiator.ADFS")), m_appId(appId), m_binding(WSFED_NS) {
-
- SPConfig::getConfig().deprecation().warn("ADFS LogoutInitiator");
-
- // If Location isn't set, defer address registration until the setParent call.
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::ADFSLI";
- setAddress(address.c_str());
- }
- }
- virtual ~ADFSLogoutInitiator() {}
-
- void setParent(const PropertySet* parent) {
- DOMPropertySet::setParent(parent);
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::ADFSLI";
- setAddress(address.c_str());
- }
- else {
- m_log.warn("no Location property in ADFS LogoutInitiator (or parent), can't register as remoted handler");
- }
- }
-
- void receive(DDF& in, ostream& out);
- pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
- const XMLCh* getProtocolFamily() const {
- return m_binding.get();
- }
-
- private:
- pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session) const;
-
- string m_appId;
- auto_ptr_XMLCh m_binding;
- };
-
- class SHIBSP_DLLLOCAL ADFSLogout : public AbstractHandler, public LogoutHandler
- {
- public:
- ADFSLogout(const DOMElement* e, const char* appId, bool deprecationSupport)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".Logout.ADFS")), m_login(e, appId, deprecationSupport) {
-
- SPConfig::getConfig().deprecation().warn("ADFS Logout handler");
-
- m_initiator = false;
-#ifndef SHIBSP_LITE
- m_preserve.push_back("wreply");
- string address = string(appId) + getString("Location").second + "::run::ADFSLO";
- setAddress(address.c_str());
-#endif
- }
- virtual ~ADFSLogout() {}
-
- pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
-#ifndef SHIBSP_LITE
- void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
- m_login.generateMetadata(role, handlerURL);
- const char* loc = getString("Location").second;
- string hurl(handlerURL);
- if (*loc != '/')
- hurl += '/';
- hurl += loc;
- auto_ptr_XMLCh widen(hurl.c_str());
- SingleLogoutService* ep = SingleLogoutServiceBuilder::buildSingleLogoutService();
- ep->setLocation(widen.get());
- ep->setBinding(m_login.getProtocolFamily());
- role.getSingleLogoutServices().push_back(ep);
- }
-
- const char* getType() const {
- return m_login.getType();
- }
-#endif
- const XMLCh* getProtocolFamily() const {
- return m_login.getProtocolFamily();
- }
-
- private:
- ADFSConsumer m_login;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- SessionInitiator* ADFSSessionInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
- {
- return new ADFSSessionInitiator(p.first, p.second);
- }
-
- Handler* ADFSLogoutFactory(const pair<const DOMElement*,const char*>& p, bool deprecationSupport)
- {
- return new ADFSLogout(p.first, p.second, deprecationSupport);
- }
-
- Handler* ADFSLogoutInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
- {
- return new ADFSLogoutInitiator(p.first, p.second);
- }
-
- const XMLCh RequestedSecurityToken[] = UNICODE_LITERAL_22(R,e,q,u,e,s,t,e,d,S,e,c,u,r,i,t,y,T,o,k,e,n);
- const XMLCh RequestSecurityTokenResponse[] =UNICODE_LITERAL_28(R,e,q,u,e,s,t,S,e,c,u,r,i,t,y,T,o,k,e,n,R,e,s,p,o,n,s,e);
-};
-
-extern "C" int ADFS_EXPORTS xmltooling_extension_init(void*)
-{
- SPConfig& conf=SPConfig::getConfig();
- conf.SessionInitiatorManager.registerFactory("ADFS", ADFSSessionInitiatorFactory);
- conf.LogoutInitiatorManager.registerFactory("ADFS", ADFSLogoutInitiatorFactory);
- conf.AssertionConsumerServiceManager.registerFactory("ADFS", ADFSLogoutFactory);
- conf.AssertionConsumerServiceManager.registerFactory(WSFED_NS, ADFSLogoutFactory);
-#ifndef SHIBSP_LITE
- SAMLConfig::getConfig().MessageDecoderManager.registerFactory(WSFED_NS, ADFSDecoderFactory);
- XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestedSecurityToken"), new AnyElementBuilder());
- XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestSecurityTokenResponse"), new AnyElementBuilder());
-#endif
- return 0;
-}
-
-extern "C" void ADFS_EXPORTS xmltooling_extension_term()
-{
- /* should get unregistered during normal shutdown...
- SPConfig& conf=SPConfig::getConfig();
- conf.SessionInitiatorManager.deregisterFactory("ADFS");
- conf.LogoutInitiatorManager.deregisterFactory("ADFS");
- conf.AssertionConsumerServiceManager.deregisterFactory("ADFS");
- conf.AssertionConsumerServiceManager.deregisterFactory(WSFED_NS);
-#ifndef SHIBSP_LITE
- SAMLConfig::getConfig().MessageDecoderManager.deregisterFactory(WSFED_NS);
-#endif
- */
-}
-
-pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
-{
- // We have to know the IdP to function.
- if (entityID.empty() || !checkCompatibility(request, isHandler))
- return make_pair(false, 0L);
-
- string target;
- pair<bool,const char*> prop;
- pair<bool,const char*> acClass;
- const Handler* ACS = nullptr;
- const Application& app = request.getApplication();
-
- if (isHandler) {
- prop.second = request.getParameter("acsIndex");
- if (prop.second && *prop.second) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(atoi(prop.second));
- if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
- }
-
- prop = getString("target", request);
- if (prop.first)
- target = prop.second;
-
- // Since we're passing the ACS by value, we need to compute the return URL,
- // so we'll need the target resource for real.
- recoverRelayState(app, request, request, target, false);
- app.limitRedirect(request, target.c_str());
-
- // Default is to allow externally supplied settings.
- pair<bool,bool> externalInput = getBool("externalInput");
- unsigned int settingMask = HANDLER_PROPERTY_MAP | HANDLER_PROPERTY_FIXED;
- if (!externalInput.first || externalInput.second)
- settingMask |= HANDLER_PROPERTY_REQUEST;
-
- acClass = getString("authnContextClassRef", request, settingMask);
- }
- else {
- // Check for a hardwired target value in the map or handler.
- prop = getString("target", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (prop.first)
- target = prop.second;
- else
- target = request.getRequestURL();
-
- acClass = getString("authnContextClassRef", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- }
-
- if (!ACS) {
- pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (index.first) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(index.second);
- }
- }
-
- // Validate the ACS for use with this protocol.
- if (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
- if (ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-ADFS ACS, using default ADFS ACS");
- ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily());
- if (!ACS)
- throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration.");
- }
-
- // Since we're not passing by index, we need to fully compute the return URL.
- // Compute the ACS URL. We add the ACS location to the base handlerURL.
- string ACSloc = request.getHandlerURL(target.c_str());
- prop = ACS->getString("Location");
- if (prop.first)
- ACSloc += prop.second;
-
- if (isHandler) {
- // We may already have RelayState set if we looped back here,
- // but we've turned it back into a resource by this point, so if there's
- // a target on the URL, reset to that value.
- prop.second = request.getParameter("target");
- if (prop.second && *prop.second)
- target = prop.second;
- }
-
- m_log.debug("attempting to initiate session using ADFS with provider (%s)", entityID.c_str());
-
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- // Out of process means the POST data via the request can be exposed directly to the private method.
- // The method will handle POST preservation if necessary *before* issuing the response, but only if
- // it dispatches to an IdP.
- return doRequest(app, &request, request, entityID.c_str(), ACSloc.c_str(), (acClass.first ? acClass.second : nullptr), target);
- }
-
- // Remote the call.
- DDF out,in = DDF(m_address.c_str()).structure();
- DDFJanitor jin(in), jout(out);
- in.addmember("application_id").string(app.getId());
- in.addmember("entity_id").string(entityID.c_str());
- in.addmember("acsLocation").string(ACSloc.c_str());
- if (!target.empty())
- in.addmember("RelayState").unsafe_string(target.c_str());
- if (acClass.first)
- in.addmember("authnContextClassRef").string(acClass.second);
-
- // Remote the processing.
- out = send(request, in);
- return unwrap(request, out);
-}
-
-pair<bool,long> ADFSSessionInitiator::unwrap(SPRequest& request, DDF& out) const
-{
- // See if there's any response to send back.
- if (!out["redirect"].isnull() || !out["response"].isnull()) {
- // If so, we're responsible for handling the POST data, probably by dropping a cookie.
- preservePostData(request.getApplication(), request, request, out["RelayState"].string());
- }
- return RemotedHandler::unwrap(request, out);
-}
-
-void ADFSSessionInitiator::receive(DDF& in, ostream& out)
-{
- // Find application.
- const char* aid = in["application_id"].string();
- const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
- if (!app) {
- // Something's horribly wrong.
- m_log.error("couldn't find application (%s) to generate ADFS request", aid ? aid : "(missing)");
- throw ConfigurationException("Unable to locate application for new session, deleted?");
- }
-
- const char* entityID = in["entity_id"].string();
- const char* acsLocation = in["acsLocation"].string();
- if (!entityID || !acsLocation)
- throw ConfigurationException("No entityID or acsLocation parameter supplied to remoted SessionInitiator.");
-
- DDF ret(nullptr);
- DDFJanitor jout(ret);
-
- // Wrap the outgoing object with a Response facade.
- scoped_ptr<HTTPResponse> http(getResponse(*app, ret));
-
- string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
-
- // Since we're remoted, the result should either be a throw, which we pass on,
- // a false/0 return, which we just return as an empty structure, or a response/redirect,
- // which we capture in the facade and send back.
- doRequest(*app, nullptr, *http, entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
- if (!ret.isstruct())
- ret.structure();
- ret.addmember("RelayState").unsafe_string(relayState.c_str());
- out << ret;
-}
-
-pair<bool,long> ADFSSessionInitiator::doRequest(
- const Application& app,
- const HTTPRequest* httpRequest,
- HTTPResponse& httpResponse,
- const char* entityID,
- const char* acsLocation,
- const char* authnContextClassRef,
- string& relayState
- ) const
-{
-#ifndef SHIBSP_LITE
- // Use metadata to invoke the SSO service directly.
- MetadataProvider* m = app.getMetadataProvider();
- Locker locker(m);
- MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
- pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
- if (!entity.first) {
- m_log.warn("unable to locate metadata for provider (%s)", entityID);
- throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
- }
- else if (!entity.second) {
- m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate ADFS-aware identity provider role for provider (%s)", entityID);
- if (getParent())
- return make_pair(false, 0L);
- throw MetadataException("Unable to locate ADFS-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
- const EndpointType* ep = EndpointManager<SingleSignOnService>(
- dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleSignOnServices()
- ).getByBinding(m_binding.get());
- if (!ep) {
- m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
- if (getParent())
- return make_pair(false, 0L);
- throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
-
- preserveRelayState(app, httpResponse, relayState);
-
- scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
- if (ar_event.get()) {
- ar_event->m_binding = WSFED_NS;
- ar_event->m_protocol = WSFED_NS;
- ar_event->m_peer = entity.first;
- app.getServiceProvider().getTransactionLog()->write(*ar_event);
- }
-
- // UTC timestamp
- time_t epoch=time(nullptr);
-#ifndef HAVE_GMTIME_R
- struct tm* ptime=gmtime(&epoch);
-#else
- struct tm res;
- struct tm* ptime=gmtime_r(&epoch,&res);
-#endif
- char timebuf[32];
- strftime(timebuf,32,"%Y-%m-%dT%H:%M:%SZ",ptime);
-
- auto_ptr_char dest(ep->getLocation());
- const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
-
- const PropertySet* relyingParty = app.getRelyingParty(entity.first);
-
- string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "wa=wsignin1.0&wreply=" + urlenc->encode(acsLocation) +
- "&wct=" + urlenc->encode(timebuf) + "&wtrealm=" + urlenc->encode(relyingParty->getString("entityID").second);
- if (!authnContextClassRef) {
- pair<bool,const char*> rpClass = relyingParty->getString("authnContextClassRef");
- if (rpClass.first)
- authnContextClassRef = rpClass.second;
- }
- if (authnContextClassRef)
- req += "&wauth=" + urlenc->encode(authnContextClassRef);
- if (!relayState.empty())
- req += "&wctx=" + urlenc->encode(relayState.c_str());
-
- if (httpRequest) {
- // If the request object is available, we're responsible for the POST data.
- preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
- }
-
- return make_pair(true, httpResponse.sendRedirect(req.c_str()));
-#else
- return make_pair(false, 0L);
-#endif
-}
-
-#ifndef SHIBSP_LITE
-
-XMLObject* ADFSDecoder::decode(
- string& relayState, const GenericRequest& genericRequest, const GenericResponse*, SecurityPolicy& policy
- ) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("decode");
-#endif
- Category& log = Category::getInstance(SHIBSP_LOGCAT ".MessageDecoder.ADFS");
-
- log.debug("validating input");
- const HTTPRequest* httpRequest=dynamic_cast<const HTTPRequest*>(&genericRequest);
- if (!httpRequest)
- throw BindingException("Unable to cast request object to HTTPRequest type.");
- if (strcmp(httpRequest->getMethod(),"POST"))
- throw BindingException("Invalid HTTP method ($1).", params(1, httpRequest->getMethod()));
- const char* param = httpRequest->getParameter("wa");
- if (!param || strcmp(param, "wsignin1.0"))
- throw BindingException("Missing or invalid wa parameter (should be wsignin1.0).");
- param = httpRequest->getParameter("wctx");
- if (param)
- relayState = param;
-
- param = httpRequest->getParameter("wresult");
- if (!param)
- throw BindingException("Request missing wresult parameter.");
-
- log.debug("decoded ADFS response:\n%s", param);
-
- // Parse and bind the document into an XMLObject.
- istringstream is(param);
- DOMDocument* doc = (policy.getValidating() ? XMLToolingConfig::getConfig().getValidatingParser()
- : XMLToolingConfig::getConfig().getParser()).parse(is);
- XercesJanitor<DOMDocument> janitor(doc);
- auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
- janitor.release();
-
- if (!XMLString::equals(xmlObject->getElementQName().getLocalPart(), RequestSecurityTokenResponse)) {
- log.error("unrecognized root element on message: %s", xmlObject->getElementQName().toString().c_str());
- throw BindingException("Decoded message was not of the appropriate type.");
- }
-
- SchemaValidators.validate(xmlObject.get());
-
- // Skip policy step here, there's no security in the wrapper.
- // policy.evaluate(*xmlObject.get(), &genericRequest);
-
- return xmlObject.release();
-}
-
-void ADFSConsumer::implementProtocol(
- const Application& application,
- const HTTPRequest& httpRequest,
- HTTPResponse& httpResponse,
- SecurityPolicy& policy,
- const PropertySet*,
- const XMLObject& xmlObject
- ) const
-{
- // Implementation of ADFS profile.
- m_log.debug("processing message against ADFS Passive Requester profile");
-
- // With ADFS, all the security comes from the assertion, which is two levels down in the message.
-
- const ElementProxy* response = dynamic_cast<const ElementProxy*>(&xmlObject);
- if (!response || !response->hasChildren())
- throw FatalProfileException("Incoming message was not of the proper type or contains no security token.");
-
- const Assertion* token = nullptr;
- for (vector<XMLObject*>::const_iterator xo = response->getUnknownXMLObjects().begin(); xo != response->getUnknownXMLObjects().end(); ++xo) {
- // Look for the RequestedSecurityToken element.
- if (XMLString::equals((*xo)->getElementQName().getLocalPart(), RequestedSecurityToken)) {
- response = dynamic_cast<const ElementProxy*>(*xo);
- if (!response || !response->hasChildren())
- throw FatalProfileException("Token wrapper element did not contain a security token.");
- token = dynamic_cast<const Assertion*>(response->getUnknownXMLObjects().front());
- if (!token || !token->getSignature())
- throw FatalProfileException("Incoming message did not contain a signed SAML assertion.");
- break;
- }
- }
-
- // Extract message and issuer details from assertion.
- extractMessageDetails(*token, m_protocol.get(), policy);
-
- // Populate recipient as audience.
- const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
- policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
-
- // Run the policy over the assertion. Handles replay, freshness, and
- // signature verification, assuming the relevant rules are configured,
- // along with condition enforcement.
- policy.evaluate(*token, &httpRequest);
-
- // If no security is in place now, we kick it.
- if (!policy.isAuthenticated())
- throw SecurityPolicyException("Unable to establish security of incoming assertion.");
-
- const saml1::NameIdentifier* saml1name=nullptr;
- const saml1::AuthenticationStatement* saml1statement=nullptr;
- const saml2::NameID* saml2name=nullptr;
- const saml2::AuthnStatement* saml2statement=nullptr;
- const XMLCh* authMethod=nullptr;
- const XMLCh* authInstant=nullptr;
- time_t now = time(nullptr), sessionExp = 0;
- const PropertySet* sessionProps = application.getPropertySet("Sessions");
-
- const saml1::Assertion* saml1token = dynamic_cast<const saml1::Assertion*>(token);
- if (saml1token) {
- // Now do profile validation to ensure we can use it for SSO.
- if (!saml1token->getConditions() || !saml1token->getConditions()->getNotBefore() || !saml1token->getConditions()->getNotOnOrAfter())
- throw FatalProfileException("Assertion did not contain time conditions.");
- else if (saml1token->getAuthenticationStatements().empty())
- throw FatalProfileException("Assertion did not contain an authentication statement.");
-
- // authnskew allows rejection of SSO if AuthnInstant is too old.
- pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
-
- saml1statement = saml1token->getAuthenticationStatements().front();
- if (saml1statement->getAuthenticationInstant()) {
- if (saml1statement->getAuthenticationInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
- throw FatalProfileException("The login time at your identity provider was future-dated.");
- }
- else if (authnskew.first && authnskew.second && saml1statement->getAuthenticationInstantEpoch() <= now &&
- (now - saml1statement->getAuthenticationInstantEpoch() > authnskew.second)) {
- throw FatalProfileException("The gap between now and the time you logged into your identity provider exceeds the allowed limit.");
- }
- }
- else if (authnskew.first && authnskew.second) {
- throw FatalProfileException("Your identity provider did not supply a time of login, violating local policy.");
- }
-
- // Address checking.
- saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
- if (locality && locality->getIPAddress()) {
- auto_ptr_char ip(locality->getIPAddress());
- checkAddress(application, httpRequest, ip.get());
- }
-
- saml1name = saml1statement->getSubject()->getNameIdentifier();
- authMethod = saml1statement->getAuthenticationMethod();
- if (saml1statement->getAuthenticationInstant())
- authInstant = saml1statement->getAuthenticationInstant()->getRawData();
-
- // Session expiration.
- pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
- if (!lifetime.first || lifetime.second == 0)
- lifetime.second = 28800;
- sessionExp = now + lifetime.second;
- }
- else {
- const saml2::Assertion* saml2token = dynamic_cast<const saml2::Assertion*>(token);
- if (!saml2token)
- throw FatalProfileException("Incoming message did not contain a recognized type of SAML assertion.");
-
- // Now do profile validation to ensure we can use it for SSO.
- if (!saml2token->getConditions() || !saml2token->getConditions()->getNotBefore() || !saml2token->getConditions()->getNotOnOrAfter())
- throw FatalProfileException("Assertion did not contain time conditions.");
- else if (saml2token->getAuthnStatements().empty())
- throw FatalProfileException("Assertion did not contain an authentication statement.");
-
- // authnskew allows rejection of SSO if AuthnInstant is too old.
- pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
-
- saml2statement = saml2token->getAuthnStatements().front();
- if (authnskew.first && authnskew.second &&
- saml2statement->getAuthnInstant() && (now - saml2statement->getAuthnInstantEpoch() > authnskew.second))
- throw FatalProfileException("The gap between now and the time you logged into your identity provider exceeds the limit.");
-
- // Address checking.
- saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
- if (locality && locality->getAddress()) {
- auto_ptr_char ip(locality->getAddress());
- checkAddress(application, httpRequest, ip.get());
- }
-
- saml2name = saml2token->getSubject() ? saml2token->getSubject()->getNameID() : nullptr;
- if (saml2statement->getAuthnContext() && saml2statement->getAuthnContext()->getAuthnContextClassRef())
- authMethod = saml2statement->getAuthnContext()->getAuthnContextClassRef()->getReference();
- if (saml2statement->getAuthnInstant())
- authInstant = saml2statement->getAuthnInstant()->getRawData();
-
- // Session expiration for SAML 2.0 is jointly IdP- and SP-driven.
- sessionExp = saml2statement->getSessionNotOnOrAfter() ? saml2statement->getSessionNotOnOrAfterEpoch() : 0;
- pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
- if (!lifetime.first || lifetime.second == 0)
- lifetime.second = 28800;
- if (sessionExp == 0)
- sessionExp = now + lifetime.second; // IdP says nothing, calulate based on SP.
- else
- sessionExp = min(sessionExp, now + lifetime.second); // Use the lowest.
- }
-
- m_log.debug("ADFS profile processing completed successfully");
-
- // We've successfully "accepted" the SSO token.
- // To complete processing, we need to extract and resolve attributes and then create the session.
-
- // Normalize a SAML 1.x NameIdentifier...
- scoped_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
- if (saml1name) {
- nameid->setName(saml1name->getName());
- nameid->setFormat(saml1name->getFormat());
- nameid->setNameQualifier(saml1name->getNameQualifier());
- }
-
- // The context will handle deleting attributes and new tokens.
- vector<const Assertion*> tokens(1,token);
- scoped_ptr<ResolutionContext> ctx(
- resolveAttributes(
- application,
- &httpRequest,
- policy.getIssuerMetadata(),
- m_protocol.get(),
- nullptr,
- saml1name,
- saml1statement,
- (saml1name ? nameid.get() : saml2name),
- saml2statement,
- authMethod,
- nullptr,
- &tokens
- )
- );
-
- if (ctx.get()) {
- // Copy over any new tokens, but leave them in the context for cleanup.
- tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
- }
-
- string session_id;
- application.getServiceProvider().getSessionCache()->insert(
- session_id,
- application,
- httpRequest,
- httpResponse,
- sessionExp,
- entity,
- m_protocol.get(),
- (saml1name ? nameid.get() : saml2name),
- authInstant,
- nullptr,
- authMethod,
- nullptr,
- &tokens,
- ctx ? &ctx->getResolvedAttributes() : nullptr
- );
-
- scoped_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
- if (login_event) {
- login_event->m_sessionID = session_id.c_str();
- login_event->m_peer = entity;
- login_event->m_protocol = WSFED_NS;
- login_event->m_binding = WSFED_NS;
- login_event->m_saml1AuthnStatement = saml1statement;
- login_event->m_nameID = (saml1name ? nameid.get() : saml2name);
- login_event->m_saml2AuthnStatement = saml2statement;
- if (ctx)
- login_event->m_attributes = &ctx->getResolvedAttributes();
- application.getServiceProvider().getTransactionLog()->write(*login_event);
- }
-}
-
-#endif
-
-pair<bool,long> ADFSLogoutInitiator::run(SPRequest& request, bool) const
-{
- // Normally we'd do notifications and session clearage here, but ADFS logout
- // is missing the needed request/response features, so we have to rely on
- // the IdP half to notify us back about the logout and do the work there.
- // Basically we have no way to tell in the Logout receiving handler whether
- // we initiated the logout or not.
-
- Session* session = nullptr;
- try {
- session = request.getSession(false, true, false); // don't cache it and ignore all checks
- if (!session)
- return make_pair(false, 0L);
-
- // We only handle ADFS sessions.
- if (!XMLString::equals(session->getProtocol(), WSFED_NS) || !session->getEntityID()) {
- session->unlock();
- return make_pair(false, 0L);
- }
- }
- catch (std::exception& ex) {
- m_log.error("error accessing current session: %s", ex.what());
- return make_pair(false,0L);
- }
-
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- // When out of process, we run natively.
- return doRequest(request.getApplication(), request, request, session);
- }
- else {
- // When not out of process, we remote the request.
- session->unlock();
- vector<string> headers(1,"Cookie");
- headers.push_back("User-Agent");
- DDF out,in = wrap(request, &headers);
- DDFJanitor jin(in), jout(out);
- out = send(request, in);
- return unwrap(request, out);
- }
-}
-
-void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
-{
-#ifndef SHIBSP_LITE
- // Defer to base class for notifications
- if (in["notify"].integer() == 1)
- return LogoutHandler::receive(in, out);
-
- // Find application.
- const char* aid = in["application_id"].string();
- const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
- if (!app) {
- // Something's horribly wrong.
- m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
- throw ConfigurationException("Unable to locate application for logout, deleted?");
- }
-
- // Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(*app, in));
-
- // Set up a response shim.
- DDF ret(nullptr);
- DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
-
- Session* session = nullptr;
- try {
- session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
- }
- catch (std::exception& ex) {
- m_log.error("error accessing current session: %s", ex.what());
- }
-
- // With no session, we just skip the request and let it fall through to an empty struct return.
- if (session) {
- if (session->getEntityID()) {
- // Since we're remoted, the result should either be a throw, which we pass on,
- // a false/0 return, which we just return as an empty structure, or a response/redirect,
- // which we capture in the facade and send back.
- doRequest(*app, *req, *resp, session);
- }
- else {
- m_log.error("no issuing entityID found in session");
- time_t revocationExp = session->getExpiration();
- session->unlock();
- app->getServiceProvider().getSessionCache()->remove(*app, *req, resp.get(), revocationExp);
- }
- }
- out << ret;
-#else
- throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
-#endif
-}
-
-pair<bool,long> ADFSLogoutInitiator::doRequest(
- const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session
- ) const
-{
- Locker sessionLocker(session, false);
-
- // Do back channel notification.
- vector<string> sessions(1, session->getID());
- if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
-#ifndef SHIBSP_LITE
- scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
- if (logout_event) {
- logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
- application.getServiceProvider().getTransactionLog()->write(*logout_event);
- }
-#endif
- time_t revocationExp = session->getExpiration();
- sessionLocker.assign();
- session = nullptr;
- application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse, revocationExp);
- return sendLogoutPage(application, httpRequest, httpResponse, "partial");
- }
-
-#ifndef SHIBSP_LITE
- pair<bool,long> ret = make_pair(false, 0L);
-
- try {
- // With a session in hand, we can create a request message, if we can find a compatible endpoint.
- MetadataProvider* m = application.getMetadataProvider();
- Locker metadataLocker(m);
- MetadataProviderCriteria mc(application, session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
- pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
- if (!entity.first) {
- throw MetadataException(
- "Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", session->getEntityID())
- );
- }
- else if (!entity.second) {
- throw MetadataException(
- "Unable to locate ADFS IdP role for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID())
- );
- }
-
- const EndpointType* ep = EndpointManager<SingleLogoutService>(
- dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleLogoutServices()
- ).getByBinding(m_binding.get());
- if (!ep) {
- throw MetadataException(
- "Unable to locate ADFS single logout service for identity provider ($entityID).",
- namedparams(1, "entityID", session->getEntityID())
- );
- }
-
- const char* returnloc = httpRequest.getParameter("return");
- if (returnloc)
- application.limitRedirect(httpRequest, returnloc);
-
- // Log the request.
- scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
- if (logout_event) {
- logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_UNKNOWN;
- application.getServiceProvider().getTransactionLog()->write(*logout_event);
- }
-
- auto_ptr_char dest(ep->getLocation());
- string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "wa=wsignout1.0";
- if (returnloc) {
- req += "&wreply=";
- if (*returnloc == '/') {
- string s(returnloc);
- httpRequest.absolutize(s);
- req += XMLToolingConfig::getConfig().getURLEncoder()->encode(s.c_str());
- }
- else {
- req += XMLToolingConfig::getConfig().getURLEncoder()->encode(returnloc);
- }
- }
- ret.second = httpResponse.sendRedirect(req.c_str());
- ret.first = true;
-
- if (session) {
- time_t revocationExp = session->getExpiration();
- sessionLocker.assign();
- session = nullptr;
- application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse, revocationExp);
- }
- }
- catch (const MetadataException& mex) {
- // Less noise for IdPs that don't support logout
- m_log.info("unable to issue ADFS logout request: %s", mex.what());
- }
- catch (const std::exception& ex) {
- m_log.error("error issuing ADFS logout request: %s", ex.what());
- }
-
- return ret;
-#else
- throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
-#endif
-}
-
-pair<bool,long> ADFSLogout::run(SPRequest& request, bool isHandler) const
-{
- // Defer to base class for front-channel loop first.
- // This won't initiate the loop, only continue/end it.
- pair<bool,long> ret = LogoutHandler::run(request, isHandler);
- if (ret.first)
- return ret;
-
- // wa parameter indicates the "action" to perform
- bool returning = false;
- const char* param = request.getParameter("wa");
- if (param) {
- if (!strcmp(param, "wsignin1.0"))
- return m_login.run(request, isHandler);
- else if (strcmp(param, "wsignout1.0") && strcmp(param, "wsignoutcleanup1.0"))
- throw FatalProfileException("Unsupported WS-Federation action parameter ($1).", params(1, param));
- }
- else if (strcmp(request.getMethod(),"GET") || !request.getParameter("notifying"))
- throw FatalProfileException("Unsupported request to ADFS protocol endpoint.");
- else
- returning = true;
-
- param = request.getParameter("wreply");
- const Application& app = request.getApplication();
-
- if (!returning) {
- // Pass control to the first front channel notification point, if any.
- map<string,string> parammap;
- if (param)
- parammap["wreply"] = param;
- pair<bool,long> result = notifyFrontChannel(app, request, request, ¶mmap);
- if (result.first)
- return result;
- }
-
- // Best effort on back channel and to remove the user agent's session.
- string session_id = app.getServiceProvider().getSessionCache()->active(app, request);
- if (!session_id.empty()) {
- vector<string> sessions(1,session_id);
- notifyBackChannel(app, request.getRequestURL(), sessions, false);
- try {
- app.getServiceProvider().getSessionCache()->remove(app, request, &request);
- }
- catch (const std::exception& ex) {
- m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
- }
- }
-
- if (param) {
- if (*param == '/') {
- string p(param);
- request.absolutize(p);
- return make_pair(true, request.sendRedirect(p.c_str()));
- }
- else {
- app.limitRedirect(request, param);
- return make_pair(true, request.sendRedirect(param));
- }
- }
- return sendLogoutPage(app, request, request, "global");
-}
diff --git a/adfs/adfs.rc b/adfs/adfs.rc
deleted file mode 100644
index 9dfb6027..00000000
--- a/adfs/adfs.rc
+++ /dev/null
@@ -1,109 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"
-#ifdef SHIBSP_LITE
- VALUE "InternalName", "adfs-lite\0"
-#else
- VALUE "InternalName", "adfs\0"
-#endif
-#ifdef SHIBSP_LITE
- VALUE "OriginalFilename", "adfs-lite.so\0"
-#else
- VALUE "OriginalFilename", "adfs.so\0"
-#endif
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/adfs/resource.h b/adfs/resource.h
deleted file mode 100644
index 213fc9a2..00000000
--- a/adfs/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{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/configure.ac b/configure.ac
index 1cfd7511..112b94d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,24 +1,11 @@
AC_PREREQ([2.50])
-AC_INIT([shibboleth],[3.5.0],[https://shibboleth.atlassian.net/jira],[shibboleth-sp])
+AC_INIT([shibboleth],[4.0.0],[https://shibboleth.atlassian.net/jira],[shibboleth-sp])
AC_CONFIG_SRCDIR(shibsp)
AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(m4)
AM_INIT_AUTOMAKE
PKG_INSTALLDIR
-# Docygen features
-DX_HTML_FEATURE(ON)
-DX_DOT_FEATURE(ON)
-DX_CHM_FEATURE(OFF)
-DX_CHI_FEATURE(OFF)
-DX_MAN_FEATURE(OFF)
-DX_RTF_FEATURE(OFF)
-DX_XML_FEATURE(OFF)
-DX_PDF_FEATURE(OFF)
-DX_PS_FEATURE(OFF)
-DX_INIT_DOXYGEN(shibboleth, doxygen.cfg, doc/api)
-DX_INCLUDE=
-
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],[Produce debug variant (Default = no)]),
enable_debug=$enableval, enable_debug=no)
@@ -29,15 +16,11 @@ if test "$enable_debug" = "yes" ; then
fi
AC_CONFIG_HEADERS([config.h shibsp/config_pub.h])
-AC_CONFIG_FILES([shibsp.pc shibsp-lite.pc shibboleth.spec])
+AC_CONFIG_FILES([shibsp.pc shibsp-lite.pc])
AC_PROG_CC([gcc gcc3 cc])
AC_PROG_CXX([g++ g++3 c++ CC])
-
-if test "$GCC" = "yes" ; then
- AM_CFLAGS="$AM_CFLAGS -Wall -W"
- AM_CXXFLAGS="$AM_CXXFLAGS -Wall -W"
-fi
+AX_CXX_COMPILE_STDCXX([11])
AC_SUBST([AM_CFLAGS])
AC_SUBST([AM_CXXFLAGS])
@@ -145,26 +128,9 @@ AX_PKG_CHECK_MODULES([opensaml],,[opensaml >= 3.1],,,
PKG_CHECK_VAR([OPENSAMLXMLDIR],[opensaml],[pkgxmldir])
# output the underlying makefiles
-WANT_SUBDIRS="doc schemas configs shibsp plugins shibd util"
+WANT_SUBDIRS="doc schemas configs shibsp util"
AC_CONFIG_FILES([Makefile doc/Makefile schemas/Makefile \
- configs/Makefile shibsp/Makefile plugins/Makefile \
- shibd/Makefile util/Makefile selinux/Makefile])
-
-## ADFS?
-AC_CONFIG_FILES([adfs/Makefile])
-AC_ARG_ENABLE([adfs],
- AS_HELP_STRING([--disable-adfs],[do not build the ADFS module]),
- [adfs_enabled=$enableval], [adfs_enabled=yes])
-if test "x$adfs_enabled" = "x" ; then
- adfs_enabled=yes
-fi
-AC_MSG_CHECKING(whether to build the ADFS module)
-if test "$adfs_enabled" = "no" ; then
- AC_MSG_RESULT(no)
-else
- AC_MSG_RESULT(yes)
- WANT_SUBDIRS="$WANT_SUBDIRS adfs"
-fi
+ configs/Makefile shibsp/Makefile util/Makefile])
## systemd
dnl Systemd will be disabled by default and requires you to run configure with
@@ -177,50 +143,6 @@ AC_ARG_ENABLE(systemd,
# sd_notify() is always present, no need to check for it:
AC_DEFINE([HAVE_SD_NOTIFY],[1],[Define to 1 if you have the sd_notify function.])])])
-#
-# Build NSAPI module?
-#
-AC_MSG_CHECKING(for NSAPI module option)
-AC_ARG_WITH(nsapi,
- AS_HELP_STRING([--with-nsapi=DIR],[Build NSAPI module for Netscape/iPlanet/SunONE]),
- [WANT_NSAPI=$withval],[WANT_NSAPI=no])
-AC_MSG_RESULT($WANT_NSAPI)
-
-if test "$WANT_NSAPI" != "no"; then
- if test ! -d $WANT_NSAPI/bin ; then
- AC_MSG_ERROR([Please specify the path to the root of your Netscape/iPlanet/SunONE server using --with-nsapi=DIR])
- fi
- AC_MSG_CHECKING(for NSAPI include files)
- if test -d $WANT_NSAPI/include ; then
- NSAPI_INCLUDE=$WANT_NSAPI/include
- AC_MSG_RESULT(Netscape-Enterprise 3.x style)
- AC_CHECK_HEADERS([$NSAPI_INCLUDE/nsapi.h],,,[#define XP_UNIX])
- NSAPI_INCLUDE="$NSAPI_INC_DIR -I$NSAPI_INCLUDE"
- fi
- if test -d $WANT_NSAPI/plugins/include ; then
- test -n "$NSAPI_INCLUDE" && NSAPI_INC_DIR="-I$NSAPI_INCLUDE"
- NSAPI_INCLUDE="$WANT_NSAPI/plugins/include"
- AC_MSG_RESULT(iPlanet 4.x / SunONE 6.x style)
- AC_CHECK_HEADERS([$NSAPI_INCLUDE/nsapi.h],,,[#define XP_UNIX])
- NSAPI_INCLUDE="$NSAPI_INC_DIR -I$NSAPI_INCLUDE"
- fi
- if test "$NSAPI_INCLUDE" = ""; then
- AC_MSG_ERROR([Please check you have nsapi.h in either $WANT_NSAPI/include or $WANT_NSAPI/plugins/include])
- fi
-fi
-
-AC_SUBST(NSAPI_INCLUDE)
-
-# always output the Makefile, even if you don't use it
-AC_CONFIG_FILES([nsapi_shib/Makefile])
-AM_CONDITIONAL(BUILD_NSAPI,test ! "$WANT_NSAPI" = "no")
-
-# add the NSAPI module to the list of wanted subdirs..
-if test ! "$WANT_NSAPI" = "no" ; then
- WANT_SUBDIRS="$WANT_SUBDIRS nsapi_shib"
-fi
-
-
#
# Build FastCGI support?
#
@@ -262,51 +184,6 @@ if test ! "$WANT_FASTCGI" = "no" ; then
WANT_SUBDIRS="$WANT_SUBDIRS fastcgi"
fi
-#
-# Build Memcached support?
-#
-AC_MSG_CHECKING(for Memcached support)
-AC_ARG_WITH(memcached,
- AS_HELP_STRING([--with-memcached=DIR],[Build Memcached support]),
- [WANT_MEMCACHED=$withval],[WANT_MEMCACHED=no])
-AC_MSG_RESULT($WANT_MEMCACHED)
-
-if test "$WANT_MEMCACHED" != "no"; then
-
- if test "$WANT_MEMCACHED" != "yes"; then
- if test x_$WANT_MEMCACHED != x_/usr; then
- MEMCACHED_INCLUDE="-I$WANT_MEMCACHED/include"
- MEMCACHED_LDFLAGS="-L$WANT_MEMCACHED/lib"
- fi
- fi
-
- # save and append master flags
- save_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$MEMCACHED_INCLUDE $CPPFLAGS"
-
- AC_CHECK_HEADER([libmemcached/memcached.h],,
- AC_MSG_ERROR([unable to find Memcached header files]))
- AC_CHECK_DECL([memcached_last_error_message],
- [AC_DEFINE([HAVE_MEMCACHED_LAST_ERROR_MESSAGE],[1],[Define to 1 if libmemcached supports error handling function.])],,
- [#include <libmemcached/memcached.h>])
- MEMCACHED_LIBS="-lmemcached"
-
- # restore standard flags
- CPPFLAGS="$save_CPPFLAGS"
-fi
-
-AC_SUBST(MEMCACHED_INCLUDE)
-AC_SUBST(MEMCACHED_LDFLAGS)
-AC_SUBST(MEMCACHED_LIBS)
-
-# always output the Makefile, even if you don't use it
-AC_CONFIG_FILES([memcache-store/Makefile])
-AM_CONDITIONAL(BUILD_MEMCACHED,test ! "$WANT_MEMCACHED" = "no")
-
-if test ! "$WANT_MEMCACHED" = "no" ; then
- WANT_SUBDIRS="$WANT_SUBDIRS memcache-store"
-fi
-
#
# If no --enable-apache-xx specified
@@ -809,101 +686,6 @@ if test "$WANT_APACHE_13" = "yes" || test "$WANT_APACHE_20" = "yes" || test "$WA
fi
-#
-# Implement the checks of the ODBC Storage Service
-#
-# 1) Assume the user wants ODBC; if it's not found then just continue without
-# 2) If the user specifically requested odbc, look for it and ERROR if not found
-# 3) If the user specifically requested no odbc, don't build it.
-#
-
-AC_CONFIG_FILES([odbc-store/Makefile])
-
-# determine whether we should enable the odbc ccache
-AC_ARG_ENABLE([odbc],
- AS_HELP_STRING([--disable-odbc],[disable the ODBC Storage Service]),
- [odbc_enabled=$enableval], [odbc_enabled=default])
-if test "x$odbc_enabled" = "x" ; then
- odbc_enabled=yes
-fi
-
-# Are we trying to build ODBC?
-AC_MSG_CHECKING(whether to build the ODBC storage service)
-if test "$odbc_enabled" = "yes" ; then
- build_odbc=yes
- AC_MSG_RESULT(yes)
-elif test "$odbc_enabled" = "default" ; then
- build_odbc=yes
- AC_MSG_RESULT([yes, if it can be found])
-else
- build_odbc=no
- AC_MSG_RESULT(no)
-fi
-
-# If we're trying to build ODBC, try to find the odbc_config program.
-if test "$build_odbc" = "yes" ; then
- odbc_dir=""
- AC_ARG_WITH(odbc,
- AS_HELP_STRING([--with-odbc=PATH],[directory where odbc is installed]),
- [if test "$with_odbc" = no ; then
- AC_MSG_ERROR([Try running --disable-odbc instead.])
- elif test "$with_odbc" != yes ; then
- odbc_dir="$with_odbc/bin"
- if test "$with_odbc" != /usr ; then
- ODBC_CFLAGS="-I$with_odbc/include"
- ODBC_LIBS="-L$with_odbc/lib"
- fi
- fi])
-
- AC_PATH_PROG(ODBC_CONFIG, odbc_config, no, $odbc_dir $PATH )
- if test "$ODBC_CONFIG" = no ; then
- AC_MSG_WARN([Cannot find odbc_config, will try to guess settings.])
- ODBC_LIBS="$ODBC_LIBS -lodbc"
- else
- ODBC_CFLAGS=`$ODBC_CONFIG --cflags`
- ODBC_LIBS=`$ODBC_CONFIG --libs`
- fi
-
- save_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $ODBC_CFLAGS"
-
- AC_CHECK_HEADER([sql.h], [have_sql_h=yes], [have_sql_h=no])
- if test "$have_sql_h" = no -a "$odbc_enabled" = "yes" ; then
- AC_MSG_ERROR(unable to find ODBC header files)
- fi
-
- if test "$have_sql_h" = yes ; then
- save_LIBS="$LIBS"
- LIBS="$LIBS $ODBC_LIBS"
- AC_MSG_CHECKING(if we can link againt ODBC)
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[#include <sql.h>
- #include <sqlext.h>
- #include <stdio.h>]],
- [[SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0)]])],
- [have_odbc_libs=yes],[have_odbc_libs=no])
- LIBS="$save_LIBS"
- if test "$have_odbc_libs" = no ; then
- if test "$odbc_enabled" = "yes" ; then
- AC_MSG_ERROR([unable to link with ODBC Library])
- else
- AC_MSG_RESULT([no, skipping ODBC])
- fi
- fi
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
-fi
-
-# if have_odbc_libs=yes then go ahead with building ODBC
-if test "$have_odbc_libs" = yes ; then
- # this AC_MSG_RESULT is from above!
- AC_MSG_RESULT(yes)
- WANT_SUBDIRS="$WANT_SUBDIRS odbc-store"
- AC_SUBST(ODBC_CFLAGS)
- AC_SUBST(ODBC_LIBS)
-fi
-
AC_ARG_WITH([gssapi],
[AS_HELP_STRING([--with-gssapi],[include GSSAPI support])],,[with_gssapi=check])
AS_IF([test "x$with_gssapi" != xno],
diff --git a/doc/api/.gitkeep b/doc/api/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/doxygen.am b/doxygen.am
deleted file mode 100644
index a03a6282..00000000
--- a/doxygen.am
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright (C) 2004 Oren Ben-Kiki
-# This file is distributed under the same terms as the Automake macro files.
-
-# Generate automatic documentation using Doxygen. Goals and variables values
-# are controlled by the various DX_COND_??? conditionals set by autoconf.
-#
-# The provided goals are:
-# doxygen-doc: Generate all doxygen documentation.
-# doxygen-run: Run doxygen, which will generate some of the documentation
-# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
-# processing required for the rest of it (PS, PDF, and some MAN).
-# doxygen-man: Rename some doxygen generated man pages.
-# doxygen-ps: Generate doxygen PostScript documentation.
-# doxygen-pdf: Generate doxygen PDF documentation.
-#
-# Note that by default these are not integrated into the automake goals. If
-# doxygen is used to generate man pages, you can achieve this integration by
-# setting man3_MANS to the list of man pages generated and then adding the
-# dependency:
-#
-# $(man3_MANS): doxygen-doc
-#
-# This will cause make to run doxygen and generate all the documentation.
-#
-# The following variable is intended for use in Makefile.am:
-#
-# DX_CLEANFILES = everything to clean.
-#
-# This is usually added to MOSTLYCLEANFILES.
-
-## --------------------------------- ##
-## Format-independent Doxygen rules. ##
-## --------------------------------- ##
-
-if DX_COND_doc
-
-## ------------------------------- ##
-## Rules specific for HTML output. ##
-## ------------------------------- ##
-
-if DX_COND_html
-
-DX_CLEAN_HTML = @DX_DOCDIR@/html
-
-endif DX_COND_html
-
-## ------------------------------ ##
-## Rules specific for CHM output. ##
-## ------------------------------ ##
-
-if DX_COND_chm
-
-DX_CLEAN_CHM = @DX_DOCDIR@/chm
-
-if DX_COND_chi
-
-DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE_NAME at .chi
-
-endif DX_COND_chi
-
-endif DX_COND_chm
-
-## ------------------------------ ##
-## Rules specific for MAN output. ##
-## ------------------------------ ##
-
-if DX_COND_man
-
-DX_CLEAN_MAN = @DX_DOCDIR@/man
-
-endif DX_COND_man
-
-## ------------------------------ ##
-## Rules specific for RTF output. ##
-## ------------------------------ ##
-
-if DX_COND_rtf
-
-DX_CLEAN_RTF = @DX_DOCDIR@/rtf
-
-endif DX_COND_rtf
-
-## ------------------------------ ##
-## Rules specific for XML output. ##
-## ------------------------------ ##
-
-if DX_COND_xml
-
-DX_CLEAN_XML = @DX_DOCDIR@/xml
-
-endif DX_COND_xml
-
-## ----------------------------- ##
-## Rules specific for PS output. ##
-## ----------------------------- ##
-
-if DX_COND_ps
-
-DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE_NAME at .ps
-
-DX_PS_GOAL = doxygen-ps
-
-doxygen-ps: @DX_DOCDIR@/@PACKAGE_NAME at .ps
-
- at DX_DOCDIR@/@PACKAGE_NAME at .ps: @DX_DOCDIR@/@PACKAGE_NAME at .tag
- cd @DX_DOCDIR@/latex; \
- rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
- $(DX_LATEX) refman.tex; \
- $(MAKEINDEX_PATH) refman.idx; \
- $(DX_LATEX) refman.tex; \
- countdown=5; \
- while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
- refman.log > /dev/null 2>&1 \
- && test $$countdown -gt 0; do \
- $(DX_LATEX) refman.tex; \
- countdown=`expr $$countdown - 1`; \
- done; \
- $(DX_DVIPS) -o ../@PACKAGE_NAME at .ps refman.dvi
-
-endif DX_COND_ps
-
-## ------------------------------ ##
-## Rules specific for PDF output. ##
-## ------------------------------ ##
-
-if DX_COND_pdf
-
-DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE_NAME at .pdf
-
-DX_PDF_GOAL = doxygen-pdf
-
-doxygen-pdf: @DX_DOCDIR@/@PACKAGE_NAME at .pdf
-
- at DX_DOCDIR@/@PACKAGE_NAME at .pdf: @DX_DOCDIR@/@PACKAGE_NAME at .tag
- cd @DX_DOCDIR@/latex; \
- rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
- $(DX_PDFLATEX) refman.tex; \
- $(DX_MAKEINDEX) refman.idx; \
- $(DX_PDFLATEX) refman.tex; \
- countdown=5; \
- while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
- refman.log > /dev/null 2>&1 \
- && test $$countdown -gt 0; do \
- $(DX_PDFLATEX) refman.tex; \
- countdown=`expr $$countdown - 1`; \
- done; \
- mv refman.pdf ../@PACKAGE_NAME at .pdf
-
-endif DX_COND_pdf
-
-## ------------------------------------------------- ##
-## Rules specific for LaTeX (shared for PS and PDF). ##
-## ------------------------------------------------- ##
-
-if DX_COND_latex
-
-DX_CLEAN_LATEX = @DX_DOCDIR@/latex
-
-endif DX_COND_latex
-
-.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-doxygen-run: @DX_DOCDIR@/@PACKAGE_NAME at .tag
-
-doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
- at DX_DOCDIR@/@PACKAGE_NAME at .tag: $(DX_CONFIG) $(pkginclude_HEADERS)
- rm -rf @DX_DOCDIR@
- $(DX_ENV) DX_INCLUDE=$(DX_INCLUDE) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
-
-DX_CLEANFILES = \
- @DX_DOCDIR@/@PACKAGE_NAME at .tag \
- -r \
- $(DX_CLEAN_HTML) \
- $(DX_CLEAN_CHM) \
- $(DX_CLEAN_CHI) \
- $(DX_CLEAN_MAN) \
- $(DX_CLEAN_RTF) \
- $(DX_CLEAN_XML) \
- $(DX_CLEAN_PS) \
- $(DX_CLEAN_PDF) \
- $(DX_CLEAN_LATEX)
-
-endif DX_COND_doc
diff --git a/doxygen.cfg b/doxygen.cfg
deleted file mode 100644
index 1c136a61..00000000
--- a/doxygen.cfg
+++ /dev/null
@@ -1,255 +0,0 @@
-# Doxyfile 1.4.6
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-PROJECT_NAME = $(PROJECT)-$(VERSION)
-PROJECT_NUMBER =
-OUTPUT_DIRECTORY = $(DOCDIR)
-CREATE_SUBDIRS = NO
-OUTPUT_LANGUAGE = English
-USE_WINDOWS_ENCODING = YES
-BRIEF_MEMBER_DESC = YES
-REPEAT_BRIEF = YES
-ABBREVIATE_BRIEF = "The $name class" \
- "The $name widget" \
- "The $name file" \
- is \
- provides \
- specifies \
- contains \
- represents \
- a \
- an \
- the
-ALWAYS_DETAILED_SEC = NO
-INLINE_INHERITED_MEMB = NO
-FULL_PATH_NAMES = YES
-STRIP_FROM_PATH = $(SRCDIR)
-STRIP_FROM_INC_PATH = $(SRCDIR)
-SHORT_NAMES = YES
-JAVADOC_AUTOBRIEF = YES
-MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP = NO
-INHERIT_DOCS = YES
-SEPARATE_MEMBER_PAGES = NO
-TAB_SIZE = 4
-ALIASES =
-OPTIMIZE_OUTPUT_FOR_C = NO
-OPTIMIZE_OUTPUT_JAVA = NO
-BUILTIN_STL_SUPPORT = YES
-DISTRIBUTE_GROUP_DOC = NO
-SUBGROUPING = YES
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-EXTRACT_ALL = NO
-EXTRACT_PRIVATE = NO
-EXTRACT_STATIC = YES
-EXTRACT_LOCAL_CLASSES = YES
-EXTRACT_LOCAL_METHODS = NO
-HIDE_UNDOC_MEMBERS = NO
-HIDE_UNDOC_CLASSES = NO
-HIDE_FRIEND_COMPOUNDS = NO
-HIDE_IN_BODY_DOCS = NO
-INTERNAL_DOCS = NO
-CASE_SENSE_NAMES = NO
-HIDE_SCOPE_NAMES = NO
-SHOW_INCLUDE_FILES = YES
-INLINE_INFO = YES
-SORT_MEMBER_DOCS = YES
-SORT_BRIEF_DOCS = NO
-SORT_BY_SCOPE_NAME = NO
-GENERATE_TODOLIST = YES
-GENERATE_TESTLIST = YES
-GENERATE_BUGLIST = YES
-GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS =
-MAX_INITIALIZER_LINES = 30
-SHOW_USED_FILES = YES
-SHOW_DIRECTORIES = YES
-FILE_VERSION_FILTER =
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-QUIET = NO
-WARNINGS = YES
-WARN_IF_UNDOCUMENTED = YES
-WARN_IF_DOC_ERROR = YES
-WARN_NO_PARAMDOC = NO
-WARN_FORMAT = "$file:$line: $text"
-WARN_LOGFILE =
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-INPUT = $(SRCDIR)/shibsp
-FILE_PATTERNS = *.d \
- *.java \
- *.ii \
- *.ixx \
- *.ipp \
- *.i++ \
- *.inl \
- *.h \
- *.hh \
- *.hxx \
- *.hpp \
- *.h++ \
- *.idl \
- *.odl \
- *.cs \
- *.php \
- *.php3 \
- *.inc \
- *.m \
- *.mm \
- *.dox \
- *.py
-RECURSIVE = YES
-EXCLUDE =
-EXCLUDE_SYMLINKS = NO
-EXCLUDE_PATTERNS =
-EXAMPLE_PATH = $(SRCDIR)/shibsp
-EXAMPLE_PATTERNS =
-EXAMPLE_RECURSIVE = NO
-IMAGE_PATH =
-INPUT_FILTER =
-FILTER_PATTERNS =
-FILTER_SOURCE_FILES = NO
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-SOURCE_BROWSER = NO
-INLINE_SOURCES = NO
-STRIP_CODE_COMMENTS = YES
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION = NO
-USE_HTAGS = NO
-VERBATIM_HEADERS = NO
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX = NO
-COLS_IN_ALPHA_INDEX = 5
-IGNORE_PREFIX =
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-GENERATE_HTML = $(GENERATE_HTML)
-HTML_OUTPUT = html
-HTML_FILE_EXTENSION = .html
-HTML_HEADER =
-HTML_FOOTER =
-HTML_STYLESHEET =
-HTML_ALIGN_MEMBERS = YES
-GENERATE_HTMLHELP = $(GENERATE_CHM)
-CHM_FILE = ../$(PROJECT).chm
-HHC_LOCATION = $(HHC_PATH)
-GENERATE_CHI = $(GENERATE_CHI)
-BINARY_TOC = NO
-TOC_EXPAND = NO
-DISABLE_INDEX = NO
-ENUM_VALUES_PER_LINE = 4
-GENERATE_TREEVIEW = YES
-TREEVIEW_WIDTH = 250
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-GENERATE_LATEX = $(GENERATE_LATEX)
-LATEX_OUTPUT = latex
-LATEX_CMD_NAME = latex
-MAKEINDEX_CMD_NAME = makeindex
-COMPACT_LATEX = NO
-PAPER_TYPE = $(PAPER_SIZE)
-EXTRA_PACKAGES =
-LATEX_HEADER =
-PDF_HYPERLINKS = NO
-USE_PDFLATEX = NO
-LATEX_BATCHMODE = YES
-LATEX_HIDE_INDICES = NO
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-GENERATE_RTF = $(GENERATE_RTF)
-RTF_OUTPUT = rtf
-COMPACT_RTF = NO
-RTF_HYPERLINKS = NO
-RTF_STYLESHEET_FILE =
-RTF_EXTENSIONS_FILE =
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-GENERATE_MAN = $(GENERATE_MAN)
-MAN_OUTPUT = man
-MAN_EXTENSION = .1
-MAN_LINKS = NO
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-GENERATE_XML = $(GENERATE_XML)
-XML_OUTPUT = xml
-XML_SCHEMA =
-XML_DTD =
-XML_PROGRAMLISTING = YES
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-GENERATE_AUTOGEN_DEF = NO
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-GENERATE_PERLMOD = NO
-PERLMOD_LATEX = NO
-PERLMOD_PRETTY = YES
-PERLMOD_MAKEVAR_PREFIX =
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING = YES
-MACRO_EXPANSION = YES
-EXPAND_ONLY_PREDEF = NO
-SEARCH_INCLUDES = YES
-INCLUDE_PATH = $(SRCDIR) $(DX_INCLUDE)
-INCLUDE_FILE_PATTERNS =
-PREDEFINED = _MSC_VER \
- DOXYGEN_SKIP
-EXPAND_AS_DEFINED =
-SKIP_FUNCTION_MACROS = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-TAGFILES =
-GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
-ALLEXTERNALS = NO
-EXTERNAL_GROUPS = YES
-PERL_PATH = $(PERL_PATH)
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-CLASS_DIAGRAMS = YES
-HIDE_UNDOC_RELATIONS = YES
-HAVE_DOT = $(HAVE_DOT)
-CLASS_GRAPH = YES
-COLLABORATION_GRAPH = YES
-GROUP_GRAPHS = YES
-UML_LOOK = NO
-TEMPLATE_RELATIONS = NO
-INCLUDE_GRAPH = YES
-INCLUDED_BY_GRAPH = YES
-CALL_GRAPH = NO
-GRAPHICAL_HIERARCHY = YES
-DIRECTORY_GRAPH = YES
-DOT_IMAGE_FORMAT = png
-DOT_PATH = $(DOT_PATH)
-DOTFILE_DIRS =
-MAX_DOT_GRAPH_WIDTH = 1024
-MAX_DOT_GRAPH_HEIGHT = 1024
-MAX_DOT_GRAPH_DEPTH = 1000
-DOT_TRANSPARENT = NO
-DOT_MULTI_TARGETS = NO
-GENERATE_LEGEND = YES
-DOT_CLEANUP = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-SEARCHENGINE = NO
diff --git a/isapi_shib/isapi_shib.cpp b/isapi_shib/isapi_shib.cpp
deleted file mode 100644
index adea5924..00000000
--- a/isapi_shib/isapi_shib.cpp
+++ /dev/null
@@ -1,1105 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-/**
- * isapi_shib.cpp
- *
- * Shibboleth ISAPI filter.
- */
-
-#define SHIBSP_LITE
-#include "config_win32.h"
-
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#define _CRT_SECURE_NO_DEPRECATE 1
-#define _CRT_RAND_S
-
-#include <shibsp/exceptions.h>
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-
-#include <set>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-#include <boost/lexical_cast.hpp>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xmltooling/logging.h>
-
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-using xmltooling::logging::Category;
-using xmltooling::logging::Priority;
-
-// globals
-namespace {
- 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);
- static const XMLCh name[] = UNICODE_LITERAL_4(n,a,m,e);
- static const XMLCh port[] = UNICODE_LITERAL_4(p,o,r,t);
- static const XMLCh sslport[] = UNICODE_LITERAL_7(s,s,l,p,o,r,t);
- static const XMLCh scheme[] = UNICODE_LITERAL_6(s,c,h,e,m,e);
- static const XMLCh id[] = UNICODE_LITERAL_2(i,d);
- static const XMLCh useHeaders[] = UNICODE_LITERAL_10(u, s, e, H, e, a, d, e, r, s);
- static const XMLCh useVariables[] = UNICODE_LITERAL_12(u, s, e, V, a, r, i, a, b, l, e, s);
- static const XMLCh Alias[] = UNICODE_LITERAL_5(A,l,i,a,s);
- static const XMLCh Site[] = UNICODE_LITERAL_4(S,i,t,e);
-
- struct site_t {
- site_t(const DOMElement* e)
- : m_name(XMLHelper::getAttrString(e, "", name)),
- m_scheme(XMLHelper::getAttrString(e, "", scheme)),
- m_port(XMLHelper::getAttrString(e, "", port)),
- m_sslport(XMLHelper::getAttrString(e, "", sslport))
- {
- e = XMLHelper::getFirstChildElement(e, Alias);
- while (e) {
- if (e->hasChildNodes()) {
- auto_ptr_char alias(XMLHelper::getTextContent(e));
- m_aliases.insert(alias.get());
- }
- e = XMLHelper::getNextSiblingElement(e, Alias);
- }
- }
- string m_scheme,m_port,m_sslport,m_name;
- set<string> m_aliases;
- };
-
- HINSTANCE g_hinstDLL;
- SPConfig* g_Config = nullptr;
- map<string,site_t> g_Sites;
- bool g_bNormalizeRequest = true;
- string g_unsetHeaderValue,g_spoofKey;
- bool g_checkSpoofing = true;
- bool g_catchAll = false;
- bool g_bSafeHeaderNames = false;
- vector<string> g_NoCerts;
-}
-
-void _my_invalid_parameter_handler(
- const wchar_t * expression,
- const wchar_t * function,
- const wchar_t * file,
- unsigned int line,
- uintptr_t pReserved
- )
-{
- return;
-}
-
-extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
-{
- if (fdwReason == DLL_PROCESS_ATTACH)
- g_hinstDLL = hinstDLL;
- return TRUE;
-}
-
-extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
-{
- if (!pVer)
- return FALSE;
-
- if (!g_Config) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").fatal("extension mode startup not possible, is the DLL loaded as a filter?");
- return FALSE;
- }
-
- pVer->dwExtensionVersion = HSE_VERSION;
- strncpy(pVer->lpszExtensionDesc, "Shibboleth ISAPI Extension", HSE_MAX_EXT_DLL_NAME_LEN-1);
- return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateExtension(DWORD)
-{
- return TRUE; // cleanup should happen when filter unloads
-}
-
-extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
-{
- Category& log = Category::getInstance(SHIBSP_LOGCAT ".ISAPI");
-
- if (!pVer)
- return FALSE;
- else if (g_Config) {
- log.warn("reentrant ISAPI filter initialization, ignoring...");
- return TRUE;
- }
-
- g_Config = &SPConfig::getConfig();
- g_Config->deprecation().warn("ISAPI extension is replaced by IIS 7+ module");
- g_Config->setFeatures(
- SPConfig::Listener |
- SPConfig::Caching |
- SPConfig::RequestMapping |
- SPConfig::InProcess |
- SPConfig::Logging |
- SPConfig::Handlers
- );
- if (!g_Config->init()) {
- g_Config = nullptr;
- log.fatal("ISAPI filter startup failed during library initialization, check native log for help");
- return FALSE;
- }
-
- try {
- if (!g_Config->instantiate(nullptr, true))
- throw runtime_error("unknown error");
- }
- catch (const std::exception& ex) {
- log.fatal("ISAPI filter startup failed: %s", ex.what());
- g_Config->term();
- g_Config=nullptr;
- return FALSE;
- }
-
- // Access implementation-specifics and site mappings.
- ServiceProvider* sp = g_Config->getServiceProvider();
- Locker locker(sp);
- const PropertySet* props = sp->getPropertySet("InProcess");
- if (props) {
- pair<bool,bool> flag = props->getBool("checkSpoofing");
- g_checkSpoofing = !flag.first || flag.second;
- flag = props->getBool("catchAll");
- g_catchAll = flag.first && flag.second;
-
- pair<bool,const char*> unsetValue = props->getString("unsetHeaderValue");
- if (unsetValue.first)
- g_unsetHeaderValue = unsetValue.second;
- if (g_checkSpoofing) {
- unsetValue = props->getString("spoofKey");
- if (unsetValue.first)
- g_spoofKey = unsetValue.second;
- else {
- _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
- unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
- if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
- _set_invalid_parameter_handler(old);
- g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
- lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
- }
- else {
- _set_invalid_parameter_handler(old);
- log.fatal("ISAPI filter failed to generate a random anti-spoofing key");
- locker.assign(); // pops lock on SP config
- g_Config->term();
- g_Config = nullptr;
- return FALSE;
- }
- }
- }
-
- props = props->getPropertySet("ISAPI");
- if (props) {
- flag = props->getBool("normalizeRequest");
- g_bNormalizeRequest = !flag.first || flag.second;
- flag = props->getBool("safeHeaderNames");
- g_bSafeHeaderNames = flag.first && flag.second;
- if (props->getString("useHeaders").first)
- log.warn("useHeaders attribute not supported by ISAPI filter, ignored");
- if (props->getString("useVariables").first)
- log.warn("useVariables attribute not supported by ISAPI filter, ignored");
-
- const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(), Site);
- while (child) {
- string id(XMLHelper::getAttrString(child, "", id));
- if (!id.empty()) {
- g_Sites.insert(make_pair(id, site_t(child)));
- if (!XMLHelper::getAttrString(child, "", useHeaders).empty())
- log.warn("useHeaders attribute not valid for this filter");
- if (!XMLHelper::getAttrString(child, "", useVariables).empty())
- log.warn("useVariables attribute not valid for this filter");
- }
- child = XMLHelper::getNextSiblingElement(child, Site);
- }
-
- if (nullptr != props->getPropertySet("Roles"))
- log.warn("<Roles> element not valid for this filter");
- }
- }
-
- pVer->dwFilterVersion = HTTP_FILTER_REVISION;
- strncpy(pVer->lpszFilterDesc, "Shibboleth ISAPI Filter", SF_MAX_FILTER_DESC_LEN);
- pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
- SF_NOTIFY_SECURE_PORT |
- SF_NOTIFY_NONSECURE_PORT |
- SF_NOTIFY_PREPROC_HEADERS |
- SF_NOTIFY_LOG);
- log.info("ISAPI filter initialized");
- return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
- if (g_Config)
- g_Config->term();
- g_Config = nullptr;
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").info("ISAPI filter shutting down");
- return TRUE;
-}
-
-/* Next up, some suck-free versions of various APIs.
-
- You DON'T require people to guess the buffer size and THEN tell them the right size.
- Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that
- constant strings aren't typed as such, making it just that much harder. These versions
- are now updated to use a special growable buffer object, modeled after the standard
- string class. The standard string won't work because they left out the option to
- pre-allocate a non-constant buffer.
-*/
-
-class dynabuf
-{
-public:
- dynabuf() { bufptr=nullptr; buflen=0; }
- dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }
- ~dynabuf() { delete[] bufptr; }
- size_t length() const { return bufptr ? strlen(bufptr) : 0; }
- size_t size() const { return buflen; }
- bool empty() const { return length()==0; }
- void reserve(size_t s, bool keep=false);
- void erase() { if (bufptr) memset(bufptr,0,buflen); }
- operator char*() { return bufptr; }
- bool operator ==(const char* s) const;
- bool operator !=(const char* s) const { return !(*this==s); }
-private:
- char* bufptr;
- size_t buflen;
-};
-
-void dynabuf::reserve(size_t s, bool keep)
-{
- if (s<=buflen)
- return;
- char* p=new char[s];
- if (keep)
- while (buflen--)
- p[buflen]=bufptr[buflen];
- buflen=s;
- delete[] bufptr;
- bufptr=p;
-}
-
-bool dynabuf::operator==(const char* s) const
-{
- if (buflen==0 || s==nullptr)
- return (buflen==0 && s==nullptr);
- else
- return strcmp(bufptr,s)==0;
-}
-
-/****************************************************************************/
-// ISAPI Filter
-
-class ShibTargetIsapiF : public AbstractSPRequest
-{
- PHTTP_FILTER_CONTEXT m_pfc;
- PHTTP_FILTER_PREPROC_HEADERS m_pn;
- multimap<string,string> m_headers;
- int m_port;
- string m_scheme,m_hostname;
- mutable string m_remote_addr,m_content_type,m_method;
- dynabuf m_allhttp;
- bool m_firsttime;
-
-public:
- ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)
- : AbstractSPRequest(SHIBSP_LOGCAT ".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {
-
- static char _url[] = "url";
- static char _SERVER_PORT[] = "SERVER_PORT";
- static char _SERVER_NAME[] = "SERVER_NAME";
- static char _ShibSpoofCheck[] = "ShibSpoofCheck:";
-
- // URL path always come from IIS.
- dynabuf var(256);
- GetHeader(_url,var,256,false);
- setRequestURI(var);
-
- // Port may come from IIS or from site def.
- if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {
- GetServerVariable(_SERVER_PORT,var,10);
- if (var.empty()) {
- m_port = pfc->fIsSecurePort ? 443 : 80;
- }
- else {
- m_port = atoi(var);
- }
- }
- else if (pfc->fIsSecurePort) {
- m_port = atoi(site.m_sslport.c_str());
- }
- else {
- m_port = atoi(site.m_port.c_str());
- }
-
- // Scheme may come from site def or be derived from IIS.
- m_scheme=site.m_scheme;
- if (m_scheme.empty() || !g_bNormalizeRequest)
- m_scheme=pfc->fIsSecurePort ? "https" : "http";
-
- GetServerVariable(_SERVER_NAME,var,32);
-
- // Make sure SERVER_NAME is "authorized" for use on this site. If not, or empty, set to canonical name.
- if (var.empty()) {
- m_hostname = site.m_name;
- }
- else {
- m_hostname = var;
- if (site.m_name != m_hostname && site.m_aliases.find(m_hostname) == site.m_aliases.end())
- m_hostname = site.m_name;
- }
-
- if (!g_spoofKey.empty()) {
- GetHeader(_ShibSpoofCheck, var, 32, false);
- if (!var.empty() && g_spoofKey == (char*)var)
- m_firsttime = false;
- }
-
- if (!m_firsttime)
- log(SPDebug, "ISAPI filter running more than once");
- }
- ~ShibTargetIsapiF() { }
-
- 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* getQueryString() const {
- const char* uri = getRequestURI();
- uri = (uri ? strchr(uri, '?') : nullptr);
- return uri ? (uri + 1) : nullptr;
- }
- const char* getMethod() const {
- static char _HTTP_METHOD[] = "HTTP_METHOD";
- if (m_method.empty()) {
- dynabuf var(5);
- GetServerVariable(_HTTP_METHOD,var,5,false);
- if (!var.empty())
- m_method = var;
- }
- return m_method.c_str();
- }
- string getContentType() const {
- static char _HTTP_CONTENT_TYPE[] = "HTTP_CONTENT_TYPE";
- if (m_content_type.empty()) {
- dynabuf var(32);
- GetServerVariable(_HTTP_CONTENT_TYPE,var,32,false);
- if (!var.empty())
- m_content_type = var;
- }
- return m_content_type;
- }
- string getRemoteAddr() const {
- static char _REMOTE_ADDR[] = "REMOTE_ADDR";
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(_REMOTE_ADDR,var,16,false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- string makeSafeHeader(const char* rawname) const {
- string hdr;
- for (; *rawname; ++rawname) {
- if (isalnum(*rawname))
- hdr += *rawname;
- }
- return (hdr + ':');
- }
- void clearHeader(const char* rawname, const char* cginame) {
- static char _ALL_HTTP[] = "ALL_HTTP";
- static char _REMOTE_USER[] = "remote-user:";
- static char _REMOTE_USER2[] = "remote_user:";
-
- if (g_checkSpoofing && m_firsttime) {
- if (m_allhttp.empty())
- GetServerVariable(_ALL_HTTP, m_allhttp, 4096, false);
- if (!m_allhttp.empty()) {
- string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');
- if (strstr(m_allhttp, hdr.c_str()))
- throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));
- }
- }
- if (g_bSafeHeaderNames) {
- string hdr = makeSafeHeader(rawname);
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
- }
- else if (!strcmp(rawname,"REMOTE_USER")) {
- m_pn->SetHeader(m_pfc, _REMOTE_USER, const_cast<char*>(g_unsetHeaderValue.c_str()));
- m_pn->SetHeader(m_pfc, _REMOTE_USER2, const_cast<char*>(g_unsetHeaderValue.c_str()));
- }
- else {
- string hdr = string(rawname) + ':';
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
- }
- }
- void setHeader(const char* name, const char* value) {
- string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
- }
- string getSecureHeader(const char* name) const {
- string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
- dynabuf buf(256);
- GetHeader(const_cast<char*>(hdr.c_str()), buf, 256, false);
- return string(buf.empty() ? "" : static_cast<char*>(buf));
- }
- string getHeader(const char* name) const {
- string hdr(name);
- hdr += ':';
- dynabuf buf(256);
- GetHeader(const_cast<char*>(hdr.c_str()), buf, 256, false);
- return string(buf.empty() ? "" : static_cast<char*>(buf));
- }
- void setRemoteUser(const char* user) {
- setHeader("remote-user", user);
- if (!user || !*user)
- m_pfc->pFilterContext = nullptr;
- else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), 0))
- strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
- }
- string getRemoteUser() const {
- return getSecureHeader("remote-user");
- }
- void setResponseHeader(const char* name, const char* value, bool replace=false) {
- HTTPResponse::setResponseHeader(name, value, replace);
- if (name && *name) {
- // Set for later.
- if (replace || !value)
- m_headers.erase(name);
- if (value && *value)
- m_headers.insert(make_pair(name,value));
- }
- }
- long sendResponse(istream& in, long status) {
- string hdr = string("Connection: close\r\n");
- for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
- hdr += i->first + ": " + i->second + "\r\n";
- hdr += "\r\n";
- const char* codestr="200 OK";
- switch (status) {
- case XMLTOOLING_HTTP_STATUS_NOTMODIFIED: codestr="304 Not Modified"; break;
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="401 Authorization Required"; break;
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="403 Forbidden"; break;
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;
- case XMLTOOLING_HTTP_STATUS_ERROR: codestr="500 Server Error"; break;
- }
- m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (ULONG_PTR)hdr.c_str(), 0);
- char buf[1024];
- while (in) {
- in.read(buf,1024);
- DWORD resplen = in.gcount();
- m_pfc->WriteClient(m_pfc, buf, &resplen, 0);
- }
- return SF_STATUS_REQ_FINISHED;
- }
- long sendRedirect(const char* url) {
- static char _status[] = "302 Please Wait";
- HTTPResponse::sendRedirect(url);
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: Wed, 01 Jan 1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache,max-age=0\r\n";
- for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
- hdr += i->first + ": " + i->second + "\r\n";
- hdr += "\r\n";
- m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, _status, (ULONG_PTR)hdr.c_str(), 0);
- static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
- DWORD resplen=40;
- m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
- return SF_STATUS_REQ_FINISHED;
- }
- long returnDecline() {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
- long returnOK() {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- const vector<string>& getClientCertificates() const {
- return g_NoCerts;
- }
-
- // The filter never processes the POST, so stub these methods.
- long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }
- const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }
-
- void GetServerVariable(LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true) const {
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!m_pfc->GetServerVariable(m_pfc,lpszVariable,s,&size)) {
- // Grumble. Check the error.
- DWORD e = GetLastError();
- if (e == ERROR_INSUFFICIENT_BUFFER)
- s.reserve(size);
- else
- break;
- }
- if (bRequired && s.empty())
- log(SPRequest::SPError, string("missing required server variable: ") + lpszVariable);
- }
-
- void GetHeader(LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true) const {
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!m_pn->GetHeader(m_pfc,lpszName,s,&size)) {
- // Grumble. Check the error.
- DWORD e = GetLastError();
- if (e == ERROR_INSUFFICIENT_BUFFER)
- s.reserve(size);
- else
- break;
- }
- if (bRequired && s.empty())
- log(SPRequest::SPError, string("missing required header: ") + lpszName);
- }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
- static char _status[] = "200 OK";
- static char ctype[] = "Connection: close\r\nContent-Type: text/html\r\n\r\n";
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,_status,(ULONG_PTR)ctype,0);
- static char xmsg[] = "<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
- "<H1>Shibboleth Filter Error</H1>";
- DWORD resplen=strlen(xmsg);
- pfc->WriteClient(pfc,xmsg,&resplen,0);
- resplen=strlen(msg);
- pfc->WriteClient(pfc,const_cast<char*>(msg),&resplen,0);
- static char xmsg2[] = "</BODY></HTML>";
- resplen=strlen(xmsg2);
- pfc->WriteClient(pfc,xmsg2,&resplen,0);
- return SF_STATUS_REQ_FINISHED;
-}
-
-void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {
- // Grumble. Check the error.
- DWORD e=GetLastError();
- if (e==ERROR_INSUFFICIENT_BUFFER)
- s.reserve(size);
- else
- break;
- }
- if (bRequired && s.empty()) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("missing server variable: %s", lpszVariable);
- }
-}
-
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
- static char _INSTANCE_ID[] = "INSTANCE_ID";
- static char _ShibSpoofCheck[] = "ShibSpoofCheck:";
-
- // Is this a log notification?
- if (notificationType == SF_NOTIFY_LOG) {
- if (pfc->pFilterContext)
- ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName = reinterpret_cast<char*>(pfc->pFilterContext);
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;
- try {
- // Determine web site number. This can't really fail, I don't think.
- dynabuf buf(128);
- GetServerVariable(pfc,_INSTANCE_ID,buf,10);
- if (buf.empty())
- return WriteClientError(pfc, "Shibboleth Filter failed to obtain INSTANCE_ID server variable.");
-
- // Match site instance to host name, skip if no match.
- map<string,site_t>::const_iterator map_i = g_Sites.find(static_cast<char*>(buf));
- if (map_i == g_Sites.end())
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
-
- string threadid("[");
- threadid += lexical_cast<string>(getpid()) + "] isapi_shib";
- xmltooling::NDC ndc(threadid.c_str());
-
- ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
- pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
- if (!g_spoofKey.empty())
- pn->SetHeader(pfc, _ShibSpoofCheck, const_cast<char*>(g_spoofKey.c_str()));
- if (res.first) return res.second;
-
- res = stf.getServiceProvider().doExport(stf);
- if (res.first) return res.second;
-
- res = stf.getServiceProvider().doAuthorization(stf);
- if (res.first) return res.second;
-
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
- catch(const bad_alloc&) {
- return WriteClientError(pfc, "Out of Memory");
- }
- catch(long e) {
- if (e==ERROR_NO_DATA)
- return WriteClientError(pfc, "A required variable or header was empty.");
- else
- return WriteClientError(pfc, "Shibboleth Filter detected unexpected IIS error.");
- }
- catch (const std::exception& e) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("ISAPI filter caught an exception: %s", e.what());
- return WriteClientError(pfc, "Shibboleth Filter caught an exception, check Event Log for details.");
- }
- catch(...) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").crit("ISAPI extension caught an unknown exception");
- if (g_catchAll)
- return WriteClientError(pfc, "Shibboleth Filter threw an unknown exception.");
- throw;
- }
- return WriteClientError(pfc, "Shibboleth Filter reached unreachable code, save my walrus!");
-}
-
-
-/****************************************************************************/
-// ISAPI Extension
-
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
-{
- static char _status[] = "200 OK";
- static char ctype[] = "Connection: close\r\nContent-Type: text/html\r\n\r\n";
- lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,_status,0,(LPDWORD)ctype);
- static char xmsg[] = "<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
- DWORD resplen=strlen(xmsg);
- lpECB->WriteClient(lpECB->ConnID,xmsg,&resplen,HSE_IO_SYNC);
- resplen=strlen(msg);
- lpECB->WriteClient(lpECB->ConnID,const_cast<char*>(msg),&resplen,HSE_IO_SYNC);
- static char xmsg2[] = "</BODY></HTML>";
- resplen=strlen(xmsg2);
- lpECB->WriteClient(lpECB->ConnID,xmsg2,&resplen,HSE_IO_SYNC);
- return HSE_STATUS_SUCCESS;
-}
-
-
-class ShibTargetIsapiE : public AbstractSPRequest
-{
- LPEXTENSION_CONTROL_BLOCK m_lpECB;
- multimap<string,string> m_headers;
- mutable vector<string> m_certs;
- mutable string m_body;
- mutable bool m_gotBody;
- int m_port;
- string m_scheme,m_hostname,m_uri;
- mutable string m_remote_addr,m_remote_user;
-
-public:
- ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)
- : AbstractSPRequest(SHIBSP_LOGCAT ".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {
- static char _HTTPS[] = "HTTPS";
- static char _URL[] = "URL";
- static char _SERVER_PORT[] = "SERVER_PORT";
- static char _SERVER_NAME[] = "SERVER_NAME";
-
- dynabuf ssl(5);
- GetServerVariable(_HTTPS,ssl,5);
- bool SSL=(ssl=="on" || ssl=="ON");
-
- // Scheme may come from site def or be derived from IIS.
- m_scheme = site.m_scheme;
- if (m_scheme.empty() || !g_bNormalizeRequest)
- m_scheme = SSL ? "https" : "http";
-
- // URL path always come from IIS.
- dynabuf url(256);
- GetServerVariable(_URL,url,255);
-
- // Port may come from IIS or from site def.
- if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty())) {
- dynabuf port(11);
- GetServerVariable(_SERVER_PORT,port,10);
- if (port.empty()) {
- m_port = SSL ? 443 : 80;
- }
- else {
- m_port = atoi(port);
- }
- }
- else if (SSL) {
- m_port = atoi(site.m_sslport.c_str());
- }
- else {
- m_port = atoi(site.m_port.c_str());
- }
-
- dynabuf var(32);
- GetServerVariable(_SERVER_NAME, var, 32);
- if (var.empty()) {
- m_hostname = site.m_name;
- }
- else {
- // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
- m_hostname=var;
- if (site.m_name != m_hostname && site.m_aliases.find(m_hostname) == site.m_aliases.end())
- m_hostname = site.m_name;
- }
-
- /*
- * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if
- * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",
- * which is the default. No perfect way to tell, but we can take a good guess by checking
- * whether the URL is a substring of the PATH_INFO:
- *
- * e.g. for /Shibboleth.sso/SAML/POST
- *
- * Bad mode (default):
- * URL: /Shibboleth.sso
- * PathInfo: /Shibboleth.sso/SAML/POST
- *
- * Good mode:
- * URL: /Shibboleth.sso
- * PathInfo: /SAML/POST
- */
-
- string uri;
-
- // Clearly we're only in bad mode if path info exists at all.
- if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {
- if (strstr(lpECB->lpszPathInfo,url))
- // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.
- uri = lpECB->lpszPathInfo;
- else {
- if (!url.empty())
- uri = url;
- uri += lpECB->lpszPathInfo;
- }
- }
- else if (!url.empty()) {
- uri = url;
- }
-
- // For consistency with Apache, let's add the query string.
- if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {
- uri += '?';
- uri += lpECB->lpszQueryString;
- }
-
- setRequestURI(uri.c_str());
- }
- ~ShibTargetIsapiE() {}
-
- 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 m_lpECB->lpszMethod;
- }
- string getContentType() const {
- return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";
- }
- long getContentLength() const {
- return m_lpECB->cbTotalBytes;
- }
- string getRemoteUser() const {
- static char _REMOTE_USER[] = "REMOTE_USER";
- if (m_remote_user.empty()) {
- dynabuf var(16);
- GetServerVariable(_REMOTE_USER, var, 32, false);
- if (!var.empty())
- m_remote_user = var;
- }
- return m_remote_user;
- }
- string getRemoteAddr() const {
- static char _REMOTE_ADDR[] = "REMOTE_ADDR";
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(_REMOTE_ADDR, var, 16, false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- string getHeader(const char* name) const {
- string hdr("HTTP_");
- for (; *name; ++name) {
- if (*name == '-')
- hdr += '_';
- else
- hdr += toupper(*name);
- }
- dynabuf buf(128);
- GetServerVariable(const_cast<char*>(hdr.c_str()), buf, 128, false);
- return buf.empty() ? "" : static_cast<char*>(buf);
- }
- void setResponseHeader(const char* name, const char* value, bool replace = false) {
- HTTPResponse::setResponseHeader(name, value, replace);
- if (name && *name) {
- // Set for later.
- if (replace || !value)
- m_headers.erase(name);
- if (value && *value)
- m_headers.insert(make_pair(name, value));
- }
- }
- const char* getQueryString() const {
- return m_lpECB->lpszQueryString;
- }
- const char* getRequestBody() const {
- if (m_gotBody)
- return m_body.c_str();
- if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
- throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
- else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
- m_gotBody=true;
- DWORD datalen=m_lpECB->cbTotalBytes;
- if (m_lpECB->cbAvailable > 0) {
- m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
- datalen-=m_lpECB->cbAvailable;
- }
- char buf[8192];
- while (datalen) {
- DWORD buflen=8192;
- BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
- if (!ret) {
- char message[65];
- _snprintf(message, 64, "Error reading request body from browser (%x).", GetLastError());
- throw IOException(message);
- }
- else if (!buflen)
- throw IOException("Socket closed while reading request body from browser.");
- m_body.append(buf, buflen);
- datalen-=buflen;
- }
- }
- else if (m_lpECB->cbAvailable) {
- m_gotBody=true;
- m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
- }
- return m_body.c_str();
- }
- long sendResponse(istream& in, long status) {
- string hdr = string("Connection: close\r\n");
- for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
- hdr += i->first + ": " + i->second + "\r\n";
- hdr += "\r\n";
-
- static char okstr[] = "200 OK";
- static char notmodstr[] = "304 Not Modified";
- static char authzstr[] = "401 Authorization Required";
- static char forbiddenstr[] = "403 Forbidden";
- static char notfoundstr[] = "404 Not Found";
- static char errorstr[] = "500 Server Error";
-
- char* str = nullptr;
-
- switch (status) {
- case XMLTOOLING_HTTP_STATUS_NOTMODIFIED: str = notmodstr; break;
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: str = authzstr; break;
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: str = forbiddenstr; break;
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: str = notfoundstr; break;
- case XMLTOOLING_HTTP_STATUS_ERROR: str = errorstr; break;
-
- default: str = okstr;
- }
- m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, str, 0, (LPDWORD)hdr.c_str());
- char buf[1024];
- while (in) {
- in.read(buf,1024);
- DWORD resplen = in.gcount();
- m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);
- }
- return HSE_STATUS_SUCCESS;
- }
- long sendRedirect(const char* url) {
- static char _status[] = "302 Moved";
-
- HTTPResponse::sendRedirect(url);
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: Wed, 01 Jan 1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache,max-age=0\r\n";
- for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
- hdr += i->first + ": " + i->second + "\r\n";
- hdr += "\r\n";
- m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, _status, 0, (LPDWORD)hdr.c_str());
- static char redmsg[] = "<HTML><BODY>Redirecting...</BODY></HTML>";
- DWORD resplen=40;
- m_lpECB->WriteClient(m_lpECB->ConnID, redmsg, &resplen, HSE_IO_SYNC);
- return HSE_STATUS_SUCCESS;
- }
- // Decline happens in the POST processor if this isn't the handler url
- // Note that it can also happen with HTAccess, but we don't support that, yet.
- long returnDecline() {
- return WriteClientError(
- m_lpECB,
- "ISAPI extension can only be invoked to process Shibboleth protocol requests."
- "Make sure the mapped file extension doesn't match actual content."
- );
- }
- long returnOK() {
- return HSE_STATUS_SUCCESS;
- }
-
- const vector<string>& getClientCertificates() const {
- if (m_certs.empty()) {
- char CertificateBuf[8192];
- CERT_CONTEXT_EX ccex;
- ccex.cbAllocated = sizeof(CertificateBuf);
- ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;
- DWORD dwSize = sizeof(ccex);
-
- if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, nullptr)) {
- if (ccex.CertContext.cbCertEncoded) {
- XMLSize_t outlen;
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
- m_certs.push_back(reinterpret_cast<char*>(serialized));
- XMLString::release((char**)&serialized);
- }
- }
- }
- return m_certs;
- }
-
- // Not used in the extension.
- void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }
- void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
- void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
-
- void GetServerVariable(LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true) const {
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!m_lpECB->GetServerVariable(m_lpECB->ConnID,lpszVariable,s,&size)) {
- // Grumble. Check the error.
- DWORD e=GetLastError();
- if (e==ERROR_INSUFFICIENT_BUFFER)
- s.reserve(size);
- else
- break;
- }
- if (bRequired && s.empty()) {
- log(SPRequest::SPError, string("missing required server variable: ") + lpszVariable);
- }
- }
-};
-
-void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {
- // Grumble. Check the error.
- DWORD e=GetLastError();
- if (e==ERROR_INSUFFICIENT_BUFFER)
- s.reserve(size);
- else
- break;
- }
- if (bRequired && s.empty()) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("missing required server variable: %s", lpszVariable);
- }
-}
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
- static char _INSTANCE_ID[] = "INSTANCE_ID";
-
- try {
- string threadid("[");
- threadid += lexical_cast<string>(getpid()) + "] isapi_shib_extension";
- xmltooling::NDC ndc(threadid.c_str());
-
- // Determine web site number. This can't really fail, I don't think.
- dynabuf buf(128);
- GetServerVariable(lpECB,_INSTANCE_ID,buf,10);
- if (buf.empty())
- return WriteClientError(lpECB, "Shibboleth Extension failed to obtain INSTANCE_ID server variable.");
-
- // Match site instance to host name, skip if no match.
- map<string,site_t>::const_iterator map_i = g_Sites.find(static_cast<char*>(buf));
- if (map_i == g_Sites.end())
- return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check ISAPI mappings in SP configuration).");
-
- ShibTargetIsapiE ste(lpECB, map_i->second);
- pair<bool,long> res = ste.getServiceProvider().doHandler(ste);
- if (res.first) return res.second;
-
- return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
-
- }
- catch(const bad_alloc&) {
- return WriteClientError(lpECB, "Out of Memory");
- }
- catch(long e) {
- if (e==ERROR_NO_DATA)
- return WriteClientError(lpECB, "A required variable or header was empty.");
- else
- return WriteClientError(lpECB, "Server detected unexpected IIS error.");
- }
- catch (const std::exception& e) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("ISAPI extension caught an exception: %s", e.what());
- return WriteClientError(lpECB, "Shibboleth Extension caught an exception, check native log for details.");
- }
- catch(...) {
- Category::getInstance(SHIBSP_LOGCAT ".ISAPI").crit("ISAPI filter caught an unknown exception");
- if (g_catchAll)
- return WriteClientError(lpECB, "Shibboleth Extension threw an unknown exception.");
- throw;
- }
-
- // If we get here we've got an error.
- return HSE_STATUS_ERROR;
-}
diff --git a/isapi_shib/isapi_shib.rc b/isapi_shib/isapi_shib.rc
deleted file mode 100644
index 7f1751a4..00000000
--- a/isapi_shib/isapi_shib.rc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth ISAPI Filter / Extension"
- VALUE "InternalName", "isapi_shib"
- VALUE "OriginalFilename", "isapi_shib.dll"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/isapi_shib/resource.h b/isapi_shib/resource.h
deleted file mode 100644
index 74732329..00000000
--- a/isapi_shib/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{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/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 00000000..528592d0
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,1071 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the specified
+# version of the C++ standard. If necessary, add switches to CXX and
+# CXXCPP to enable support. VERSION may be '11', '14', '17', '20', or
+# '23' for the respective C++ standard version.
+#
+# The second argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for no added switch, and then for an extended mode.
+#
+# The third argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline support for the specified C++ standard is
+# required and that the macro should error out if no mode with that
+# support is found. If specified 'optional', then configuration proceeds
+# regardless, after defining HAVE_CXX${VERSION} if and only if a
+# supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz at redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw at panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr at ices.utexas.edu>
+# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov at google.com>
+# Copyright (c) 2015 Paul Norman <penorman at mac.com>
+# Copyright (c) 2015 Moritz Klammler <moritz at klammler.eu>
+# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz at gmail.com>
+# Copyright (c) 2019 Enji Cooper <yaneurabeya at gmail.com>
+# Copyright (c) 2020 Jason Merrill <jason at redhat.com>
+# Copyright (c) 2021, 2024 Jörn Heusipp <osmanx at problemloesungsmaschine.de>
+# Copyright (c) 2015, 2022, 2023, 2024 Olly Betts
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 25
+
+dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+ m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+ [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+ [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+ [$1], [20], [ax_cxx_compile_alternatives="20"],
+ [$1], [23], [ax_cxx_compile_alternatives="23"],
+ [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$2], [], [],
+ [$2], [ext], [],
+ [$2], [noext], [],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+ [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+
+ m4_if([$2], [], [dnl
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+ ax_cv_cxx_compile_cxx$1,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [ax_cv_cxx_compile_cxx$1=yes],
+ [ax_cv_cxx_compile_cxx$1=no])])
+ if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+ ac_success=yes
+ fi])
+
+ m4_if([$2], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ switch="-std=gnu++${alternative}"
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ if test -n "$CXXCPP" ; then
+ CXXCPP="$CXXCPP $switch"
+ fi
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$2], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ dnl HP's aCC needs +std=c++11 according to:
+ dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+ dnl Cray's crayCC needs "-h std=c++11"
+ dnl MSVC needs -std:c++NN for C++17 and later (default is C++14)
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do
+ if test x"$switch" = xMSVC; then
+ dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide
+ dnl with -std=c++17. We suffix the cache variable name with _MSVC to
+ dnl avoid this.
+ switch=-std:c++${alternative}
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC])
+ else
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ fi
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ if test -n "$CXXCPP" ; then
+ CXXCPP="$CXXCPP $switch"
+ fi
+ ac_success=yes
+ break
+ fi
+ done
+ if test x$ac_success = xyes; then
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+ if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+ fi
+ fi
+ if test x$ac_success = xno; then
+ HAVE_CXX$1=0
+ AC_MSG_NOTICE([No compiler with C++$1 support was found])
+ else
+ HAVE_CXX$1=1
+ AC_DEFINE(HAVE_CXX$1,1,
+ [define if the compiler supports basic C++$1 syntax])
+ fi
+ AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+ [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11]
+)
+
+dnl Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+ [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14]
+)
+
+dnl Test body for checking C++17 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+ [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17]
+)
+
+dnl Test body for checking C++20 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
+ [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_20]
+)
+
+dnl Test body for checking C++23 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23],
+ [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_20
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_23]
+)
+
+
+dnl Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+// MSVC always sets __cplusplus to 199711L in older versions; newer versions
+// only set it correctly if /Zc:__cplusplus is specified as well as a
+// /std:c++NN switch:
+//
+// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
+//
+// The value __cplusplus ought to have is available in _MSVC_LANG since
+// Visual Studio 2015 Update 3:
+//
+// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+//
+// This was also the first MSVC version to support C++14 so we can't use the
+// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having
+// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later.
+#elif __cplusplus < 201103L && !defined _MSC_VER
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual ~Base() {}
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual ~Derived() override {}
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+]])
+
+
+dnl Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L && !defined _MSC_VER
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+ namespace test_polymorphic_lambdas
+ {
+
+ int
+ test()
+ {
+ const auto lambda = [](auto&&... args){
+ const auto istiny = [](auto x){
+ return (sizeof(x) == 1UL) ? 1 : 0;
+ };
+ const int aretiny[] = { istiny(args)... };
+ return aretiny[0];
+ };
+ return lambda(1, 1L, 1.0f, '1');
+ }
+
+ }
+
+ namespace test_binary_literals
+ {
+
+ constexpr auto ivii = 0b0000000000101010;
+ static_assert(ivii == 42, "wrong value");
+
+ }
+
+ namespace test_generalized_constexpr
+ {
+
+ template < typename CharT >
+ constexpr unsigned long
+ strlen_c(const CharT *const s) noexcept
+ {
+ auto length = 0UL;
+ for (auto p = s; *p; ++p)
+ ++length;
+ return length;
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("x") == 1UL, "");
+ static_assert(strlen_c("test") == 4UL, "");
+ static_assert(strlen_c("another\0test") == 7UL, "");
+
+ }
+
+ namespace test_lambda_init_capture
+ {
+
+ int
+ test()
+ {
+ auto x = 0;
+ const auto lambda1 = [a = x](int b){ return a + b; };
+ const auto lambda2 = [a = lambda1(x)](){ return a; };
+ return lambda2();
+ }
+
+ }
+
+ namespace test_digit_separators
+ {
+
+ constexpr auto ten_million = 100'000'000;
+ static_assert(ten_million == 100000000, "");
+
+ }
+
+ namespace test_return_type_deduction
+ {
+
+ auto f(int& x) { return x; }
+ decltype(auto) g(int& x) { return x; }
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static constexpr auto value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static constexpr auto value = true;
+ };
+
+ int
+ test()
+ {
+ auto x = 0;
+ static_assert(is_same<int, decltype(f(x))>::value, "");
+ static_assert(is_same<int&, decltype(g(x))>::value, "");
+ return x;
+ }
+
+ }
+
+} // namespace cxx14
+
+#endif // __cplusplus >= 201402L
+
+]])
+
+
+dnl Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+ namespace test_constexpr_lambdas
+ {
+
+ constexpr int foo = [](){return 42;}();
+
+ }
+
+ namespace test::nested_namespace::definitions
+ {
+
+ }
+
+ namespace test_fold_expression
+ {
+
+ template<typename... Args>
+ int multiply(Args... args)
+ {
+ return (args * ... * 1);
+ }
+
+ template<typename... Args>
+ bool all(Args... args)
+ {
+ return (args && ...);
+ }
+
+ }
+
+ namespace test_extended_static_assert
+ {
+
+ static_assert (true);
+
+ }
+
+ namespace test_auto_brace_init_list
+ {
+
+ auto foo = {5};
+ auto bar {5};
+
+ static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+ static_assert(std::is_same<int, decltype(bar)>::value);
+ }
+
+ namespace test_typename_in_template_template_parameter
+ {
+
+ template<template<typename> typename X> struct D;
+
+ }
+
+ namespace test_fallthrough_nodiscard_maybe_unused_attributes
+ {
+
+ int f1()
+ {
+ return 42;
+ }
+
+ [[nodiscard]] int f2()
+ {
+ [[maybe_unused]] auto unused = f1();
+
+ switch (f1())
+ {
+ case 17:
+ f1();
+ [[fallthrough]];
+ case 42:
+ f1();
+ }
+ return f1();
+ }
+
+ }
+
+ namespace test_extended_aggregate_initialization
+ {
+
+ struct base1
+ {
+ int b1, b2 = 42;
+ };
+
+ struct base2
+ {
+ base2() {
+ b3 = 42;
+ }
+ int b3;
+ };
+
+ struct derived : base1, base2
+ {
+ int d;
+ };
+
+ derived d1 {{1, 2}, {}, 4}; // full initialization
+ derived d2 {{}, {}, 4}; // value-initialized bases
+
+ }
+
+ namespace test_general_range_based_for_loop
+ {
+
+ struct iter
+ {
+ int i;
+
+ int& operator* ()
+ {
+ return i;
+ }
+
+ const int& operator* () const
+ {
+ return i;
+ }
+
+ iter& operator++()
+ {
+ ++i;
+ return *this;
+ }
+ };
+
+ struct sentinel
+ {
+ int i;
+ };
+
+ bool operator== (const iter& i, const sentinel& s)
+ {
+ return i.i == s.i;
+ }
+
+ bool operator!= (const iter& i, const sentinel& s)
+ {
+ return !(i == s);
+ }
+
+ struct range
+ {
+ iter begin() const
+ {
+ return {0};
+ }
+
+ sentinel end() const
+ {
+ return {5};
+ }
+ };
+
+ void f()
+ {
+ range r {};
+
+ for (auto i : r)
+ {
+ [[maybe_unused]] auto v = i;
+ }
+ }
+
+ }
+
+ namespace test_lambda_capture_asterisk_this_by_value
+ {
+
+ struct t
+ {
+ int i;
+ int foo()
+ {
+ return [*this]()
+ {
+ return i;
+ }();
+ }
+ };
+
+ }
+
+ namespace test_enum_class_construction
+ {
+
+ enum class byte : unsigned char
+ {};
+
+ byte foo {42};
+
+ }
+
+ namespace test_constexpr_if
+ {
+
+ template <bool cond>
+ int f ()
+ {
+ if constexpr(cond)
+ {
+ return 13;
+ }
+ else
+ {
+ return 42;
+ }
+ }
+
+ }
+
+ namespace test_selection_statement_with_initializer
+ {
+
+ int f()
+ {
+ return 13;
+ }
+
+ int f2()
+ {
+ if (auto i = f(); i > 0)
+ {
+ return 3;
+ }
+
+ switch (auto i = f(); i + 4)
+ {
+ case 17:
+ return 2;
+
+ default:
+ return 1;
+ }
+ }
+
+ }
+
+ namespace test_template_argument_deduction_for_class_templates
+ {
+
+ template <typename T1, typename T2>
+ struct pair
+ {
+ pair (T1 p1, T2 p2)
+ : m1 {p1},
+ m2 {p2}
+ {}
+
+ T1 m1;
+ T2 m2;
+ };
+
+ void f()
+ {
+ [[maybe_unused]] auto p = pair{13, 42u};
+ }
+
+ }
+
+ namespace test_non_type_auto_template_parameters
+ {
+
+ template <auto n>
+ struct B
+ {};
+
+ B<5> b1;
+ B<'a'> b2;
+
+ }
+
+ namespace test_structured_bindings
+ {
+
+ int arr[2] = { 1, 2 };
+ std::pair<int, int> pr = { 1, 2 };
+
+ auto f1() -> int(&)[2]
+ {
+ return arr;
+ }
+
+ auto f2() -> std::pair<int, int>&
+ {
+ return pr;
+ }
+
+ struct S
+ {
+ int x1 : 2;
+ volatile double y1;
+ };
+
+ S f3()
+ {
+ return {};
+ }
+
+ auto [ x1, y1 ] = f1();
+ auto& [ xr1, yr1 ] = f1();
+ auto [ x2, y2 ] = f2();
+ auto& [ xr2, yr2 ] = f2();
+ const auto [ x3, y3 ] = f3();
+
+ }
+
+ namespace test_exception_spec_type_system
+ {
+
+ struct Good {};
+ struct Bad {};
+
+ void g1() noexcept;
+ void g2();
+
+ template<typename T>
+ Bad
+ f(T*, T*);
+
+ template<typename T1, typename T2>
+ Good
+ f(T1*, T2*);
+
+ static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+ }
+
+ namespace test_inline_variables
+ {
+
+ template<class T> void f(T)
+ {}
+
+ template<class T> inline T g(T)
+ {
+ return T{};
+ }
+
+ template<> inline void f<>(int)
+ {}
+
+ template<> int g<>(int)
+ {
+ return 5;
+ }
+
+ }
+
+} // namespace cxx17
+
+#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L
+
+]])
+
+
+dnl Tests for new features in C++20
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L
+
+#error "This is not a C++20 compiler"
+
+#else
+
+#include <version>
+
+namespace cxx20
+{
+
+// As C++20 supports feature test macros in the standard, there is no
+// immediate need to actually test for feature availability on the
+// Autoconf side.
+
+} // namespace cxx20
+
+#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L
+
+]])
+
+
+dnl Tests for new features in C++23
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L
+
+#error "This is not a C++23 compiler"
+
+#else
+
+#include <version>
+
+namespace cxx23
+{
+
+// As C++23 supports feature test macros in the standard, there is no
+// immediate need to actually test for feature availability on the
+// Autoconf side.
+
+} // namespace cxx23
+
+#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L
+
+]])
+
diff --git a/m4/doxygen.m4 b/m4/doxygen.m4
deleted file mode 100644
index a44060cb..00000000
--- a/m4/doxygen.m4
+++ /dev/null
@@ -1,537 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR])
-# DX_DOXYGEN_FEATURE(ON|OFF)
-# DX_DOT_FEATURE(ON|OFF)
-# DX_HTML_FEATURE(ON|OFF)
-# DX_CHM_FEATURE(ON|OFF)
-# DX_CHI_FEATURE(ON|OFF)
-# DX_MAN_FEATURE(ON|OFF)
-# DX_RTF_FEATURE(ON|OFF)
-# DX_XML_FEATURE(ON|OFF)
-# DX_PDF_FEATURE(ON|OFF)
-# DX_PS_FEATURE(ON|OFF)
-#
-# DESCRIPTION
-#
-# The DX_*_FEATURE macros control the default setting for the given
-# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
-# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
-# help (for MS users), 'CHI' for generating a seperate .chi file by the
-# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
-# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
-# specified to override the default 'a4wide' paper size.
-#
-# By default, HTML, PDF and PS documentation is generated as this seems to
-# be the most popular and portable combination. MAN pages created by
-# Doxygen are usually problematic, though by picking an appropriate subset
-# and doing some massaging they might be better than nothing. CHM and RTF
-# are specific for MS (note that you can't generate both HTML and CHM at
-# the same time). The XML is rather useless unless you apply specialized
-# post-processing to it.
-#
-# The macros mainly control the default state of the feature. The use can
-# override the default by specifying --enable or --disable. The macros
-# ensure that contradictory flags are not given (e.g.,
-# --enable-doxygen-html and --enable-doxygen-chm,
-# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
-# feature will be automatically disabled (with a warning) if the required
-# programs are missing.
-#
-# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
-# with the following parameters: a one-word name for the project for use
-# as a filename base etc., an optional configuration file name (the
-# default is 'Doxyfile', the same as Doxygen's default), and an optional
-# output directory name (the default is 'doxygen-doc').
-#
-# Automake Support
-#
-# The following is a template aminclude.am file for use with Automake.
-# Make targets and variables values are controlled by the various
-# DX_COND_* conditionals set by autoconf.
-#
-# The provided targets are:
-#
-# doxygen-doc: Generate all doxygen documentation.
-#
-# doxygen-run: Run doxygen, which will generate some of the
-# documentation (HTML, CHM, CHI, MAN, RTF, XML)
-# but will not do the post processing required
-# for the rest of it (PS, PDF, and some MAN).
-#
-# doxygen-man: Rename some doxygen generated man pages.
-#
-# doxygen-ps: Generate doxygen PostScript documentation.
-#
-# doxygen-pdf: Generate doxygen PDF documentation.
-#
-# Note that by default these are not integrated into the automake targets.
-# If doxygen is used to generate man pages, you can achieve this
-# integration by setting man3_MANS to the list of man pages generated and
-# then adding the dependency:
-#
-# $(man3_MANS): doxygen-doc
-#
-# This will cause make to run doxygen and generate all the documentation.
-#
-# The following variable is intended for use in Makefile.am:
-#
-# DX_CLEANFILES = everything to clean.
-#
-# Then add this variable to MOSTLYCLEANFILES.
-#
-# ----- begin aminclude.am -------------------------------------
-#
-# ## --------------------------------- ##
-# ## Format-independent Doxygen rules. ##
-# ## --------------------------------- ##
-#
-# if DX_COND_doc
-#
-# ## ------------------------------- ##
-# ## Rules specific for HTML output. ##
-# ## ------------------------------- ##
-#
-# if DX_COND_html
-#
-# DX_CLEAN_HTML = @DX_DOCDIR@/html
-#
-# endif DX_COND_html
-#
-# ## ------------------------------ ##
-# ## Rules specific for CHM output. ##
-# ## ------------------------------ ##
-#
-# if DX_COND_chm
-#
-# DX_CLEAN_CHM = @DX_DOCDIR@/chm
-#
-# if DX_COND_chi
-#
-# DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE at .chi
-#
-# endif DX_COND_chi
-#
-# endif DX_COND_chm
-#
-# ## ------------------------------ ##
-# ## Rules specific for MAN output. ##
-# ## ------------------------------ ##
-#
-# if DX_COND_man
-#
-# DX_CLEAN_MAN = @DX_DOCDIR@/man
-#
-# endif DX_COND_man
-#
-# ## ------------------------------ ##
-# ## Rules specific for RTF output. ##
-# ## ------------------------------ ##
-#
-# if DX_COND_rtf
-#
-# DX_CLEAN_RTF = @DX_DOCDIR@/rtf
-#
-# endif DX_COND_rtf
-#
-# ## ------------------------------ ##
-# ## Rules specific for XML output. ##
-# ## ------------------------------ ##
-#
-# if DX_COND_xml
-#
-# DX_CLEAN_XML = @DX_DOCDIR@/xml
-#
-# endif DX_COND_xml
-#
-# ## ----------------------------- ##
-# ## Rules specific for PS output. ##
-# ## ----------------------------- ##
-#
-# if DX_COND_ps
-#
-# DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE at .ps
-#
-# DX_PS_GOAL = doxygen-ps
-#
-# doxygen-ps: @DX_DOCDIR@/@PACKAGE at .ps
-#
-# @DX_DOCDIR@/@PACKAGE at .ps: @DX_DOCDIR@/@PACKAGE at .tag
-# cd @DX_DOCDIR@/latex; \
-# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-# $(DX_LATEX) refman.tex; \
-# $(MAKEINDEX_PATH) refman.idx; \
-# $(DX_LATEX) refman.tex; \
-# countdown=5; \
-# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-# refman.log > /dev/null 2>&1 \
-# && test $$countdown -gt 0; do \
-# $(DX_LATEX) refman.tex; \
-# countdown=`expr $$countdown - 1`; \
-# done; \
-# $(DX_DVIPS) -o ../@PACKAGE at .ps refman.dvi
-#
-# endif DX_COND_ps
-#
-# ## ------------------------------ ##
-# ## Rules specific for PDF output. ##
-# ## ------------------------------ ##
-#
-# if DX_COND_pdf
-#
-# DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE at .pdf
-#
-# DX_PDF_GOAL = doxygen-pdf
-#
-# doxygen-pdf: @DX_DOCDIR@/@PACKAGE at .pdf
-#
-# @DX_DOCDIR@/@PACKAGE at .pdf: @DX_DOCDIR@/@PACKAGE at .tag
-# cd @DX_DOCDIR@/latex; \
-# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-# $(DX_PDFLATEX) refman.tex; \
-# $(DX_MAKEINDEX) refman.idx; \
-# $(DX_PDFLATEX) refman.tex; \
-# countdown=5; \
-# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-# refman.log > /dev/null 2>&1 \
-# && test $$countdown -gt 0; do \
-# $(DX_PDFLATEX) refman.tex; \
-# countdown=`expr $$countdown - 1`; \
-# done; \
-# mv refman.pdf ../@PACKAGE at .pdf
-#
-# endif DX_COND_pdf
-#
-# ## ------------------------------------------------- ##
-# ## Rules specific for LaTeX (shared for PS and PDF). ##
-# ## ------------------------------------------------- ##
-#
-# if DX_COND_latex
-#
-# DX_CLEAN_LATEX = @DX_DOCDIR@/latex
-#
-# endif DX_COND_latex
-#
-# .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-# .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-# doxygen-run: @DX_DOCDIR@/@PACKAGE at .tag
-#
-# doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-# @DX_DOCDIR@/@PACKAGE at .tag: $(DX_CONFIG) $(pkginclude_HEADERS)
-# rm -rf @DX_DOCDIR@
-# $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
-#
-# DX_CLEANFILES = \
-# @DX_DOCDIR@/@PACKAGE at .tag \
-# -r \
-# $(DX_CLEAN_HTML) \
-# $(DX_CLEAN_CHM) \
-# $(DX_CLEAN_CHI) \
-# $(DX_CLEAN_MAN) \
-# $(DX_CLEAN_RTF) \
-# $(DX_CLEAN_XML) \
-# $(DX_CLEAN_PS) \
-# $(DX_CLEAN_PDF) \
-# $(DX_CLEAN_LATEX)
-#
-# endif DX_COND_doc
-#
-# ----- end aminclude.am ---------------------------------------
-#
-# LICENSE
-#
-# Copyright (c) 2009 Oren Ben-Kiki <oren at ben-kiki.org>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 11
-
-## ----------##
-## Defaults. ##
-## ----------##
-
-DX_ENV=""
-AC_DEFUN([DX_FEATURE_doc], ON)
-AC_DEFUN([DX_FEATURE_dot], OFF)
-AC_DEFUN([DX_FEATURE_man], OFF)
-AC_DEFUN([DX_FEATURE_html], ON)
-AC_DEFUN([DX_FEATURE_chm], OFF)
-AC_DEFUN([DX_FEATURE_chi], OFF)
-AC_DEFUN([DX_FEATURE_rtf], OFF)
-AC_DEFUN([DX_FEATURE_xml], OFF)
-AC_DEFUN([DX_FEATURE_pdf], ON)
-AC_DEFUN([DX_FEATURE_ps], ON)
-
-# Compatibility with older autoconf versions.
-m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))])
-
-## --------------- ##
-## Private macros. ##
-## --------------- ##
-
-# DX_ENV_APPEND(VARIABLE, VALUE)
-# ------------------------------
-# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
-AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
-
-# DX_DIRNAME_EXPR
-# ---------------
-# Expand into a shell expression prints the directory part of a path.
-AC_DEFUN([DX_DIRNAME_EXPR],
- [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
-
-# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
-# -------------------------------------
-# Expands according to the M4 (static) status of the feature.
-AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
-
-# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
-# ----------------------------------
-# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
-AC_DEFUN([DX_REQUIRE_PROG], [
-AC_PATH_TOOL([$1], [$2])
-if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
- AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
- AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
-fi
-])
-
-# DX_TEST_FEATURE(FEATURE)
-# ------------------------
-# Expand to a shell expression testing whether the feature is active.
-AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
-
-# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
-# -------------------------------------------------
-# Verify that a required features has the right state before trying to turn on
-# the DX_CURRENT_FEATURE.
-AC_DEFUN([DX_CHECK_DEPEND], [
-test "$DX_FLAG_$1" = "$2" \
-|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
- requires, contradicts) doxygen-DX_CURRENT_FEATURE])
-])
-
-# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
-# ----------------------------------------------------------
-# Turn off the DX_CURRENT_FEATURE if the required feature is off.
-AC_DEFUN([DX_CLEAR_DEPEND], [
-test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
-])
-
-# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
-# CHECK_DEPEND, CLEAR_DEPEND,
-# REQUIRE, DO-IF-ON, DO-IF-OFF)
-# --------------------------------------------
-# Parse the command-line option controlling a feature. CHECK_DEPEND is called
-# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
-# otherwise CLEAR_DEPEND is called to turn off the default state if a required
-# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
-# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
-# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
-AC_DEFUN([DX_ARG_ABLE], [
- AC_DEFUN([DX_CURRENT_FEATURE], [$1])
- AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
- AC_ARG_ENABLE(doxygen-$1,
- [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
- [--enable-doxygen-$1]),
- DX_IF_FEATURE([$1], [don't $2], [$2]))],
- [
-case "$enableval" in
-#(
-y|Y|yes|Yes|YES)
- AC_SUBST([DX_FLAG_$1], 1)
- $3
-;; #(
-n|N|no|No|NO)
- AC_SUBST([DX_FLAG_$1], 0)
-;; #(
-*)
- AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
-;;
-esac
-], [
-AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
-$4
-])
-if DX_TEST_FEATURE([$1]); then
- $5
- :
-fi
-if DX_TEST_FEATURE([$1]); then
- AM_CONDITIONAL(DX_COND_$1, :)
- $6
- :
-else
- AM_CONDITIONAL(DX_COND_$1, false)
- $7
- :
-fi
-])
-
-## -------------- ##
-## Public macros. ##
-## -------------- ##
-
-# DX_XXX_FEATURE(DEFAULT_STATE)
-# -----------------------------
-AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
-AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
-AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
-AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
-AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
-AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
-AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
-AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
-AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
-AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
-AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
-
-# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
-# ---------------------------------------------------------
-# PROJECT also serves as the base name for the documentation files.
-# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
-AC_DEFUN([DX_INIT_DOXYGEN], [
-
-# Files:
-AC_SUBST([DX_PROJECT], [$1])
-AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
-AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
-
-# Environment variables used inside doxygen.cfg:
-DX_ENV_APPEND(SRCDIR, $srcdir)
-DX_ENV_APPEND(PROJECT, $DX_PROJECT)
-DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
-DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
-
-# Doxygen itself:
-DX_ARG_ABLE(doc, [generate any doxygen documentation],
- [],
- [],
- [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
- DX_REQUIRE_PROG([DX_PERL], perl)],
- [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
-
-# Dot for graphics:
-DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_DOT], dot)],
- [DX_ENV_APPEND(HAVE_DOT, YES)
- DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
- [DX_ENV_APPEND(HAVE_DOT, NO)])
-
-# Man pages generation:
-DX_ARG_ABLE(man, [generate doxygen manual pages],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_MAN, YES)],
- [DX_ENV_APPEND(GENERATE_MAN, NO)])
-
-# RTF file generation:
-DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_RTF, YES)],
- [DX_ENV_APPEND(GENERATE_RTF, NO)])
-
-# XML file generation:
-DX_ARG_ABLE(xml, [generate doxygen XML documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_XML, YES)],
- [DX_ENV_APPEND(GENERATE_XML, NO)])
-
-# (Compressed) HTML help generation:
-DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_HHC], hhc)],
- [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
- DX_ENV_APPEND(GENERATE_HTML, YES)
- DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
- [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
-
-# Seperate CHI file generation.
-DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
- [DX_CHECK_DEPEND(chm, 1)],
- [DX_CLEAR_DEPEND(chm, 1)],
- [],
- [DX_ENV_APPEND(GENERATE_CHI, YES)],
- [DX_ENV_APPEND(GENERATE_CHI, NO)])
-
-# Plain HTML pages generation:
-DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
- [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
- [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
- [],
- [DX_ENV_APPEND(GENERATE_HTML, YES)],
- [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
-
-# PostScript file generation:
-DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_LATEX], latex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_DVIPS], dvips)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# PDF file generation:
-DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
- [DX_CHECK_DEPEND(doc, 1)],
- [DX_CLEAR_DEPEND(doc, 1)],
- [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
- DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
- DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# LaTeX generation for PS and/or PDF:
-if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
- AM_CONDITIONAL(DX_COND_latex, :)
- DX_ENV_APPEND(GENERATE_LATEX, YES)
-else
- AM_CONDITIONAL(DX_COND_latex, false)
- DX_ENV_APPEND(GENERATE_LATEX, NO)
-fi
-
-# Paper size for PS and/or PDF:
-AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
- [a4wide (default), a4, letter, legal or executive])
-case "$DOXYGEN_PAPER_SIZE" in
-#(
-"")
- AC_SUBST(DOXYGEN_PAPER_SIZE, "")
-;; #(
-a4wide|a4|letter|legal|executive)
- DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
-;; #(
-*)
- AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
-;;
-esac
-
-#For debugging:
-#echo DX_FLAG_doc=$DX_FLAG_doc
-#echo DX_FLAG_dot=$DX_FLAG_dot
-#echo DX_FLAG_man=$DX_FLAG_man
-#echo DX_FLAG_html=$DX_FLAG_html
-#echo DX_FLAG_chm=$DX_FLAG_chm
-#echo DX_FLAG_chi=$DX_FLAG_chi
-#echo DX_FLAG_rtf=$DX_FLAG_rtf
-#echo DX_FLAG_xml=$DX_FLAG_xml
-#echo DX_FLAG_pdf=$DX_FLAG_pdf
-#echo DX_FLAG_ps=$DX_FLAG_ps
-#echo DX_ENV=$DX_ENV
-])
\ No newline at end of file
diff --git a/memcache-store/Makefile.am b/memcache-store/Makefile.am
deleted file mode 100644
index a2cf4dc5..00000000
--- a/memcache-store/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = memcache-store.la
-
-memcache_store_la_LDFLAGS = $(MEMCACHED_LDFLAGS) -module -avoid-version
-memcache_store_la_CXXFLAGS = \
- $(AM_CXXFLAGS) \
- $(MEMCACHED_INCLUDE) \
- $(BOOST_CPPFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(log4cpp_CFLAGS) \
- $(log4shib_CFLAGS) \
- $(opensaml_CFLAGS) \
- $(xerces_CFLAGS) \
- $(xmltooling_CFLAGS)
-memcache_store_la_LIBADD = \
- $(MEMCACHED_LIBS) \
- $(PTHREAD_LIBS) \
- $(log4cpp_LIBS) \
- $(log4shib_LIBS) \
- $(opensaml_LIBS) \
- $(xerces_LIBS) \
- $(xmltooling_LIBS)
-
-memcache_store_la_SOURCES = \
- memcache-store.cpp
-
-EXTRA_DIST = memcache-store.rc resource.h
diff --git a/memcache-store/memcache-store.cpp b/memcache-store/memcache-store.cpp
deleted file mode 100644
index 98b4f4c0..00000000
--- a/memcache-store/memcache-store.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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 <xmltooling/base.h>
-
-#include <list>
-#include <iostream>
-#include <libmemcached/memcached.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <xmltooling/logging.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/StorageService.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLHelper.h>
-
-using namespace xmltooling::logging;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-namespace {
- 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);
- static const XMLCh nonBlocking[] = UNICODE_LITERAL_11(n,o,n,B,l,o,c,k,i,n,g);
-
- 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<string> &source, string &dest);
- void deserialize(string &source, mc_record &dest);
- void deserialize(string &source, list<string> &dest);
-
- bool addLock(string what, bool use_prefix = true);
- void deleteLock(string what, bool use_prefix = true);
-
- protected:
- Category& m_log;
- memcached_st* memc;
- string m_prefix;
- scoped_ptr<Mutex> m_lock;
-
- private:
- bool handleError(const char*, memcached_return) const;
- };
-
- class MemcacheStorageService : public StorageService, public MemcacheBase {
-
- public:
- MemcacheStorageService(const DOMElement* e);
- ~MemcacheStorageService() {}
-
- const Capabilities& getCapabilities() const {
- return m_caps;
- }
-
- bool createString(const char* context, const char* key, const char* value, time_t expiration);
- int readString(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0);
- int updateString(const char* context, const char* key, const char* value=nullptr, 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=nullptr, time_t* pexpiration=nullptr, int version=0) {
- return readString(context, key, pvalue, pexpiration, version);
- }
- int updateText(const char* context, const char* key, const char* value=nullptr, 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*) {}
-
- void updateContext(const char* context, time_t expiration);
- void deleteContext(const char* context);
-
- private:
- Capabilities m_caps;
- bool m_buildMap;
- };
-
- StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e, bool) {
- return new MemcacheStorageService(e);
- }
-};
-
-MemcacheBase::MemcacheBase(const DOMElement* e)
- : m_log(Category::getInstance("XMLTooling.StorageService.MEMCACHE")), memc(nullptr),
- m_prefix(XMLHelper::getAttrString(e, nullptr, prefix)), m_lock(Mutex::create())
-{
- memc = memcached_create(nullptr);
- if (!memc)
- throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
- m_log.debug("Memcache created");
-
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_CRC);
- m_log.debug("CRC hash set");
-
- int prop = XMLHelper::getAttrInt(e, 999999, sendTimeout);
- m_log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, prop);
-
- prop = XMLHelper::getAttrInt(e, 999999, recvTimeout);
- m_log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, prop);
-
- prop = XMLHelper::getAttrInt(e, 1000, pollTimeout);
- m_log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, prop);
-
- prop = XMLHelper::getAttrInt(e, 5, failLimit);
- m_log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, prop);
-
- prop = XMLHelper::getAttrInt(e, 30, retryTimeout);
- m_log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, prop);
-
- prop = XMLHelper::getAttrInt(e, 1, nonBlocking);
- m_log.debug("MEMCACHED_BEHAVIOR_NO_BLOCK will be set to %d", prop);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, prop);
-
- // Grab hosts from the configuration.
- e = e ? XMLHelper::getFirstChildElement(e, Hosts) : nullptr;
- if (!e || !e->hasChildNodes()) {
- memcached_free(memc);
- throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");
- }
- auto_ptr_char h(XMLHelper::getTextContent(e));
- m_log.debug("INIT: GOT Hosts: %s", h.get());
- memcached_server_st* servers;
- servers = memcached_servers_parse(const_cast<char*>(h.get()));
- m_log.debug("Got %u hosts.", memcached_server_list_count(servers));
- if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {
- memcached_server_list_free(servers);
- memcached_free(memc);
- throw IOException("MemcacheBase: memcached_server_push() failed");
- }
- memcached_server_list_free(servers);
-
- m_log.debug("Memcache object initialized");
-}
-
-MemcacheBase::~MemcacheBase()
-{
- memcached_free(memc);
- m_log.debug("Base object destroyed");
-}
-
-
-bool MemcacheBase::handleError(const char* fn, memcached_return rv) const
-{
-#ifdef HAVE_MEMCACHED_LAST_ERROR_MESSAGE
- string error = string("Memcache::") + fn + ": " + memcached_last_error_message(memc);
-#else
- string error;
- if (rv == MEMCACHED_ERRNO) {
- // System error
- error = string("Memcache::") + fn + "SYSTEM ERROR: " + strerror(memc->cached_errno);
- }
- else {
- error = string("Memcache::") + fn + " Problems: " + memcached_strerror(memc, rv);
- }
-#endif
- m_log.error(error);
- throw IOException(error);
-}
-
-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) {
- m_log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
- return false;
- }
- m_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<string>& 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<string>& source, string& dest)
-{
- ostringstream os(stringstream::in | stringstream::out);
- for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {
- if (iter != source.begin()) {
- os << endl;
- }
- os << *iter;
- }
- dest = os.str();
-}
-
-bool MemcacheBase::deleteMemcache(const char* key, time_t timeout, bool use_prefix)
-{
- string final_key;
- if (use_prefix)
- final_key = m_prefix + key;
- else
- final_key = key;
-
- Lock lock(m_lock);
- memcached_return rv = memcached_delete(memc, const_cast<char*>(final_key.c_str()), final_key.length(), timeout);
-
- switch (rv) {
- case MEMCACHED_SUCCESS:
- return true;
- case MEMCACHED_NOTFOUND:
- // Key wasn't there... No biggie.
- return false;
- default:
- return handleError("deleteMemcache", rv);
- }
-}
-
-bool MemcacheBase::getMemcache(const char* key, string& dest, uint32_t* flags, bool use_prefix)
-{
- string final_key;
- if (use_prefix)
- final_key = m_prefix + key;
- else
- final_key = key;
-
- Lock lock(m_lock);
- size_t len;
- memcached_return rv;
- char* result = memcached_get(memc, const_cast<char*>(final_key.c_str()), final_key.length(), &len, flags, &rv);
-
- switch (rv) {
- case MEMCACHED_SUCCESS:
- dest = result;
- free(result);
- return true;
- case MEMCACHED_NOTFOUND:
- m_log.debug("Key %s not found in memcache...", key);
- return false;
- default:
- return handleError("getMemcache", rv);
- }
-}
-
-bool MemcacheBase::addMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
- string final_key;
- if (use_prefix)
- final_key = m_prefix + key;
- else
- final_key = key;
-
- Lock lock(m_lock);
- memcached_return rv = memcached_add(
- memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
- );
-
- switch (rv) {
- case MEMCACHED_SUCCESS:
- return true;
- case MEMCACHED_NOTSTORED:
- return false;
- default:
- return handleError("addMemcache", rv);
- }
-}
-
-bool MemcacheBase::setMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
- string final_key;
- if (use_prefix)
- final_key = m_prefix + key;
- else
- final_key = key;
-
- Lock lock(m_lock);
- memcached_return rv = memcached_set(
- memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
- );
-
- if (rv == MEMCACHED_SUCCESS)
- return true;
- return handleError("setMemcache", rv);
-}
-
-bool MemcacheBase::replaceMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
-
- string final_key;
- if (use_prefix)
- final_key = m_prefix + key;
- else
- final_key = key;
-
- Lock lock(m_lock);
- memcached_return rv = memcached_replace(
- memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
- );
-
- switch (rv) {
- case MEMCACHED_SUCCESS:
- return true;
- case MEMCACHED_NOTSTORED:
- // not there
- return false;
- default:
- return handleError("replaceMemcache", rv);
- }
-}
-
-
-MemcacheStorageService::MemcacheStorageService(const DOMElement* e)
- : MemcacheBase(e), m_caps(80, 250 - m_prefix.length() - 1 - 80, 255),
- m_buildMap(XMLHelper::getAttrBool(e, false, buildMap))
-{
- if (m_buildMap)
- m_log.debug("Cache built with buildMap ON");
-}
-
-bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration)
-{
- m_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) {
- m_log.debug("Got result, updating map");
-
- string map_name = context;
- // we need to update the context map
- if (!addLock(map_name)) {
- m_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<string> contents;
- if (result) {
- m_log.debug("Match found. Parsing...");
- deserialize(ser_arr, contents);
- if (m_log.isDebugEnabled()) {
- m_log.debug("Iterating retrieved session map...");
- for(list<string>::const_iterator iter = contents.begin(); iter != contents.end(); ++iter)
- m_log.debug("value = %s", iter->c_str());
- }
- }
- else {
- m_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)
-{
- m_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) {
- m_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;
-
- mc_record rec;
- if (pexpiration || pvalue)
- deserialize(value, rec);
-
- if (pexpiration)
- *pexpiration = rec.expiration;
-
- if (version && rec_version <= (uint32_t)version)
- return version;
-
- 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)
-{
- m_log.debug("updateString ctx: %s - key: %s", context, key);
-
- time_t final_exp = expiration;
- time_t* want_expiration = nullptr;
- if (!final_exp)
- want_expiration = &final_exp;
-
- int read_res = readString(context, key, nullptr, 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)
-{
- m_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)
-{
-
- m_log.debug("updateContext ctx: %s", context);
-
- if (!m_buildMap) {
- m_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<string> contents;
- if (result) {
- m_log.debug("Match found. Parsing...");
- deserialize(ser_arr, contents);
-
- m_log.debug("Iterating retrieved session map...");
- for(list<string>::const_iterator iter = contents.begin(); iter != contents.end(); ++iter) {
- // Update expiration times
- string value;
- int read_res = readString(context, iter->c_str(), &value, nullptr, 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)
-{
-
- m_log.debug("deleteContext ctx: %s", context);
-
- if (!m_buildMap) {
- m_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<string> contents;
- if (result) {
- m_log.debug("Match found. Parsing...");
- deserialize(ser_arr, contents);
-
- m_log.debug("Iterating retrieved session map...");
- for (list<string>::const_iterator 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/memcache-store.rc b/memcache-store/memcache-store.rc
deleted file mode 100644
index 506d7b14..00000000
--- a/memcache-store/memcache-store.rc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth Memcache Storage Service Plugin\0"
- VALUE "InternalName", "memcache-store\0"
- VALUE "OriginalFilename", "memcache-store.so\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/memcache-store/resource.h b/memcache-store/resource.h
deleted file mode 100644
index ccedb46a..00000000
--- a/memcache-store/resource.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{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/nsapi_shib/Makefile.am b/nsapi_shib/Makefile.am
deleted file mode 100644
index 696f80ad..00000000
--- a/nsapi_shib/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-if BUILD_NSAPI
-nsapi_shibdir = $(libdir)/@PACKAGE_NAME@
-nsapi_shib_LTLIBRARIES = nsapi_shib.la
-nsapi_shib_la_SOURCES = nsapi_shib.cpp
-nsapi_shib_la_CXXFLAGS = $(NSAPI_INCLUDE) \
- $(AM_CXXFLAGS) \
- $(BOOST_CPPFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(log4shib_CFLAGS) $(log4cpp_CFLAGS) \
- $(xerces_CFLAGS) \
- $(xmltooling_lite_CFLAGS)
-nsapi_shib_la_LDFLAGS = -module -avoid-version
-nsapi_shib_la_LIBADD = \
- $(top_builddir)/shibsp/libshibsp-lite.la \
- $(PTHREAD_LIBS) \
- $(log4shib_LIBS) $(log4cpp_LIBS) \
- $(xerces_LIBS) \
- $(xmltooling_lite_LIBS)
-endif
-
-EXTRA_DIST = resource.h nsapi_shib.rc nsapi_shib.cpp
diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp
deleted file mode 100644
index 570dfbf2..00000000
--- a/nsapi_shib/nsapi_shib.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-/**
- * nsapi_shib.cpp
- *
- * Shibboleth NSAPI filter.
- */
-
-#define SHIBSP_LITE
-
-#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 _CRT_RAND_S
-#endif
-
-#include <shibsp/exceptions.h>
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/RequestMapper.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-
-#include <set>
-#include <memory>
-#include <fstream>
-#include <stdexcept>
-#include <boost/lexical_cast.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <process.h>
-# define XP_WIN32
-#else
-# define XP_UNIX
-#endif
-
-#define MCC_HTTPD
-#define NET_SSL
-
-extern "C"
-{
-#include <nsapi.h>
-}
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-// macros to output text to client
-#define NET_WRITE(str) \
- if (IO_ERROR==net_write(sn->csd,str,strlen(str))) return REQ_EXIT
-
-namespace {
- SPConfig* g_Config=nullptr;
- string g_ServerName;
- string g_unsetHeaderValue;
- string g_spoofKey;
- bool g_checkSpoofing = true;
- bool g_catchAll = false;
-
- 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);
-
- void _my_invalid_parameter_handler(
- const wchar_t * expression,
- const wchar_t * function,
- const wchar_t * file,
- unsigned int line,
- uintptr_t pReserved
- ) {
- return;
- }
-}
-
-PluginManager<RequestMapper,string,const xercesc::DOMElement*>::Factory SunRequestMapFactory;
-
-extern "C" NSAPI_PUBLIC void nsapi_shib_exit(void*)
-{
- if (g_Config)
- g_Config->term();
- g_Config = nullptr;
-}
-
-extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request* rq)
-{
- static char _funcname[] = "nsapi_shib_init";
-
- // Save off a default hostname for this virtual server.
- char* name=pblock_findval("server-name",pb);
- if (name)
- g_ServerName=name;
- else {
- name=server_hostname;
- if (name)
- g_ServerName=name;
- else {
- name=util_hostname();
- if (name) {
- g_ServerName=name;
- FREE(name);
- }
- else {
- pblock_nvinsert("error","unable to determine web server hostname",pb);
- return REQ_ABORTED;
- }
- }
- }
-
- static char _logmsg[] = "nsapi_shib loaded for host (%s)";
- log_error(LOG_INFORM,_funcname,sn,rq,_logmsg,g_ServerName.c_str());
-
- const char* schemadir=pblock_findval("shib-schemas",pb);
- const char* prefix=pblock_findval("shib-prefix",pb);
-
- g_Config=&SPConfig::getConfig();
- g_Config->deprecation().warn("NSAPI filter");
- g_Config->setFeatures(
- SPConfig::Listener |
- SPConfig::Caching |
- SPConfig::RequestMapping |
- SPConfig::InProcess |
- SPConfig::Logging |
- SPConfig::Handlers
- );
- if (!g_Config->init(schemadir,prefix)) {
- g_Config=nullptr;
- pblock_nvinsert("error","unable to initialize Shibboleth libraries",pb);
- return REQ_ABORTED;
- }
-
- g_Config->RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER,&SunRequestMapFactory);
-
- try {
- if (!g_Config->instantiate(pblock_findval("shib-config",pb), true))
- throw runtime_error("unknown error");
- }
- catch (std::exception& ex) {
- pblock_nvinsert("error",ex.what(),pb);
- g_Config->term();
- g_Config=nullptr;
- return REQ_ABORTED;
- }
-
- daemon_atrestart(nsapi_shib_exit,nullptr);
-
- ServiceProvider* sp=g_Config->getServiceProvider();
- Locker locker(sp);
- const PropertySet* props=sp->getPropertySet("InProcess");
- if (props) {
- pair<bool,bool> flag=props->getBool("checkSpoofing");
- g_checkSpoofing = !flag.first || flag.second;
- flag=props->getBool("catchAll");
- g_catchAll = flag.first && flag.second;
-
- pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
- if (unsetValue.first)
- g_unsetHeaderValue = unsetValue.second;
- if (g_checkSpoofing) {
- unsetValue=props->getString("spoofKey");
- if (unsetValue.first)
- g_spoofKey = unsetValue.second;
-#ifdef WIN32
- else {
- _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
- unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
- if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
- _set_invalid_parameter_handler(old);
- g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
- lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
- }
- else {
- _set_invalid_parameter_handler(old);
- pblock_nvinsert("error", "module failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually)", pb);
- locker.assign(); // pops lock on SP config
- g_Config->term();
- g_Config=nullptr;
- return REQ_ABORTED;
- }
- }
-#endif
- }
- }
- return REQ_PROCEED;
-}
-
-/********************************************************************************/
-// NSAPI Shib Target Subclass
-
-class ShibTargetNSAPI : public AbstractSPRequest
-{
- mutable string m_body;
- mutable bool m_gotBody,m_firsttime;
- bool m_security_active;
- int m_server_portnum;
- mutable vector<string> m_certs;
- set<string> m_allhttp;
-
-public:
- pblock* m_pb;
- ::Session* m_sn;
- Request* m_rq;
-
- ShibTargetNSAPI(pblock* pb, ::Session* sn, Request* rq)
- : AbstractSPRequest(SHIBSP_LOGCAT ".NSAPI"),
- m_gotBody(false), m_firsttime(true), m_security_active(false), m_server_portnum(0), m_pb(pb), m_sn(sn), m_rq(rq) {
-
- // To determine whether SSL is active or not, we're supposed to rely
- // on the security_active macro. For iPlanet 4.x, this works.
- // For Sun 7.x, it's useless and appears to be on or off based
- // on whether ANY SSL support is enabled for a vhost. Sun 6.x is unknown.
- // As a fix, there's a conf variable called $security that can be mapped
- // into a function parameter: security_active="$security"
- // We check for this parameter, and rely on the macro if it isn't set.
- // This doubles as a scheme virtualizer for load balanced scenarios
- // since you can set the parameter to 1 or 0 as needed.
- const char* sa = pblock_findval("security_active", m_pb);
- if (sa)
- m_security_active = (*sa == '1');
- else if (security_active)
- m_security_active = true;
- else
- m_security_active = false;
-
- // A similar issue exists for the port. server_portnum is no longer
- // working on at least Sun 7.x, and returns the first listener's port
- // rather than whatever port is actually used for the request. Nice job, Sun.
- sa = pblock_findval("server_portnum", m_pb);
- m_server_portnum = (sa && *sa) ? atoi(sa) : server_portnum;
-
- const char* uri = pblock_findval("uri", rq->reqpb);
- const char* qstr = pblock_findval("query", rq->reqpb);
-
- if (qstr) {
- string temp = string(uri) + '?' + qstr;
- setRequestURI(temp.c_str());
- }
- else {
- setRequestURI(uri);
- }
-
- // See if this is the first time we've run.
- if (!g_spoofKey.empty()) {
- qstr = pblock_findval("Shib-Spoof-Check", rq->headers);
- if (qstr && g_spoofKey == qstr)
- m_firsttime = false;
- }
- if (!m_firsttime || rq->orig_rq)
- log(SPDebug, "nsapi_shib function running more than once");
- }
- ~ShibTargetNSAPI() { }
-
- const char* getScheme() const {
- return m_security_active ? "https" : "http";
- }
- const char* getHostname() const {
-#ifdef vs_is_default_vs
- // This is 6.0 or later, so we can distinguish requests to name-based vhosts.
- if (!vs_is_default_vs(request_get_vs(m_rq)))
- // The beauty here is, a non-default vhost can *only* be accessed if the client
- // specified the exact name in the Host header. So we can trust the Host header.
- return pblock_findval("host", m_rq->headers);
- else
-#endif
- // In other cases, we're going to rely on the initialization process...
- return g_ServerName.c_str();
- }
- int getPort() const {
- return m_server_portnum;
- }
- const char* getMethod() const {
- return pblock_findval("method", m_rq->reqpb);
- }
- string getContentType() const {
- static char _contenttype[] = "content-type";
- char* content_type = nullptr;
- if (request_header(_contenttype, &content_type, m_sn, m_rq) != REQ_PROCEED)
- return "";
- return content_type ? content_type : "";
- }
- long getContentLength() const {
- static char _contentlen[] = "content-length";
- if (m_gotBody)
- return m_body.length();
- char* content_length=nullptr;
- if (request_header(_contentlen, &content_length, m_sn, m_rq) != REQ_PROCEED)
- return 0;
- return content_length ? atoi(content_length) : 0;
- }
- string getRemoteAddr() const {
- string ret = AbstractSPRequest::getRemoteAddr();
- return ret.empty() ? pblock_findval("ip", m_sn->client) : ret;
- }
- void log(SPLogLevel level, const string& msg) const {
- static char _module[] = "nsapi_shib";
- AbstractSPRequest::log(level,msg);
- if (level>=SPError)
- log_error(LOG_FAILURE, _module, m_sn, m_rq, const_cast<char*>(msg.c_str()));
- }
- const char* getQueryString() const {
- return pblock_findval("query", m_rq->reqpb);
- }
- const char* getRequestBody() const {
- static char _contentlen[] = "content-length";
- if (m_gotBody)
- return m_body.c_str();
- char* content_length=nullptr;
- if (request_header(_contentlen, &content_length, m_sn, m_rq) != REQ_PROCEED || !content_length) {
- m_gotBody = true;
- return nullptr;
- }
- else if (atoi(content_length) > 1024*1024) // 1MB?
- throw opensaml::SecurityPolicyException("Blocked request body exceeding 1M size limit.");
- else {
- char ch=IO_EOF+1;
- int cl=atoi(content_length);
- m_gotBody=true;
- while (cl && ch != IO_EOF) {
- ch=netbuf_getc(m_sn->inbuf);
- // Check for error.
- if(ch==IO_ERROR)
- break;
- m_body += ch;
- cl--;
- }
- if (cl)
- throw IOException("Error reading request body from browser.");
- return m_body.c_str();
- }
- }
- void clearHeader(const char* rawname, const char* cginame) {
- if (g_checkSpoofing && m_firsttime && !m_rq->orig_rq) {
- if (m_allhttp.empty()) {
- // Populate the set of client-supplied headers for spoof checking.
- const pb_entry* entry;
- for (int i=0; i<m_rq->headers->hsize; ++i) {
- entry = m_rq->headers->ht[i];
- while (entry) {
- string cgiversion("HTTP_");
- const char* pch = entry->param->name;
- while (*pch) {
- cgiversion += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
- m_allhttp.insert(cgiversion);
- entry = entry->next;
- }
- }
- }
- if (m_allhttp.count(cginame) > 0)
- throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
- }
- if (strcmp(rawname, "REMOTE_USER") == 0) {
- param_free(pblock_remove("remote-user", m_rq->headers));
- pblock_nvinsert("remote-user", g_unsetHeaderValue.c_str(), m_rq->headers);
- }
- else {
- param_free(pblock_remove(rawname, m_rq->headers));
- pblock_nvinsert(rawname, g_unsetHeaderValue.c_str(), m_rq->headers);
- }
- }
- void setHeader(const char* name, const char* value) {
- param_free(pblock_remove(name, m_rq->headers));
- pblock_nvinsert(name, value, m_rq->headers);
- }
- string getHeader(const char* name) const {
- // NSAPI headers tend to be lower case. We'll special case "cookie" since it's used a lot.
- char* hdr = nullptr;
- int cookie = strcmp(name, "Cookie");
- if (cookie == 0)
- name = "cookie";
- if (request_header(const_cast<char*>(name), &hdr, m_sn, m_rq) != REQ_PROCEED) {
- // We didn't get a hit, so we'll try a lower-casing operation, unless we already did...
- if (cookie == 0)
- return "";
- string n;
- while (*name)
- n += tolower(*(name++));
- if (request_header(const_cast<char*>(n.c_str()), &hdr, m_sn, m_rq) != REQ_PROCEED)
- return "";
- }
- return string(hdr ? hdr : "");
- }
- void setRemoteUser(const char* user) {
- pblock_nvinsert("auth-user", user, m_rq->vars);
- param_free(pblock_remove("remote-user", m_rq->headers));
- pblock_nvinsert("remote-user", user, m_rq->headers);
- }
- string getRemoteUser() const {
- const char* ru = pblock_findval("auth-user", m_rq->vars);
- return ru ? ru : "";
- }
- void setAuthType(const char* authtype) {
- param_free(pblock_remove("auth-type", m_rq->vars));
- if (authtype)
- pblock_nvinsert("auth-type", authtype, m_rq->vars);
- }
- string getAuthType() const {
- const char* at = pblock_findval("auth-type", m_rq->vars);
- return at ? at : "";
- }
- void setContentType(const char* type) {
- // iPlanet seems to have a case folding problem.
- param_free(pblock_remove("content-type", m_rq->srvhdrs));
- setResponseHeader("Content-Type", type);
- }
- void setResponseHeader(const char* name, const char* value, bool replace=false) {
- HTTPResponse::setResponseHeader(name, value, replace);
- if (name && *name) {
- if (replace || !value)
- param_free(pblock_remove(name, m_rq->srvhdrs));
- if (value && *value)
- pblock_nvinsert(name, value, m_rq->srvhdrs);
- }
- }
-
- long sendResponse(istream& in, long status) {
- string msg;
- char buf[1024];
- while (in) {
- in.read(buf,1024);
- msg.append(buf,in.gcount());
- }
- pblock_nvinsert("connection","close",m_rq->srvhdrs);
- pblock_nninsert("content-length", msg.length(), m_rq->srvhdrs);
- protocol_status(m_sn, m_rq, status, nullptr);
- protocol_start_response(m_sn, m_rq);
- net_write(m_sn->csd,const_cast<char*>(msg.c_str()),msg.length());
- return REQ_EXIT;
- }
- long sendRedirect(const char* url) {
- HTTPResponse::sendRedirect(url);
- param_free(pblock_remove("content-type", m_rq->srvhdrs));
- pblock_nninsert("content-length", 0, m_rq->srvhdrs);
- pblock_nvinsert("expires", "Wed, 01 Jan 1997 12:00:00 GMT", m_rq->srvhdrs);
- pblock_nvinsert("cache-control", "private,no-store,no-cache,max-age=0", m_rq->srvhdrs);
- pblock_nvinsert("location", url, m_rq->srvhdrs);
- pblock_nvinsert("connection","close",m_rq->srvhdrs);
- protocol_status(m_sn, m_rq, PROTOCOL_REDIRECT, nullptr);
- protocol_start_response(m_sn, m_rq);
- return REQ_ABORTED;
- }
- long returnDecline() { return REQ_NOACTION; }
- long returnOK() { return REQ_PROCEED; }
- const vector<string>& getClientCertificates() const {
- if (m_certs.empty()) {
- const char* cert = pblock_findval("auth-cert", m_rq->vars);
- if (cert)
- m_certs.push_back(cert);
- }
- return m_certs;
- }
-};
-
-/********************************************************************************/
-
-int WriteClientError(::Session* sn, Request* rq, char* func, char* msg)
-{
- log_error(LOG_FAILURE,func,sn,rq,msg);
- protocol_status(sn,rq,PROTOCOL_SERVER_ERROR,msg);
- return REQ_ABORTED;
-}
-
-extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
-{
- static char _func[] = "nsapi_shib";
-
- string threadid("[");
- threadid += lexical_cast<string>(getpid()) + "] nsapi_shib";
- xmltooling::NDC ndc(threadid.c_str());
-
- try {
- ShibTargetNSAPI stn(pb, sn, rq);
-
- // Check user authentication
- pair<bool,long> res = stn.getServiceProvider().doAuthentication(stn);
- // If directed, install a spoof key to recognize when we've already cleared headers.
- if (!g_spoofKey.empty()) {
- param_free(pblock_remove("Shib-Spoof-Check", rq->headers));
- pblock_nvinsert("Shib-Spoof-Check", g_spoofKey.c_str(), rq->headers);
- }
- if (res.first) return (int)res.second;
-
- // user authN was okay -- export the assertions now
- param_free(pblock_remove("auth-user",rq->vars));
-
- res = stn.getServiceProvider().doExport(stn);
- if (res.first) return (int)res.second;
-
- // Check the Authorization
- res = stn.getServiceProvider().doAuthorization(stn);
- if (res.first) return (int)res.second;
-
- // this user is ok.
- return REQ_PROCEED;
- }
- catch (const std::exception& e) {
- log_error(LOG_FAILURE,_func,sn,rq,const_cast<char*>(e.what()));
- static char _errmsg[] = "Shibboleth module threw an exception, see web server log for error.";
- return WriteClientError(sn, rq, _func, _errmsg);
- }
- catch (...) {
- static char _errmsg2[] = "Shibboleth module threw an unknown exception.";
- log_error(LOG_FAILURE,_func,sn,rq,_errmsg2);
- if (g_catchAll)
- return WriteClientError(sn, rq, _func, _errmsg2);
- throw;
- }
-}
-
-
-extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
-{
- static char _func[] = "shib_handler";
-
- string threadid("[");
- threadid += lexical_cast<string>(getpid()) + "] shib_handler";
- xmltooling::NDC ndc(threadid.c_str());
-
- try {
- ShibTargetNSAPI stn(pb, sn, rq);
-
- pair<bool,long> res = stn.getServiceProvider().doHandler(stn);
- if (res.first) return (int)res.second;
-
- static char _errmsg[] = "Shibboleth handler did not do anything.";
- return WriteClientError(sn, rq, _func, _errmsg);
- }
- catch (const std::exception& e) {
- static char _errmsg2[] = "Shibboleth handler threw an exception, see web server log for error.";
- log_error(LOG_FAILURE,_func,sn,rq,const_cast<char*>(e.what()));
- return WriteClientError(sn, rq, _func, _errmsg2);
- }
- catch (...) {
- static char _errmsg3[] = "Shibboleth handler threw an unknown exception.";
- log_error(LOG_FAILURE,_func,sn,rq,_errmsg3);
- if (g_catchAll)
- return WriteClientError(sn, rq, _func, _errmsg3);
- throw;
- }
-}
-
-
-class SunRequestMapper : public virtual RequestMapper, public virtual PropertySet
-{
-public:
- SunRequestMapper(const xercesc::DOMElement* e, bool deprecationSupport=true);
- ~SunRequestMapper() {}
- Lockable* lock() { return m_mapper->lock(); }
- void unlock() { m_stKey->setData(nullptr); m_propsKey->setData(nullptr); m_mapper->unlock(); }
- Settings getSettings(const HTTPRequest& request) const;
-
- const PropertySet* getParent() const { return nullptr; }
- void setParent(const PropertySet*) {}
- pair<bool,bool> getBool(const char* name, const char* ns=nullptr) const;
- pair<bool,const char*> getString(const char* name, const char* ns=nullptr) const;
- pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const;
- pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
- pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
- const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
- const xercesc::DOMElement* getElement() const;
-
-private:
- scoped_ptr<RequestMapper> m_mapper;
- scoped_ptr<ThreadKey> m_stKey, m_propsKey;
-};
-
-RequestMapper* SunRequestMapFactory(const xercesc::DOMElement* const & e, bool deprecationSupport)
-{
- return new SunRequestMapper(e);
-}
-
-SunRequestMapper::SunRequestMapper(const xercesc::DOMElement* e, bool deprecationSupport)
- : m_mapper(SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e, deprecationSupport)),
- m_stKey(ThreadKey::create(nullptr)),
- m_propsKey(ThreadKey::create(nullptr))
-{
-}
-
-RequestMapper::Settings SunRequestMapper::getSettings(const HTTPRequest& request) const
-{
- Settings s=m_mapper->getSettings(request);
- m_stKey->setData((void*)dynamic_cast<const ShibTargetNSAPI*>(&request));
- m_propsKey->setData((void*)s.first);
- return pair<const PropertySet*,AccessControl*>(this,s.second);
-}
-
-pair<bool,bool> SunRequestMapper::getBool(const char* name, const char* ns) const
-{
- const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- if (stn && !ns && name) {
- // Override boolean properties.
- const char* param=pblock_findval(name,stn->m_pb);
- if (param)
- return make_pair(true, !strcmp(param, "1") || !strcasecmp(param, "true"));
- }
- return s ? s->getBool(name,ns) : make_pair(false,false);
-}
-
-pair<bool,const char*> SunRequestMapper::getString(const char* name, const char* ns) const
-{
- const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- if (stn && !ns && name) {
- // Override string properties.
- if (!strcmp(name,"authType"))
- return pair<bool,const char*>(true,"shibboleth");
- else {
- const char* param=pblock_findval(name,stn->m_pb);
- if (param)
- return make_pair(true,param);
- }
- }
- return s ? s->getString(name,ns) : pair<bool,const char*>(false,nullptr);
-}
-
-pair<bool,const XMLCh*> SunRequestMapper::getXMLString(const char* name, const char* ns) const
-{
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- return s ? s->getXMLString(name,ns) : pair<bool,const XMLCh*>(false,nullptr);
-}
-
-pair<bool,unsigned int> SunRequestMapper::getUnsignedInt(const char* name, const char* ns) const
-{
- const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- if (stn && !ns && name) {
- // Override int properties.
- const char* param=pblock_findval(name,stn->m_pb);
- if (param) {
- try {
- return pair<bool,unsigned int>(true,lexical_cast<unsigned int>(param));
- }
- catch (bad_lexical_cast&) {
- return pair<bool,unsigned int>(false,0);
- }
- }
- }
- return s ? s->getUnsignedInt(name,ns) : pair<bool,unsigned int>(false,0);
-}
-
-pair<bool,int> SunRequestMapper::getInt(const char* name, const char* ns) const
-{
- const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- if (stn && !ns && name) {
- // Override int properties.
- const char* param=pblock_findval(name,stn->m_pb);
- if (param)
- return pair<bool,int>(true,atoi(param));
- }
- return s ? s->getInt(name,ns) : pair<bool,int>(false,0);
-}
-
-const PropertySet* SunRequestMapper::getPropertySet(const char* name, const char* ns) const
-{
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- return s ? s->getPropertySet(name,ns) : nullptr;
-}
-
-const xercesc::DOMElement* SunRequestMapper::getElement() const
-{
- const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
- return s ? s->getElement() : nullptr;
-}
diff --git a/nsapi_shib/nsapi_shib.rc b/nsapi_shib/nsapi_shib.rc
deleted file mode 100644
index e3aaee30..00000000
--- a/nsapi_shib/nsapi_shib.rc
+++ /dev/null
@@ -1,101 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth NSAPI Extension\0"
- VALUE "InternalName", "nsapi_shib\0"
- VALUE "OriginalFilename", "nsapi_shib.dll\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/nsapi_shib/resource.h b/nsapi_shib/resource.h
deleted file mode 100644
index bc921e9f..00000000
--- a/nsapi_shib/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by nsapi_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/odbc-store/Makefile.am b/odbc-store/Makefile.am
deleted file mode 100644
index 49e87c52..00000000
--- a/odbc-store/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = odbc-store.la
-
-odbc_store_la_CXXFLAGS = \
- $(AM_CXXFLAGS) \
- $(ODBC_CFLAGS) \
- $(BOOST_CPPFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(log4cpp_CFLAGS) \
- $(log4shib_CFLAGS) \
- $(opensaml_CFLAGS) \
- $(xerces_CFLAGS) \
- $(xmltooling_CFLAGS)
-odbc_store_la_LIBADD = \
- $(ODBC_LIBS) \
- $(PTHREAD_LIBS) \
- $(log4cpp_LIBS) \
- $(log4shib_LIBS) \
- $(opensaml_LIBS) \
- $(xerces_LIBS) \
- $(xmltooling_LIBS)
-
-odbc_store_la_SOURCES = \
- odbc-store.cpp
-
-odbc_store_la_LDFLAGS = -module -avoid-version
-
-EXTRA_DIST = odbc-store.rc resource.h
diff --git a/odbc-store/odbc-store.cpp b/odbc-store/odbc-store.cpp
deleted file mode 100644
index 2316e95c..00000000
--- a/odbc-store/odbc-store.cpp
+++ /dev/null
@@ -1,897 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-/**
- * odbc-store.cpp
- *
- * Storage Service using ODBC.
- */
-
-#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
-
-#ifdef WIN32
-# define ODBCSTORE_EXPORTS __declspec(dllexport)
-#else
-# define ODBCSTORE_EXPORTS
-#endif
-
-#include <xmltooling/logging.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/StorageService.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <sql.h>
-#include <sqlext.h>
-
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-
-using namespace xmltooling::logging;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-#define PLUGIN_VER_MAJOR 1
-#define PLUGIN_VER_MINOR 1
-
-#define LONGDATA_BUFLEN 16384
-
-#define COLSIZE_CONTEXT 255
-#define COLSIZE_ID 255
-#define COLSIZE_STRING_VALUE 255
-
-#define STRING_TABLE "strings"
-#define TEXT_TABLE "texts"
-
-/* table definitions
-CREATE TABLE version (
- major int NOT nullptr,
- minor int NOT nullptr
- )
-
-CREATE TABLE strings (
- context varchar(255) not null,
- id varchar(255) not null,
- expires datetime not null,
- version int not null,
- value varchar(255) not null,
- PRIMARY KEY (context, id)
- )
-
-CREATE TABLE texts (
- context varchar(255) not null,
- id varchar(255) not null,
- expires datetime not null,
- version int not null,
- value text not null,
- PRIMARY KEY (context, id)
- )
-*/
-
-namespace {
- static const XMLCh cleanupInterval[] = UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l);
- static const XMLCh isolationLevel[] = UNICODE_LITERAL_14(i,s,o,l,a,t,i,o,n,L,e,v,e,l);
- static const XMLCh ConnectionString[] = UNICODE_LITERAL_16(C,o,n,n,e,c,t,i,o,n,S,t,r,i,n,g);
- static const XMLCh RetryOnError[] = UNICODE_LITERAL_12(R,e,t,r,y,O,n,E,r,r,o,r);
- static const XMLCh contextSize[] = UNICODE_LITERAL_11(c,o,n,t,e,x,t,S,i,z,e);
- static const XMLCh keySize[] = UNICODE_LITERAL_7(k,e,y,S,i,z,e);
- static const XMLCh stringSize[] = UNICODE_LITERAL_10(s,t,r,i,n,g,S,i,z,e);
-
- // RAII for ODBC handles
- struct ODBCConn {
- ODBCConn(SQLHDBC conn) : handle(conn), autoCommit(true) {}
- ~ODBCConn() {
- if (handle != SQL_NULL_HDBC) {
- SQLRETURN sr = SQL_SUCCESS;
- if (!autoCommit)
- sr = SQLSetConnectAttr(handle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
- SQLDisconnect(handle);
- SQLFreeHandle(SQL_HANDLE_DBC, handle);
- if (!SQL_SUCCEEDED(sr))
- throw IOException("Failed to commit connection and return to auto-commit mode.");
- }
- }
- operator SQLHDBC() {return handle;}
- SQLHDBC handle;
- bool autoCommit;
- };
-
- class ODBCStorageService : public StorageService
- {
- public:
- ODBCStorageService(const DOMElement* e);
- virtual ~ODBCStorageService();
-
- const Capabilities& getCapabilities() const {
- return m_caps;
- }
-
- bool createString(const char* context, const char* key, const char* value, time_t expiration) {
- return createRow(STRING_TABLE, context, key, value, expiration);
- }
- int readString(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0) {
- return readRow(STRING_TABLE, context, key, pvalue, pexpiration, version);
- }
- int updateString(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0) {
- return updateRow(STRING_TABLE, context, key, value, expiration, version);
- }
- bool deleteString(const char* context, const char* key) {
- return deleteRow(STRING_TABLE, context, key);
- }
-
- bool createText(const char* context, const char* key, const char* value, time_t expiration) {
- return createRow(TEXT_TABLE, context, key, value, expiration);
- }
- int readText(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0) {
- return readRow(TEXT_TABLE, context, key, pvalue, pexpiration, version);
- }
- int updateText(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0) {
- return updateRow(TEXT_TABLE, context, key, value, expiration, version);
- }
- bool deleteText(const char* context, const char* key) {
- return deleteRow(TEXT_TABLE, context, key);
- }
-
- void reap(const char* context) {
- reap(STRING_TABLE, context);
- reap(TEXT_TABLE, context);
- }
-
- void updateContext(const char* context, time_t expiration) {
- updateContext(STRING_TABLE, context, expiration);
- updateContext(TEXT_TABLE, context, expiration);
- }
-
- void deleteContext(const char* context) {
- deleteContext(STRING_TABLE, context);
- deleteContext(TEXT_TABLE, context);
- }
-
-
- private:
- bool createRow(const char *table, const char* context, const char* key, const char* value, time_t expiration);
- int readRow(const char *table, const char* context, const char* key, string* pvalue, time_t* pexpiration, int version);
- int updateRow(const char *table, const char* context, const char* key, const char* value, time_t expiration, int version);
- bool deleteRow(const char *table, const char* context, const char* key);
-
- void reap(const char* table, const char* context);
- void updateContext(const char* table, const char* context, time_t expiration);
- void deleteContext(const char* table, const char* context);
-
- SQLHDBC getHDBC();
- SQLHSTMT getHSTMT(SQLHDBC);
- pair<SQLINTEGER,SQLINTEGER> getVersion(SQLHDBC);
- pair<bool,bool> log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor=nullptr);
-
- static void* cleanup_fn(void*);
- void cleanup();
-
- Category& m_log;
- Capabilities m_caps;
- int m_cleanupInterval;
- scoped_ptr<CondWait> shutdown_wait;
- Thread* cleanup_thread;
- bool shutdown;
-
- SQLHENV m_henv;
- string m_connstring;
- long m_isolation;
- bool m_wideVersion;
- vector<SQLINTEGER> m_retries;
- };
-
- StorageService* ODBCStorageServiceFactory(const DOMElement* const & e, bool)
- {
- return new ODBCStorageService(e);
- }
-
- // convert SQL timestamp to time_t
- time_t timeFromTimestamp(SQL_TIMESTAMP_STRUCT expires)
- {
- time_t ret;
- struct tm t;
- t.tm_sec=expires.second;
- t.tm_min=expires.minute;
- t.tm_hour=expires.hour;
- t.tm_mday=expires.day;
- t.tm_mon=expires.month-1;
- t.tm_year=expires.year-1900;
- t.tm_isdst=0;
-#if defined(HAVE_TIMEGM)
- ret = timegm(&t);
-#elif defined(WIN32)
- ret = mktime(&t) - _timezone;
-#else
- ret = mktime(&t) - timezone;
-#endif
- return (ret);
- }
-
- // conver time_t to SQL string
- void timestampFromTime(time_t t, char* ret)
- {
-#ifdef HAVE_GMTIME_R
- struct tm res;
- struct tm* ptime=gmtime_r(&t,&res);
-#else
- struct tm* ptime=gmtime(&t);
-#endif
- strftime(ret,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
- }
-
- class SQLString {
- const char* m_src;
- string m_copy;
- public:
- SQLString(const char* src) : m_src(src) {
- if (strchr(src, '\'')) {
- m_copy = src;
- replace_all(m_copy, "'", "''");
- }
- }
-
- operator const char*() const {
- return tostr();
- }
-
- const char* tostr() const {
- return m_copy.empty() ? m_src : m_copy.c_str();
- }
- };
-};
-
-ODBCStorageService::ODBCStorageService(const DOMElement* e) : m_log(Category::getInstance("XMLTooling.StorageService")),
- m_caps(XMLHelper::getAttrInt(e, 255, contextSize), XMLHelper::getAttrInt(e, 255, keySize), XMLHelper::getAttrInt(e, 255, stringSize)),
- m_cleanupInterval(XMLHelper::getAttrInt(e, 900, cleanupInterval)),
- cleanup_thread(nullptr), shutdown(false), m_henv(SQL_NULL_HENV), m_isolation(SQL_TXN_SERIALIZABLE), m_wideVersion(false)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("ODBCStorageService");
-#endif
- string iso(XMLHelper::getAttrString(e, "SERIALIZABLE", isolationLevel));
- if (iso == "SERIALIZABLE")
- m_isolation = SQL_TXN_SERIALIZABLE;
- else if (iso == "REPEATABLE_READ")
- m_isolation = SQL_TXN_REPEATABLE_READ;
- else if (iso == "READ_COMMITTED")
- m_isolation = SQL_TXN_READ_COMMITTED;
- else if (iso == "READ_UNCOMMITTED")
- m_isolation = SQL_TXN_READ_UNCOMMITTED;
- else
- throw XMLToolingException("Unknown transaction isolationLevel property.");
-
- if (m_henv == SQL_NULL_HENV) {
- // Enable connection pooling.
- SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0);
-
- // Allocate the environment.
- if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv)))
- throw XMLToolingException("ODBC failed to initialize.");
-
- // Specify ODBC 3.x
- SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
-
- m_log.info("ODBC initialized");
- }
-
- // Grab connection string from the configuration.
- e = e ? XMLHelper::getFirstChildElement(e, ConnectionString) : nullptr;
- auto_ptr_char arg(XMLHelper::getTextContent(e));
- if (!arg.get() || !*arg.get()) {
- SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
- throw XMLToolingException("ODBC StorageService requires ConnectionString element in configuration.");
- }
- m_connstring = arg.get();
-
- // Connect and check version.
- ODBCConn conn(getHDBC());
- pair<SQLINTEGER,SQLINTEGER> v = getVersion(conn);
-
- // Make sure we've got the right version.
- if (v.first != PLUGIN_VER_MAJOR) {
- SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
- m_log.crit("unknown database version: %d.%d", v.first, v.second);
- throw XMLToolingException("Unknown database version for ODBC StorageService.");
- }
-
- if (v.first > 1 || v.second > 0) {
- m_log.info("using 32-bit int type for version fields in tables");
- m_wideVersion = true;
- }
-
- // Load any retry errors to check.
- e = XMLHelper::getNextSiblingElement(e, RetryOnError);
- while (e) {
- if (e->hasChildNodes()) {
- try {
- int code = XMLString::parseInt(XMLHelper::getTextContent(e));
- m_retries.push_back(code);
- m_log.info("will retry operations when native ODBC error (%d) is returned", code);
- }
- catch (XMLException&) {
- m_log.error("skipping non-numeric ODBC retry code");
- }
- }
- e = XMLHelper::getNextSiblingElement(e, RetryOnError);
- }
-
- if (m_cleanupInterval > 0) {
- // Initialize the cleanup thread
- shutdown_wait.reset(CondWait::create());
- cleanup_thread = Thread::create(&cleanup_fn, (void*)this);
- }
- else {
- m_log.info("no cleanup interval configured, no cleanup thread will be started");
- }
-}
-
-ODBCStorageService::~ODBCStorageService()
-{
- shutdown = true;
- if (shutdown_wait.get()) {
- shutdown_wait->signal();
- }
- if (cleanup_thread) {
- cleanup_thread->join(nullptr);
- }
- if (m_henv != SQL_NULL_HANDLE) {
- SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
- }
-}
-
-pair<bool,bool> ODBCStorageService::log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor)
-{
- SQLSMALLINT i = 0;
- SQLINTEGER native;
- SQLCHAR state[7];
- SQLCHAR text[256];
- SQLSMALLINT len;
- SQLRETURN ret;
-
- pair<bool,bool> res = make_pair(false,false);
- do {
- ret = SQLGetDiagRec(htype, handle, ++i, state, &native, text, sizeof(text), &len);
- if (SQL_SUCCEEDED(ret)) {
- m_log.error("ODBC Error: %s:%ld:%ld:%s", state, i, native, text);
- for (vector<SQLINTEGER>::const_iterator n = m_retries.begin(); !res.first && n != m_retries.end(); ++n)
- res.first = (*n == native);
- if (checkfor && !strcmp(checkfor, (const char*)state))
- res.second = true;
- }
- } while(SQL_SUCCEEDED(ret));
- return res;
-}
-
-SQLHDBC ODBCStorageService::getHDBC()
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("getHDBC");
-#endif
-
- // Get a handle.
- SQLHDBC handle = SQL_NULL_HDBC;
- SQLRETURN sr = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &handle);
- if (!SQL_SUCCEEDED(sr) || handle == SQL_NULL_HDBC) {
- m_log.error("failed to allocate connection handle");
- log_error(m_henv, SQL_HANDLE_ENV);
- throw IOException("ODBC StorageService failed to allocate a connection handle.");
- }
-
- sr = SQLDriverConnect(handle,nullptr,(SQLCHAR*)m_connstring.c_str(),m_connstring.length(),nullptr,0,nullptr,SQL_DRIVER_NOPROMPT);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("failed to connect to database");
- log_error(handle, SQL_HANDLE_DBC);
- SQLFreeHandle(SQL_HANDLE_DBC, handle);
- throw IOException("ODBC StorageService failed to connect to database.");
- }
-
- sr = SQLSetConnectAttr(handle, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)m_isolation, 0);
- if (!SQL_SUCCEEDED(sr)) {
- SQLDisconnect(handle);
- SQLFreeHandle(SQL_HANDLE_DBC, handle);
- throw IOException("ODBC StorageService failed to set transaction isolation level.");
- }
-
- return handle;
-}
-
-SQLHSTMT ODBCStorageService::getHSTMT(SQLHDBC conn)
-{
- SQLHSTMT hstmt = SQL_NULL_HSTMT;
- SQLRETURN sr = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
- if (!SQL_SUCCEEDED(sr) || hstmt == SQL_NULL_HSTMT) {
- m_log.error("failed to allocate statement handle");
- log_error(conn, SQL_HANDLE_DBC);
- throw IOException("ODBC StorageService failed to allocate a statement handle.");
- }
- return hstmt;
-}
-
-pair<SQLINTEGER,SQLINTEGER> ODBCStorageService::getVersion(SQLHDBC conn)
-{
- // Grab the version number from the database.
- SQLHSTMT stmt = getHSTMT(conn);
-
- SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)"SELECT major,minor FROM version", SQL_NTS);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("failed to read version from database");
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to read version from database.");
- }
-
- SQLINTEGER major;
- SQLINTEGER minor;
- SQLBindCol(stmt, 1, SQL_C_SLONG, &major, 0, nullptr);
- SQLBindCol(stmt, 2, SQL_C_SLONG, &minor, 0, nullptr);
-
- if ((sr = SQLFetch(stmt)) != SQL_NO_DATA)
- return make_pair(major,minor);
-
- m_log.error("no rows returned in version query");
- throw IOException("ODBC StorageService failed to read version from database.");
-}
-
-bool ODBCStorageService::createRow(const char* table, const char* context, const char* key, const char* value, time_t expiration)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("createRow");
-#endif
-
- char timebuf[32];
- timestampFromTime(expiration, timebuf);
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- string q = string("INSERT INTO ") + table + " VALUES (?,?," + timebuf + ",1,?)";
-
- SQLRETURN sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("SQLPrepare failed (t=%s, c=%s, k=%s)", table, context, key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to insert record.");
- }
- m_log.debug("SQLPrepare succeeded. SQL: %s", q.c_str());
-
- SQLLEN b_ind = SQL_NTS;
- sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(context), &b_ind);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("SQLBindParam failed (context = %s)", context);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to insert record.");
- }
- m_log.debug("SQLBindParam succeeded (context = %s)", context);
-
- sr = SQLBindParam(stmt, 2, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(key), &b_ind);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("SQLBindParam failed (key = %s)", key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to insert record.");
- }
- m_log.debug("SQLBindParam succeeded (key = %s)", key);
-
- if (strcmp(table, TEXT_TABLE)==0)
- sr = SQLBindParam(stmt, 3, SQL_C_CHAR, SQL_LONGVARCHAR, strlen(value), 0, const_cast<char*>(value), &b_ind);
- else
- sr = SQLBindParam(stmt, 3, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(value), &b_ind);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("SQLBindParam failed (value = %s)", value);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to insert record.");
- }
- m_log.debug("SQLBindParam succeeded (value = %s)", value);
-
- int attempts = 3;
- pair<bool,bool> logres;
- do {
- logres = make_pair(false,false);
- attempts--;
- sr = SQLExecute(stmt);
- if (SQL_SUCCEEDED(sr)) {
- m_log.debug("SQLExecute of insert succeeded");
- return true;
- }
- m_log.error("insert record failed (t=%s, c=%s, k=%s)", table, context, key);
- logres = log_error(stmt, SQL_HANDLE_STMT, "23000");
- if (logres.second) {
- // Supposedly integrity violation.
- // Try and delete any expired record still hanging around until the final attempt.
- if (attempts > 0) {
- reap(table, context);
- logres.first = true; // force it to treat as a retryable error
- continue;
- }
- return false;
- }
- } while (attempts && logres.first);
-
- throw IOException("ODBC StorageService failed to insert record.");
-}
-
-int ODBCStorageService::readRow(const char *table, const char* context, const char* key, string* pvalue, time_t* pexpiration, int version)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("readRow");
-#endif
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- // Prepare and exectute select statement.
- char timebuf[32];
- timestampFromTime(time(nullptr), timebuf);
- SQLString scontext(context);
- SQLString skey(key);
- string q("SELECT version");
- if (pexpiration)
- q += ",expires";
- if (pvalue) {
- pvalue->erase();
- q = q + ",CASE version WHEN " + lexical_cast<string>(version) + " THEN null ELSE value END";
- }
- q = q + " FROM " + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "' AND expires > " + timebuf;
- if (m_log.isDebugEnabled())
- m_log.debug("SQL: %s", q.c_str());
-
- SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("error searching for (t=%s, c=%s, k=%s)", table, context, key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService search failed.");
- }
-
- SQLSMALLINT ver;
- SQLINTEGER widever;
- SQL_TIMESTAMP_STRUCT expiration;
-
- if (m_wideVersion)
- SQLBindCol(stmt, 1, SQL_C_SLONG, &widever, 0, nullptr);
- else
- SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
- if (pexpiration)
- SQLBindCol(stmt, 2, SQL_C_TYPE_TIMESTAMP, &expiration, 0, nullptr);
-
- if ((sr = SQLFetch(stmt)) == SQL_NO_DATA) {
- if (m_log.isDebugEnabled())
- m_log.debug("search returned no data (t=%s, c=%s, k=%s)", table, context, key);
- return 0;
- }
-
- if (pexpiration)
- *pexpiration = timeFromTimestamp(expiration);
-
- if (version == (m_wideVersion ? widever : ver)) {
- if (m_log.isDebugEnabled())
- m_log.debug("versioned search detected no change (t=%s, c=%s, k=%s)", table, context, key);
- return version; // nothing's changed, so just echo back the version
- }
-
- if (pvalue) {
- SQLLEN len;
- SQLCHAR buf[LONGDATA_BUFLEN];
- while ((sr = SQLGetData(stmt, (pexpiration ? 3 : 2), SQL_C_CHAR, buf, sizeof(buf), &len)) != SQL_NO_DATA) {
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("error while reading text field from result set");
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService search failed to read data from result set.");
- }
- pvalue->append((char*)buf);
- }
- }
-
- return (m_wideVersion ? widever : ver);
-}
-
-int ODBCStorageService::updateRow(const char *table, const char* context, const char* key, const char* value, time_t expiration, int version)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("updateRow");
-#endif
-
- if (!value && !expiration)
- throw IOException("ODBC StorageService given invalid update instructions.");
-
- // Get statement handle. Disable auto-commit mode to wrap select + update.
- ODBCConn conn(getHDBC());
- SQLRETURN sr = SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0);
- if (!SQL_SUCCEEDED(sr))
- throw IOException("ODBC StorageService failed to disable auto-commit mode.");
- conn.autoCommit = false;
- SQLHSTMT stmt = getHSTMT(conn);
-
- // First, fetch the current version for later, which also ensures the record still exists.
- char timebuf[32];
- timestampFromTime(time(nullptr), timebuf);
- SQLString scontext(context);
- SQLString skey(key);
- string q("SELECT version FROM ");
- q = q + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "' AND expires > " + timebuf;
-
- m_log.debug("SQL: %s", q.c_str());
-
- sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("error searching for (t=%s, c=%s, k=%s)", table, context, key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService search failed.");
- }
-
- SQLSMALLINT ver;
- SQLINTEGER widever;
- if (m_wideVersion)
- SQLBindCol(stmt, 1, SQL_C_SLONG, &widever, 0, nullptr);
- else
- SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
- if ((sr = SQLFetch(stmt)) == SQL_NO_DATA) {
- return 0;
- }
-
- // Check version?
- if (version > 0 && version != (m_wideVersion ? widever : ver)) {
- return -1;
- }
- else if ((m_wideVersion && widever == INT_MAX) || (!m_wideVersion && ver == 32767)) {
- m_log.error("record version overflow (t=%s, c=%s, k=%s)", table, context, key);
- throw IOException("Version overflow, record in ODBC StorageService could not be updated.");
- }
-
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- stmt = getHSTMT(conn);
-
- // Prepare and exectute update statement.
- q = string("UPDATE ") + table + " SET ";
-
- if (value)
- q = q + "value=?, version=version+1";
-
- if (expiration) {
- timestampFromTime(expiration, timebuf);
- if (value)
- q += ',';
- q = q + "expires = " + timebuf;
- }
-
- q = q + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "'";
-
- sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("update of record failed (t=%s, c=%s, k=%s", table, context, key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to update record.");
- }
- m_log.debug("SQLPrepare succeeded. SQL: %s", q.c_str());
-
- SQLLEN b_ind = SQL_NTS;
- if (value) {
- if (strcmp(table, TEXT_TABLE)==0)
- sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_LONGVARCHAR, strlen(value), 0, const_cast<char*>(value), &b_ind);
- else
- sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(value), &b_ind);
- if (!SQL_SUCCEEDED(sr)) {
- m_log.error("SQLBindParam failed (value = %s)", value);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to update record.");
- }
- m_log.debug("SQLBindParam succeeded (value = %s)", value);
- }
-
- int attempts = 3;
- pair<bool,bool> logres;
- do {
- logres = make_pair(false,false);
- attempts--;
- sr = SQLExecute(stmt);
- if (sr == SQL_NO_DATA)
- return 0; // went missing?
- else if (SQL_SUCCEEDED(sr)) {
- m_log.debug("SQLExecute of update succeeded");
- return (m_wideVersion ? widever : ver) + 1;
- }
-
- m_log.error("update of record failed (t=%s, c=%s, k=%s)", table, context, key);
- logres = log_error(stmt, SQL_HANDLE_STMT);
- } while (attempts && logres.first);
-
- throw IOException("ODBC StorageService failed to update record.");
-}
-
-bool ODBCStorageService::deleteRow(const char *table, const char *context, const char* key)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("deleteRow");
-#endif
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- // Prepare and execute delete statement.
- SQLString scontext(context);
- SQLString skey(key);
- string q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "'";
- m_log.debug("SQL: %s", q.c_str());
-
- SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (sr == SQL_NO_DATA)
- return false;
- else if (!SQL_SUCCEEDED(sr)) {
- m_log.error("error deleting record (t=%s, c=%s, k=%s)", table, context, key);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to delete record.");
- }
-
- return true;
-}
-
-
-void ODBCStorageService::cleanup()
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("cleanup");
-#endif
-
- scoped_ptr<Mutex> mutex(Mutex::create());
-
- mutex->lock();
-
- m_log.info("cleanup thread started... running every %d secs", m_cleanupInterval);
-
- while (!shutdown) {
- shutdown_wait->timedwait(mutex.get(), m_cleanupInterval);
- if (shutdown)
- break;
- try {
- reap(nullptr);
- }
- catch (std::exception& ex) {
- m_log.error("cleanup thread swallowed exception: %s", ex.what());
- }
- }
-
- m_log.info("cleanup thread exiting...");
-
- mutex->unlock();
- Thread::exit(nullptr);
-}
-
-void* ODBCStorageService::cleanup_fn(void* cache_p)
-{
- ODBCStorageService* cache = (ODBCStorageService*)cache_p;
-
-#ifndef WIN32
- // First, let's block all signals
- Thread::mask_all_signals();
-#endif
-
- // Now run the cleanup process.
- cache->cleanup();
- return nullptr;
-}
-
-void ODBCStorageService::updateContext(const char *table, const char* context, time_t expiration)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("updateContext");
-#endif
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- char timebuf[32];
- timestampFromTime(expiration, timebuf);
-
- char nowbuf[32];
- timestampFromTime(time(nullptr), nowbuf);
-
- SQLString scontext(context);
- string q = string("UPDATE ") + table + " SET expires = " + timebuf + " WHERE context='" + scontext.tostr() + "' AND expires > " + nowbuf;
-
- m_log.debug("SQL: %s", q.c_str());
-
- SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
- m_log.error("error updating records (t=%s, c=%s)", table, context ? context : "all");
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to update context expiration.");
- }
-}
-
-void ODBCStorageService::reap(const char *table, const char* context)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("reap");
-#endif
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- // Prepare and execute delete statement.
- char nowbuf[32];
- timestampFromTime(time(nullptr), nowbuf);
- string q;
- if (context) {
- SQLString scontext(context);
- q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "' AND expires <= " + nowbuf;
- }
- else {
- q = string("DELETE FROM ") + table + " WHERE expires <= " + nowbuf;
- }
- m_log.debug("SQL: %s", q.c_str());
-
- SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
- m_log.error("error expiring records (t=%s, c=%s)", table, context ? context : "all");
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to purge expired records.");
- }
-}
-
-void ODBCStorageService::deleteContext(const char *table, const char* context)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("deleteContext");
-#endif
-
- // Get statement handle.
- ODBCConn conn(getHDBC());
- SQLHSTMT stmt = getHSTMT(conn);
-
- // Prepare and execute delete statement.
- SQLString scontext(context);
- string q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "'";
- m_log.debug("SQL: %s", q.c_str());
-
- SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
- m_log.error("error deleting context (t=%s, c=%s)", table, context);
- log_error(stmt, SQL_HANDLE_STMT);
- throw IOException("ODBC StorageService failed to delete context.");
- }
-}
-
-extern "C" int ODBCSTORE_EXPORTS xmltooling_extension_init(void*)
-{
- // Register this SS type
- XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("ODBC", ODBCStorageServiceFactory);
- return 0;
-}
-
-extern "C" void ODBCSTORE_EXPORTS xmltooling_extension_term()
-{
- XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("ODBC");
-}
diff --git a/odbc-store/odbc-store.rc b/odbc-store/odbc-store.rc
deleted file mode 100644
index c080114e..00000000
--- a/odbc-store/odbc-store.rc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth ODBC Storage Service Plugin\0"
- VALUE "InternalName", "odbc-store\0"
- VALUE "OriginalFilename", "odbc-store.so\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/odbc-store/resource.h b/odbc-store/resource.h
deleted file mode 100644
index 3190f4a8..00000000
--- a/odbc-store/resource.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{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/selinux/Makefile.am b/selinux/Makefile.am
deleted file mode 100644
index f404e4d2..00000000
--- a/selinux/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-## $Id$
-
-AUTOMAKE_OPTIONS = foreign
-
-varrundir = $(localstatedir)/run
-BUILDFILES = shibshar.fc
-CLEANFILES = $(BUILDFILES)
-
-sepolicy = targeted
-selinuxdir = $(sysconfdir)/selinux/targeted/src/policy
-fcfiledir = $(selinuxdir)/file_contexts/program
-fcfile_DATA = shibshar.fc
-
-tefiledir = $(selinuxdir)/domains/program
-tefile_DATA = shibshar.te
-
-shibshar.fc: ${srcdir}/shibshar.fc.in Makefile ${top_builddir}/config.status
- rm -f $@.tmp
- sed < ${srcdir}/$@.in > $@.tmp \
- -e 's:@-SBINDIR-@:${sbindir}:' \
- -e 's:@-VARRUNDIR-@:${varrundir}:'
- cmp -s $@ $@.tmp || mv $@.tmp $@
- rm -f $@.tmp
-
-EXTRA_DIST = shibshar.fc.in shibshar.te
diff --git a/selinux/shibshar.fc.in b/selinux/shibshar.fc.in
deleted file mode 100644
index 34d9bd22..00000000
--- a/selinux/shibshar.fc.in
+++ /dev/null
@@ -1,4 +0,0 @@
-# Shibboleth SHAR
- at -SBINDIR-@/shibd -- system_u:object_r:shibshar_exec_t
- at -VARRUNDIR-@/shib-shar\.sock -s system_u:object_r:shibshar_var_run_t
-
diff --git a/selinux/shibshar.te b/selinux/shibshar.te
deleted file mode 100644
index 321da2e8..00000000
--- a/selinux/shibshar.te
+++ /dev/null
@@ -1,33 +0,0 @@
-# Shibboleth SHAR
-
-# Define the shibshar daemon.
-daemon_domain(shibshar)
-
-# Transition the shar socket to the shibshar_var_run_t type
-# when the shar creates it
-file_type_auto_trans(shibshar_t, var_run_t, shibshar_var_run_t, sock_file)
-
-# Enable the shar to work
-can_exec(shibshar_t, shibshar_exec_t)
-uses_shlib(shibshar_t)
-can_network(shibshar_t)
-can_tcp_connect(shibshar_t, unconfined_t)
-allow shibshar_t port_type:tcp_socket name_connect;
-allow shibshar_t etc_t:file r_file_perms;
-allow shibshar_t bin_t:dir r_dir_perms;
-allow shibshar_t bin_t:file rx_file_perms;
-allow shibshar_t var_log_t:dir rw_dir_perms;
-allow shibshar_t var_log_t:file rw_file_perms;
-allow shibshar_t var_log_t:file { create };
-
-allow shibshar_t shibshar_t:unix_stream_socket create_stream_socket_perms;
-allow shibshar_t shibshar_t:netlink_route_socket { create bind getattr};
-allow shibshar_t usr_t:dir r_dir_perms;
-allow shibshar_t usr_t:file rx_file_perms;
-
-allow shibshar_t urandom_device_t:chr_file { getattr ioctl read };
-
-# Enable HTTPD to connect to the shib-shar socket and read/write to it
-can_unix_connect(httpd_t, shibshar_var_run_t)
-allow httpd_t shibshar_var_run_t:sock_file { write };
-allow httpd_t shibshar_t:unix_stream_socket { connectto };
diff --git a/shibboleth.spec.in b/shibboleth.spec.in
deleted file mode 100644
index 3a9693e9..00000000
--- a/shibboleth.spec.in
+++ /dev/null
@@ -1,646 +0,0 @@
-Name: shibboleth
-Version: @PACKAGE_VERSION@
-Release: 1
-Summary: Open source system for attribute-based Web SSO
-Group: Productivity/Networking/Security
-Vendor: Shibboleth Consortium
-License: Apache-2.0
-URL: http://shibboleth.net/
-Source: %{name}-sp-%{version}.tar.bz2
-BuildRoot: %{_tmppath}/%{name}-sp-%{version}-root
-Obsoletes: shibboleth-sp = 2.5.0
-Requires: openssl
-%if 0%{?rhel} >= 6 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-PreReq: xmltooling-schemas%{?_isa} >= 3.2.0, opensaml-schemas%{?_isa} >= 3.2.0
-%else
-PreReq: xmltooling-schemas >= 3.2.0, opensaml-schemas >= 3.2.0
-%endif
-%if 0%{?suse_version} > 1030 && 0%{?suse_version} < 1130
-PreReq: %{insserv_prereq} %{fillup_prereq}
-%endif
-%if 0%{?rhel} >= 7
-Requires: hostname
-BuildRequires: systemd-devel
-%else
-Requires: net-tools
-%endif
-%if 0%{?rhel} >= 8
-BuildRequires: gdb
-%endif
-BuildRequires: libxerces-c-devel >= 3.2
-BuildRequires: libxml-security-c-devel >= 2.0.0
-BuildRequires: libxmltooling-devel >= 3.2.0
-BuildRequires: libsaml-devel >= 3.2.0
-%{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
-%{!?_with_log4cpp:BuildRequires: liblog4shib-devel >= 2}
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-Requires: libcurl-openssl%{?_isa} >= 7.21.7
-BuildRequires: chrpath
-%endif
-%if 0%{?suse_version} > 1300
-BuildRequires: libtool
-%endif
-BuildRequires: gcc-c++, pkgconfig, boost-devel >= 1.32.0
-%{!?_without_gssapi:BuildRequires: krb5-devel}
-%{!?_without_doxygen:BuildRequires: doxygen}
-%{!?_without_odbc:BuildRequires:unixODBC-devel}
-%{?_with_fastcgi:BuildRequires: fcgi-devel}
-%if 0%{?centos} == 6 || 0%{?centos} == 7
-BuildRequires: libmemcached-devel
-%endif
-%{?_with_memcached:BuildRequires: libmemcached-devel}
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-%if 0%{?rhel} >= 6 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-%{!?_without_builtinapache:BuildRequires: httpd-devel%{?_isa}}
-%else
-%{!?_without_builtinapache:BuildRequires: httpd-devel}
-%endif
-BuildRequires: redhat-rpm-config
-Requires(pre): shadow-utils
-Requires(post): chkconfig
-Requires(preun): chkconfig, initscripts
-%endif
-%if "%{_vendor}" == "suse"
-Requires(pre): pwdutils
-%{!?_without_builtinapache:BuildRequires: apache2-devel}
-%{?systemd_requires}
-%if 0%{?suse_version} >= 1210
-BuildRequires: systemd-rpm-macros, systemd-devel
-%endif
-%endif
-
-%{!?_tmpfilesdir:%global _tmpfilesdir /usr/lib/tmpfiles.d}
-
-%define runuser shibd
-%if "%{_vendor}" == "suse"
-%define pkgdocdir %{_docdir}/shibboleth
-%else
-%define pkgdocdir %{_docdir}/shibboleth-%{version}
-%endif
-
-%description
-Shibboleth is a Web Single Sign-On implementations based on OpenSAML
-that supports multiple protocols, federated identity, and the extensible
-exchange of rich attributes subject to privacy controls.
-
-This package contains the Shibboleth Service Provider runtime libraries,
-daemon, default plugins, and Apache module(s).
-
-%package devel
-Summary: Shibboleth Development Headers
-Group: Development/Libraries/C and C++
-Requires: %{name} = %{version}-%{release}
-Obsoletes: shibboleth-sp-devel = 2.5.0
-Requires: libxerces-c-devel >= 3.2
-Requires: libxml-security-c-devel >= 2.0.0
-Requires: libxmltooling-devel >= 3.2.0
-Requires: libsaml-devel >= 3.2.0
-%{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
-%{!?_with_log4cpp:Requires: liblog4shib-devel >= 2}
-
-%description devel
-Shibboleth is a Web Single Sign-On implementations based on OpenSAML
-that supports multiple protocols, federated identity, and the extensible
-exchange of rich attributes subject to privacy controls.
-
-This package includes files needed for development with Shibboleth.
-
-%prep
-%setup -n %{name}-sp-%{version}
-
-%build
-%if 0%{?suse_version} >= 1300
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_systemd:--enable-systemd} %{?shib_options} PKG_CONFIG_PATH=./pkgconfig-workarounds/opensuse13
-%else
-%if 0%{?suse_version} >= 1210
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_systemd:--enable-systemd} %{?shib_options}
-%else
-%if 0%{?rhel} >= 8
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with-memcached} %{!?_without_systemd:--enable-systemd} %{?shib_options}
-%else
-%if 0%{?rhel} >= 7
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_memcached:--with-memcached} %{!?_without_systemd:--enable-systemd} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig
-%else
-%if 0%{?centos} >= 6
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_memcached:--with-memcached} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig:./pkgconfig-workarounds/rh6
-%else
-%if 0%{?rhel} >= 6
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with-memcached} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig:./pkgconfig-workarounds/rh6
-%else
-%if 0%{?rhel} >= 5
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with_memcached} %{?shib_options} PKG_CONFIG_PATH=./pkgconfig-workarounds/rh5
-%else
- %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with_memcached} %{?shib_options}
-%endif
-%endif
-%endif
-%endif
-%endif
-%endif
-%endif
-%{__make} pkgdocdir=%{pkgdocdir}
-
-%install
-%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT pkgdocdir=%{pkgdocdir}
-
-%if "%{_vendor}" == "suse"
- %{__sed} -i "s/\/var\/log\/httpd/\/var\/log\/apache2/g" \
- $RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/native.logger
-%endif
-
-# Plug the SP into the built-in Apache on a recognized system.
-touch rpm.filelist
-APACHE_CONFIG="no"
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_13.so ] ; then
- APACHE_CONFIG="apache.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_20.so ] ; then
- APACHE_CONFIG="apache2.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_22.so ] ; then
- APACHE_CONFIG="apache22.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_24.so ] ; then
- APACHE_CONFIG="apache24.config"
-fi
-%{?_without_builtinapache:APACHE_CONFIG="no"}
-if [ "$APACHE_CONFIG" != "no" ] ; then
- APACHE_CONFD="no"
- if [ -d %{_sysconfdir}/httpd/conf.d ] ; then
- APACHE_CONFD="%{_sysconfdir}/httpd/conf.d"
- fi
- if [ -d %{_sysconfdir}/apache2/conf.d ] ; then
- APACHE_CONFD="%{_sysconfdir}/apache2/conf.d"
- fi
- if [ "$APACHE_CONFD" != "no" ] ; then
- %{__mkdir} -p $RPM_BUILD_ROOT$APACHE_CONFD
- %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/$APACHE_CONFIG $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf
- echo "%config(noreplace) $APACHE_CONFD/shib.conf" >> rpm.filelist
- fi
-fi
-
-# Establish location of systemd file, if any.
-SYSTEMD_SHIBD="no"
-%if 0%{?suse_version} >= 1210 || 0%{?rhel} >= 7
- %{__mkdir} -p $RPM_BUILD_ROOT%{_unitdir}
- echo "%attr(0444,-,-) %{_unitdir}/shibd.service" >> rpm.filelist
- SYSTEMD_SHIBD="$RPM_BUILD_ROOT%{_unitdir}/shibd.service"
-
- # Get run directory created at boot time.
- %{__mkdir} -p $RPM_BUILD_ROOT%{_tmpfilesdir}
- echo "%attr(0444,-,-) %{_tmpfilesdir}/%{name}.conf" >> rpm.filelist
- cat > $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf <<EOF
-d /run/%{name} 755 %{runuser} %{runuser} -
-EOF
-%endif
-
-# Otherwise, establish location of sysconfig file, if any.
-SYSCONFIG_SHIBD="no"
-if [ "$SYSTEMD_SHIBD" == "no" ] ; then
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
- %{__mkdir} -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
- echo "%config(noreplace) %{_sysconfdir}/sysconfig/shibd" >> rpm.filelist
- SYSCONFIG_SHIBD="$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/shibd"
-%endif
-%if "%{_vendor}" == "suse"
- %{__mkdir} -p $RPM_BUILD_ROOT%{_localstatedir}/adm/fillup-templates
- echo "%{_localstatedir}/adm/fillup-templates/sysconfig.shibd" >> rpm.filelist
- SYSCONFIG_SHIBD="$RPM_BUILD_ROOT%{_localstatedir}/adm/fillup-templates/sysconfig.shibd"
-%endif
-fi
-
-if [ "$SYSTEMD_SHIBD" != "no" ] ; then
- # Populate the systemd file
- cat > $SYSTEMD_SHIBD <<EOF
-[Unit]
-Description=Shibboleth Service Provider Daemon
-Documentation=https://wiki.shibboleth.net/confluence/display/SP3/Home
-After=network-online.target
-Before=httpd.service
-
-[Service]
-Type=notify
-NotifyAccess=main
-User=%{runuser}
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-Environment=LD_LIBRARY_PATH=/opt/shibboleth/%{_lib}
-%endif
-ExecStart=%{_sbindir}/shibd -f -F
-StandardInput=null
-StandardOutput=null
-StandardError=journal
-TimeoutStopSec=1m
-TimeoutStartSec=5m
-Restart=on-failure
-RestartSec=30s
-
-[Install]
-WantedBy=multi-user.target
-EOF
-elif [ "$SYSCONFIG_SHIBD" != "no" ] ; then
- # Populate the sysconfig file.
- cat > $SYSCONFIG_SHIBD <<EOF
-# Shibboleth SP init script customization
-
-# User account for shibd
-SHIBD_USER=%{runuser}
-
-# Umask for shibd
-# SHIBD_UMASK=022
-
-# Wait period (secs) for configuration (and metadata) to load
-SHIBD_WAIT=30
-EOF
- %if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
- cat >> $SYSCONFIG_SHIBD <<EOF
-
-# Override OS-supplied libcurl
-export LD_LIBRARY_PATH=/opt/shibboleth/%{_lib}
-EOF
- %endif
-fi
-
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
- # Strip existing rpath to libcurl.
- chrpath -d $RPM_BUILD_ROOT%{_sbindir}/shibd
- chrpath -d $RPM_BUILD_ROOT%{_bindir}/mdquery
- chrpath -d $RPM_BUILD_ROOT%{_bindir}/resolvertest
-%endif
-
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon" || "%{_vendor}" == "suse"
-if [ "$SYSTEMD_SHIBD" == "no" ] ; then
- # %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
- install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
- install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
-%if "%{_vendor}" == "suse"
- install -d -m 0755 $RPM_BUILD_ROOT/%{_sbindir}
- %{__ln_s} -f %{_initrddir}/shibd $RPM_BUILD_ROOT%{_sbindir}/rcshibd
-%endif
-fi
-%endif
-
-%check
-%{__make} check
-
-%clean
-[ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf $RPM_BUILD_ROOT
-
-%pre
-getent group %{runuser} >/dev/null || groupadd -r %{runuser}
-getent passwd %{runuser} >/dev/null || useradd -r -g %{runuser} \
- -d %{_localstatedir}/run/shibboleth -s /sbin/nologin -c "Shibboleth SP daemon" %{runuser}
-%if 0%{?suse_version} >= 1210
- %service_add_pre shibd.service
-%endif
-exit 0
-
-%post
-/sbin/ldconfig
-
-# Generate two keys on new installs.
-if [ $1 -eq 1 ] ; then
- cd %{_sysconfdir}/shibboleth
- /bin/sh ./keygen.sh -b -n sp-signing -u %{runuser} -g %{runuser}
- /bin/sh ./keygen.sh -b -n sp-encrypt -u %{runuser} -g %{runuser}
-fi
-
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-if [ $1 -gt 1 ] ; then
- # On Red Hat with shib.conf installed, clean up old Alias commands
- # by pointing them at new version-independent /usr/share/share tree.
- # Any Aliases we didn't create we assume are custom files.
- # This is to accomodate making shib.conf a noreplace config file.
- # We can't do this for SUSE, because they disallow changes to
- # packaged files in scriplets.
- APACHE_CONF="no"
- if [ -f %{_sysconfdir}/httpd/conf.d/shib.conf ] ; then
- APACHE_CONF="%{_sysconfdir}/httpd/conf.d/shib.conf"
- fi
- if [ "$APACHE_CONF" != "no" ] ; then
- %{__sed} -i "s/\/usr\/share\/doc\/shibboleth\(\-\(.\)\{1,\}\)\{0,1\}\/main\.css/\/usr\/share\/shibboleth\/main.css/g" \
- $APACHE_CONF
- %{__sed} -i "s/\/usr\/share\/doc\/shibboleth\(\-\(.\)\{1,\}\)\{0,1\}\/logo\.jpg/\/usr\/share\/shibboleth\/logo.jpg/g" \
- $APACHE_CONF
- fi
- fi
-
-%if 0%{?rhel} >= 7
- # Initial prep for systemd
- %systemd_post shibd.service
- if [ $1 -gt 1 ] ; then
- systemctl daemon-reload
- fi
-%else
- # Add the proper /etc/rc*.d links for the script
- /sbin/chkconfig --add shibd
-%endif
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
- %service_add_post shibd.service
- systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf
-%else
- # This adds the proper /etc/rc*.d links for the script
- # and populates the sysconfig/shibd file.
- cd /
- %{fillup_only -n shibd}
- %insserv_force_if_yast shibd
-%endif
-%endif
-
-%preun
-# On final removal, stop shibd and remove service, restart Apache if running.
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-%if 0%{?rhel} >= 7
- %systemd_preun shibd.service
-%else
- if [ $1 -eq 0 ] ; then
- /sbin/service shibd stop >/dev/null 2>&1
- /sbin/chkconfig --del shibd
- fi
-%endif
- if [ $1 -eq 0 ] ; then
- %{!?_without_builtinapache:/sbin/service httpd status 1>/dev/null && /sbin/service httpd restart 1>/dev/null}
- exit 0
- fi
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
- %service_del_preun shibd.service
-%else
- %stop_on_removal shibd
-%endif
- if [ $1 -eq 0 ] ; then
- %{!?_without_builtinapache:/sbin/service apache2 status 1>/dev/null && /sbin/service apache2 restart 1>/dev/null}
- exit 0
- fi
-%endif
-exit 0
-
-%postun
-/sbin/ldconfig
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-# On upgrade, restart components if they're already running.
-%if 0%{?rhel} >= 7
- %systemd_postun_with_restart shibd.service
-%else
- if [ $1 -ge 1 ] ; then
- /sbin/service shibd status 1>/dev/null && /sbin/service shibd restart 1>/dev/null
- fi
-%endif
- if [ $1 -ge 1 ] ; then
- %{!?_without_builtinapache:/sbin/service httpd status 1>/dev/null && /sbin/service httpd restart 1>/dev/null}
- exit 0
- fi
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
- %service_del_postun shibd.service
-%else
- cd /
- %restart_on_update shibd
- %{insserv_cleanup}
-%endif
- %{!?_without_builtinapache:%restart_on_update apache2}
-%endif
-
-%posttrans
-# One-time extra restart of shibd and Apache to work around
-# SUSE bug that breaks old %restart_on_update macro.
-# If we remove, upgrades from pre-systemd to post-systemd
-# will stop doing the final restart.
-%if "%{_vendor}" == "suse" && 0%{?suse_version} >= 1210
- /usr/bin/systemctl try-restart shibd >/dev/null 2>&1 || :
- /usr/bin/systemctl try-restart apache2 >/dev/null 2>&1 || :
-%endif
-exit 0
-
-%files -f rpm.filelist
-%defattr(-,root,root,-)
-%{_sbindir}/shibd
-%{_bindir}/mdquery
-%{_bindir}/resolvertest
-%{_libdir}/libshibsp.so.*
-%{_libdir}/libshibsp-lite.so.*
-%exclude %{_libdir}/*.la
-%dir %{_libdir}/shibboleth
-%{_libdir}/shibboleth/*.so
-%exclude %{_libdir}/shibboleth/*.la
-%{?_with_fastcgi:%{_libdir}/shibboleth/shibauthorizer}
-%{?_with_fastcgi:%{_libdir}/shibboleth/shibresponder}
-%attr(0750,%{runuser},%{runuser}) %dir %{_localstatedir}/log/shibboleth
-%if 0%{?suse_version} < 1300
-%attr(0755,%{runuser},%{runuser}) %dir %{_localstatedir}/run/shibboleth
-%endif
-%attr(0755,%{runuser},%{runuser}) %dir %{_localstatedir}/cache/shibboleth
-%dir %{_datadir}/xml/shibboleth
-%{_datadir}/xml/shibboleth/*
-%dir %{_datadir}/shibboleth
-%{_datadir}/shibboleth/*
-%dir %{_sysconfdir}/shibboleth
-%config(missingok, noreplace) %{_sysconfdir}/shibboleth/shibboleth2.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/attribute-map.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/attribute-policy.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/example-metadata.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/protocols.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/security-policy.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/*.html
-%config(noreplace) %{_sysconfdir}/shibboleth/*.logger
-%if "%{_vendor}" == "redhat"
-%if 0%{?rhel} >= 7
-%else
-%config %{_initrddir}/shibd
-%endif
-%endif
-%if "%{_vendor}" == "amazon"
-%config %{_initrddir}/shibd
-%endif
-%if "%{_vendor}" == "suse" && 0%{?suse_version} < 1210
-%config %{_initrddir}/shibd
-%{_sbindir}/rcshibd
-%endif
-%if 0%{?suse_version} >= 1210 || 0%{?rhel} >= 7
-%{_tmpfilesdir}/%{name}.conf
-%endif
-%{_sysconfdir}/shibboleth/example-shibboleth2.xml
-%{_sysconfdir}/shibboleth/*.dist
-%{_sysconfdir}/shibboleth/apache*.config
-%{_sysconfdir}/shibboleth/shibd-*
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/keygen.sh
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/metagen.sh
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/seckeygen.sh
-%doc %{pkgdocdir}
-%exclude %{pkgdocdir}/api
-
-%files devel
-%defattr(-,root,root,-)
-%{_includedir}/*
-%{_libdir}/libshibsp.so
-%{_libdir}/libshibsp-lite.so
-%{_libdir}/pkgconfig/*.pc
-%doc %{pkgdocdir}/api
-
-%changelog
-* Wed Nov 2 2022 Scott Cantor <cantor.2 at osu.edu> - 3.4.0-1
-- Version bump
-
-* Thu Apr 22 2021 Scott Cantor <cantor.2 at osu.edu> - 3.2.2-1
-- Fix devel dependency versions
-
-* Tue Dec 1 2020 Scott Cantor <cantor.2 at osu.edu> - 3.2.0-1
-- Version and lib bump
-
-* Mon Feb 3 2020 Scott Cantor <cantor.2 at osu.edu> - 3.1.0-1
-- Version and lib bump
-- Add hostname dependency for keygen script
-
-* Mon Sep 30 2019 Scott Cantor <cantor.2 at osu.edu> - 3.0.4-1
-- CentOS 8 cleanup
-
-* Mon Apr 30 2018 Scott Cantor <cantor.2 at osu.edu> - 3.0.0-1
-- Bump dependency versions
-- Require updated libraries across the board
-- Generate two keys on new installs
-
-* Tue May 03 2016 Scott Cantor <cantor.2 at osu.edu> - 2.6.0-1
-- Bump opensaml dependency version
-- Bump max wait time for shibd systemd unit file
-
-* Thu Jul 23 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.5-2
-- Fix use of /var/run/shibboleth on newer tmpfs platforms
-
-* Thu Jul 2 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.5-1
-- Revamp with systemd support for RH/CentOS 7+ and SUSE 12.1+
-
-* Mon Mar 9 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.4-1
-- Add Amazon VM support
-- Add a separate native logging directory
-- Remove hard-coded init.d usage
-- Switch to bz2 sources to prevent future issues with SuSE
-
-* Mon Nov 17 2014 Scott Cantor <cantor.2 at osu.edu> - 2.5.3-2
-- Add libtool dep for OpenSUSE 13
-- Remove /var/run/shibboleth for OpenSUSE 13
-
-* Tue May 13 2014 Ian Young <ian at iay.org.uk> - 2.5.3-1.2
-- Update package dependencies for RHEL/CentOS 7
-- Fix bogus dates in changelog
-
-* Sat Jun 8 2013 Scott Cantor <cantor.2 at osu.edu> - 2.5.2-1
-- Add --with-gssapi using MIT K5 by default
-
-* Tue Sep 25 2012 Scott Cantor <cantor.2 at osu.edu> - 2.5.1-1
-- Merge back various changes used in released packages
-- Prep for 2.5.1 by pulling extra restart out
-
-* Tue Aug 7 2012 Scott Cantor <cantor.2 at osu.edu> - 2.5.0-2
-- Changed package name back to shibboleth because of upgrade bugs
-- Put back extra restart for this release only.
-
-* Thu Mar 1 2012 Scott Cantor <cantor.2 at osu.edu> - 2.5.0-1
-- Move logo and stylesheet to version-independent tree
-- Make shib.conf noreplace
-- Post-fixup of Alias commands in older shib.conf
-- Changes to run shibd as non-root shibboleth user
-- Move init customizations to /etc/sysconfig/shibd
-- Copy shibd restart for Red Hat to postun
-- Add boost-devel dependency
-- Build memcache plugin on RH6
-- Add cachedir to install
-- Add Apache 2.4 to install
-
-* Sun Jun 26 2011 Scott Cantor <cantor.2 at osu.edu> - 2.4.3-1
-- Log files shouldn't be world readable.
-- Explicit requirement for libcurl-openssl on RHEL6
-- Uncomment LD_LIBRARY_PATH in init script for RHEL6
-- Remove rpath from binaries for RHEL6
-
-* Fri Dec 25 2009 Scott Cantor <cantor.2 at osu.edu> - 2.4-1
-- Update dependencies.
-
-* Mon Nov 23 2009 Scott Cantor <cantor.2 at osu.edu> - 2.3.1-1
-- Reset revision for 2.3.1 release
-
-* Wed Aug 19 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2.1-2
-- SuSE init script changes
-- Restart Apache on removal, not just upgrade
-- Fix scriptlet exit values when Apache is stopped
-
-* Mon Aug 10 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2.1-1
-- Doc handling changes
-- SuSE init script
-
-* Tue Aug 4 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2.1-1
-- Initial version for 2.2.1, with shibd/httpd restart on upgrade
-
-* Thu Jun 25 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-3
-- Add additional cleanup to posttrans fix
-
-* Tue Jun 23 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-2
-- Reverse without_builtinapache macro test
-- Fix init script handling on Red Hat to handle upgrades
-
-* Wed Dec 3 2008 Scott Cantor <cantor.2 at osu.edu> - 2.2-1
-- Bump minor version.
-- Make keygen.sh executable.
-- Fixing SUSE Xerces dependency name.
-- Optionally package shib.conf.
-
-* Tue Jun 10 2008 Scott Cantor <cantor.2 at osu.edu> - 2.1-1
-- Change shib.conf handling to treat as config file.
-
-* Mon Mar 17 2008 Scott Cantor <cantor.2 at osu.edu> - 2.0-6
-- Official release.
-
-* Fri Jan 18 2008 Scott Cantor <cantor.2 at osu.edu> - 2.0-5
-- Release candidate 1.
-
-* Sun Oct 21 2007 Scott Cantor <cantor.2 at osu.edu> - 2.0-4
-- libexec -> lib/shibboleth changes
-- Added doc subpackage
-
-* Thu Aug 16 2007 Scott Cantor <cantor.2 at osu.edu> - 2.0-3
-- First public beta.
-
-* Fri Jul 13 2007 Scott Cantor <cantor.2 at osu.edu> - 2.0-2
-- Second alpha release.
-
-* Sun Jun 10 2007 Scott Cantor <cantor.2 at osu.edu> - 2.0-1
-- First alpha release.
-
-* Mon Oct 2 2006 Scott Cantor <cantor.2 at osu.edu> - 1.3-11
-- Applied fix for secadv 20061002
-- Fix for metadata loader loop
-
-* Thu Jun 15 2006 Scott Cantor <cantor.2 at osu.edu> - 1.3-10
-- Applied fix for sec 20060615
-
-* Sat Apr 15 2006 Scott Cantor <cantor.2 at osu.edu> - 1.3-9
-- Misc. patches, SuSE, Apache 2.2, gcc 4.1, and 64-bit support
-
-* Mon Jan 9 2006 Scott Cantor <cantor.2 at osu.edu> - 1.3-8
-- Applied new fix for secadv 20060109
-
-* Tue Nov 8 2005 Scott Cantor <cantor.2 at osu.edu> - 1.3-7
-- Applied new fix for secadv 20050901 plus rollup
-
-* Fri Sep 23 2005 Scott Cantor <cantor.2 at osu.edu> - 1.3-6
-- Minor patches and default config changes
-- pidfile patch
-- Fix shib.conf creation
-- Integrated init.d script
-- Prevent replacement of config files
-
-* Thu Sep 1 2005 Scott Cantor <cantor.2 at osu.edu> - 1.3-5
-- Applied fix for secadv 20050901 plus rollup of NSAPI fixes
-
-* Sun Apr 24 2005 Scott Cantor <cantor.2 at osu.edu> - 1.3-1
-- Updated test programs and location of schemas.
-- move siterefresh to to sbindir
-
-* Fri Apr 1 2005 Derek Atkins <derek at ihtfp.com> - 1.3-1
-- Add selinux-targeted-policy package
-- move shar to sbindir
-
-* Tue Oct 19 2004 Derek Atkins <derek at ihtfp.com> - 1.2-1
-- Create SPEC file based on various versions in existence.
diff --git a/shibd/Makefile.am b/shibd/Makefile.am
deleted file mode 100644
index 596de41f..00000000
--- a/shibd/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-sbin_PROGRAMS = shibd
-
-shibd_SOURCES = shibd.cpp
-
-shibd_CXXFLAGS = \
- $(AM_CXXFLAGS) \
- $(PTHREAD_CFLAGS) \
- $(SYSTEMD_CFLAGS) \
- $(opensaml_CFLAGS) \
- $(xerces_CFLAGS) \
- $(xmltooling_CFLAGS)
-shibd_LDADD = \
- $(top_builddir)/shibsp/libshibsp.la \
- $(PTHREAD_LIBS) \
- $(SYSTEMD_LIBS) \
- $(opensaml_LIBS) \
- $(xerces_LIBS) \
- $(xmltooling_LIBS)
-
-EXTRA_DIST = shibd_win32.cpp resource.h shibd.rc
diff --git a/shibd/resource.h b/shibd/resource.h
deleted file mode 100644
index b5e13998..00000000
--- a/shibd/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by shibd.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/shibd/shibd.cpp b/shibd/shibd.cpp
deleted file mode 100644
index 5a31f7e1..00000000
--- a/shibd/shibd.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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.
- */
-
-/*
- * shibd.cpp -- the shibd "main" code.
- */
-
-
-// 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 <shibsp/SPConfig.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# include <sys/select.h>
-#endif
-
-#if defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
-# include <pwd.h>
-# include <grp.h>
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-#include <shibsp/ServiceProvider.h>
-#include <shibsp/remoting/ListenerService.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifdef HAVE_SD_NOTIFY
-#include <systemd/sd-daemon.h>
-#else
-#define SD_EMERG ""
-#define SD_ALERT ""
-#define SD_CRIT ""
-#define SD_ERR ""
-#define SD_WARNING ""
-#define SD_NOTICE ""
-#define SD_INFO ""
-#define SD_DEBUG ""
-#endif
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace std;
-
-bool shibd_shutdown = false;
-const char* shar_config = nullptr;
-const char* shar_schemadir = nullptr;
-const char* shar_prefix = nullptr;
-bool shar_checkonly = false;
-bool shar_version = false;
-static bool unlink_socket = false;
-const char* pidfile = nullptr;
-
-#ifdef WIN32
-
-//#include <CRTDBG.H>
-
-#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)
-{
- if (shar_version) {
- if (preinit)
- fprintf(stdout, PACKAGE_STRING"\n");
- return 0;
- }
-
- 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 or log for specific problems\n");
- return -1;
- }
-
- if (!conf.instantiate(shar_config)) {
- fprintf(stderr, "configuration is invalid, check console or log 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 or log 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;
-const char* runasuser = nullptr;
-const char* runasgroup = nullptr;
-
-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, nullptr) < 0) {
- return -1;
- }
-
- memset(&sa, 0, sizeof (sa));
- sa.sa_handler = term_handler;
- sa.sa_flags = SA_RESTART;
-
- if (sigaction(SIGHUP, &sa, nullptr) < 0) {
- return -1;
- }
- if (sigaction(SIGINT, &sa, nullptr) < 0) {
- return -1;
- }
- if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
- return -1;
- }
- if (sigaction(SIGTERM, &sa, nullptr) < 0) {
- return -1;
- }
-
- if (daemonize) {
- memset(&sa, 0, sizeof (sa));
- sa.sa_handler = run_handler;
-
- if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
- return -1;
- }
-
- memset(&sa, 0, sizeof (sa));
- sa.sa_handler = child_handler;
-
- if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
- return -1;
- }
- }
-
- return 0;
-}
-
-static void usage(char* whoami)
-{
- fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\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, " -u\tuser to run under\n");
- fprintf(stderr, " -g\tgroup to run under\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:u:g: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;
- case 'u':
- if (optarg)
- runasuser = optarg;
- break;
- case 'g':
- if (optarg)
- runasgroup = optarg;
- 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;
-
- if (runasgroup) {
-#ifdef HAVE_GETGRNAM
- struct group* grp = getgrnam(runasgroup);
- if (!grp) {
- fprintf(stderr, "getgrnam failed, check -g option\n");
- return -1;
- }
- if (setgid(grp->gr_gid) != 0) {
- fprintf(stderr, "setgid failed, check -g option\n");
- return -1;
- }
-#else
- fprintf(stderr, "-g not supported on this platform");
- return -1;
-#endif
- }
-
- if (runasuser) {
-#ifdef HAVE_GETPWNAM
- struct passwd* pwd = getpwnam(runasuser);
- if (!pwd) {
- fprintf(stderr, "getpwnam failed, check -u option\n");
- return -1;
- }
-#ifdef HAVE_INITGROUPS
- // w/out initgroups/setgroups process retains supplementary groups
- if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
- fprintf(stderr, "initgroups failed, check -u option\n");
- return -1;
- }
-#endif
- if (setuid(pwd->pw_uid) != 0) {
- fprintf(stderr, "setuid failed, check -u option\n");
- return -1;
- }
-#else
- fprintf(stderr, "-u not supported on this platform");
- return -1;
-#endif
- }
-
- // 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, SD_ERR "configuration is invalid, check console or log 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, SD_ERR "configuration is invalid, check console or log for specific problems\n");
- conf.term();
- return -2;
- }
-
- if (shar_checkonly)
- fprintf(stderr, "overall configuration is loadable, check console or log for non-fatal problems\n");
- else {
- // Init the listener.
- ListenerService* listener = conf.getServiceProvider()->getListenerService();
- if (!listener->init(unlink_socket)) {
- fprintf(stderr, SD_ERR "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.
-#ifdef HAVE_SD_NOTIFY
- sd_notify(0, "READY=1");
-#endif
- if (!listener->run(&shibd_shutdown)) {
- fprintf(stderr, SD_ERR "listener failure during service\n");
- listener->term();
- conf.term();
- if (daemonize && pidfile)
- unlink(pidfile);
- return -3;
- }
- listener->term();
- }
-#ifdef HAVE_SD_NOTIFY
- sd_notify(0, "STOPPING=1");
-#endif
- conf.term();
- if (daemonize && pidfile)
- unlink(pidfile);
- return 0;
-}
-
-#endif
diff --git a/shibd/shibd.rc b/shibd/shibd.rc
deleted file mode 100644
index 32650888..00000000
--- a/shibd/shibd.rc
+++ /dev/null
@@ -1,101 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
-#include "..\util\resourceCommon.rci"
- VALUE "FileDescription", "Shibboleth Daemon Service\0"
- VALUE "InternalName", "shibd\0"
- VALUE "OriginalFilename", "shibd.exe\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/shibd/shibd_win32.cpp b/shibd/shibd_win32.cpp
deleted file mode 100644
index 4d88a570..00000000
--- a/shibd/shibd_win32.cpp
+++ /dev/null
@@ -1,550 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you 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
- */
-
-#include "config_win32.h"
-
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#define _CRT_SECURE_NO_DEPRECATE 1
-
-#include <shibsp/base.h>
-#include <xmltooling/logging.h>
-
-#include <string>
-#include <windows.h>
-
-using namespace std;
-
-using xmltooling::logging::Priority;
-using xmltooling::logging::Category;
-
-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;
-extern bool shar_version;
-
-// 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 = nullptr;
-LPCSTR lpszRemove = nullptr;
-LPCSTR lpszStdout = nullptr;
-LPCSTR lpszStderr = nullptr;
-
-// 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(
- WORD wType,
- Priority::PriorityLevel priority,
- DWORD dwEventID,
- LPCTSTR message);
-
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
-VOID ServiceStop();
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
-
-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 shibd.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("stdout", argv[i]+1) == 0)
- {
- if (argc > ++i) {
- lpszStdout = argv[i++];
- freopen(lpszStdout, "a+", stdout);
- }
- }
- else if (_stricmp("stderr", argv[i]+1) == 0)
- {
- if (argc > ++i) {
- lpszStderr = argv[i++];
- freopen(lpszStderr, "a+", stderr);
- }
- }
- 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( "version", argv[i]+1) == 0)
- {
- i++;
- bConsole = TRUE;
- shar_version = 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)
- {
- Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("daemon startup failed, check log for 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 <name> to install the named service\n", argv[0]);
- printf("%s -remove <name> 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("%s -version to run as a console app and print the version\n", argv[0]);
- printf("\t-stdout <path> to redirect stdout stream\n");
- printf("\t-stderr <path> to redirect stderr stream\n");
- printf("\t-prefix <dir> to specify the installation directory\n");
- printf("\t-config <file> to specify the config file to use\n");
- printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");
- printf("\nService starting.\nThis may take several seconds. Please wait.\n" );
-
- static char svcname[] = "SHIBD";
-
- SERVICE_TABLE_ENTRY dispatchTable[] =
- {
- { svcname, (LPSERVICE_MAIN_FUNCTION)service_main },
- { nullptr, nullptr }
- };
-
- if (!StartServiceCtrlDispatcher(dispatchTable))
- Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("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)
- {
- Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("daemon startup failed, check log for details");
- return;
- }
-
- Category::getInstance(SHIBSP_LOGCAT ".shibd").info("daemon service startup complete");
-
- if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
- return;
-
- real_main(0);
-}
-
-
-//
-// FUNCTION: ServiceStop
-//
-// PURPOSE: Stops the service
-//
-VOID ServiceStop()
-{
- if (!bConsole)
- Category::getInstance(SHIBSP_LOGCAT ".shibd").info("daemon service 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)))
- Category::getInstance(SHIBSP_LOGCAT ".shibd").error("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( nullptr, szPath, 256 ) == 0 )
- {
- printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
- return;
- }
-
- string dispName = string("Shibboleth SP 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;
- if (lpszStdout)
- cmd = cmd + " -stdout " + lpszStdout;
- if (lpszStderr)
- cmd = cmd + " -stderr " + lpszStderr;
-
- schSCManager = OpenSCManager(
- nullptr, // machine (nullptr == local)
- nullptr, // database (nullptr == 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
- nullptr, // no load ordering group
- nullptr, // no tag identifier
- nullptr, // dependencies
- nullptr, // LocalSystem account
- nullptr); // 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(
- nullptr, // machine (nullptr == local)
- nullptr, // database (nullptr == 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 = nullptr;
-
- dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
- nullptr,
- GetLastError(),
- LANG_NEUTRAL,
- (LPSTR)&lpszTemp,
- 0,
- nullptr );
-
- // 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;
-}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list