AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
PortSystem 1.0
name shibboleth
-version 2.2.1
+version 2.3
categories security www shibboleth
maintainers scantor snc
description Shibboleth Native Service Provider
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = adfs.la adfs-lite.la\r
-\r
-adfs_la_LIBADD = \\r
- $(top_builddir)/shibsp/libshibsp.la\r
-\r
-adfs_la_SOURCES = \\r
- adfs.cpp\r
-\r
-adfs_lite_la_LIBADD = \\r
- $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-adfs_lite_la_SOURCES = \\r
- adfs.cpp\r
-\r
-adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)\r
-adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE\r
-\r
-install-exec-hook:\r
- for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = adfs.la adfs-lite.la
+
+adfs_la_LIBADD = \
+ $(top_builddir)/shibsp/libshibsp.la
+
+adfs_la_SOURCES = \
+ adfs.cpp
+
+adfs_lite_la_LIBADD = \
+ $(top_builddir)/shibsp/libshibsp-lite.la
+
+adfs_lite_la_SOURCES = \
+ adfs.cpp
+
+adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)
+adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE
+
+install-exec-hook:
+ for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
# define ADFS_EXPORTS
#endif
-#include <memory>
-
#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/handler/AssertionConsumerService.h>
#include <shibsp/handler/LogoutHandler.h>
#include <shibsp/handler/SessionInitiator.h>
#include <xmltooling/logging.h>
+#include <xmltooling/util/DateTime.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/URLEncoder.h>
#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
+#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/saml1/profile/AssertionValidator.h>
# include <saml/saml2/core/Assertions.h>
# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/EndpointManager.h>
-# include <saml/saml2/profile/AssertionValidator.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
{
public:
ADFSSessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS")), m_appId(appId), m_binding(WSFED_NS) {
+ : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS"), NULL, &m_remapper), m_appId(appId), m_binding(WSFED_NS) {
// If Location isn't set, defer address registration until the setParent call.
pair<bool,const char*> loc = getString("Location");
if (loc.first) {
if (option) {
ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
}
option = request.getParameter("target");
acClass = getString("authnContextClassRef");
}
- // Since we're not passing by index, we need to fully compute the return URL.
if (!ACS) {
- pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+ pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
if (index.first) {
ACS = app.getAssertionConsumerServiceByIndex(index.second);
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
+ }
+ if (!ACS) {
+ const vector<const Handler*>& endpoints = app.getAssertionConsumerServicesByBinding(m_binding.get());
+ if (endpoints.empty()) {
+ m_log.error("unable to locate a compatible ACS");
+ throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration.");
+ }
+ ACS = endpoints.front();
}
- if (!ACS)
- ACS = app.getDefaultAssertionConsumerService();
}
// Validate the ACS for use with this protocol.
- pair<bool,const XMLCh*> ACSbinding = ACS ? ACS->getXMLString("Binding") : pair<bool,const XMLCh*>(false,NULL);
+ pair<bool,const XMLCh*> ACSbinding = ACS->getXMLString("Binding");
if (ACSbinding.first) {
if (!XMLString::equals(ACSbinding.second, m_binding.get())) {
- m_log.info("configured or requested ACS has non-ADFS binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-ADFS binding");
+ throw ConfigurationException("Configured or requested ACS has non-ADFS binding ($1).", params(1, ACSbinding.second));
}
}
+ // 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());
- pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
+ pair<bool,const char*> loc=ACS->getString("Location");
if (loc.first) ACSloc+=loc.second;
if (isHandler) {
// 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()) : NULL;
+ 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.
+ // 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.");
- time_t now = time(NULL);
-
- const PropertySet* sessionProps = application.getPropertySet("Sessions");
- const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
-
saml1::NameIdentifier* saml1name=NULL;
saml2::NameID* saml2name=NULL;
const XMLCh* authMethod=NULL;
const XMLCh* authInstant=NULL;
- time_t sessionExp = 0;
+ time_t now = time(NULL), sessionExp = 0;
+ const PropertySet* sessionProps = application.getPropertySet("Sessions");
const saml1::Assertion* saml1token = dynamic_cast<const saml1::Assertion*>(token);
if (saml1token) {
- // Now do profile and core semantic validation to ensure we can use it for SSO.
- saml1::AssertionValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now);
- ssoValidator.validateAssertion(*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())
if (!saml2token)
throw FatalProfileException("Incoming message did not contain a recognized type of SAML assertion.");
- // Now do profile and core semantic validation to ensure we can use it for SSO.
- saml2::AssertionValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now);
- ssoValidator.validateAssertion(*saml2token);
+ // 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())
if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
session->unlock();
application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
- return sendLogoutPage(application, httpRequest, httpResponse, true, "Partial logout failure.");
+ return sendLogoutPage(application, httpRequest, httpResponse, "partial");
}
#ifndef SHIBSP_LITE
).getByBinding(m_binding.get());
if (!ep) {
throw MetadataException(
- "Unable to locate ADFS single logout service for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID())
+ "Unable to locate ADFS single logout service for identity provider ($entityID).",
+ namedparams(1, "entityID", session->getEntityID())
);
}
if (param)
return make_pair(true, request.sendRedirect(param));
- return sendLogoutPage(app, request, request, false, "Logout complete.");
+ return sendLogoutPage(app, request, request, "global");
}
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
FILEFLAGSMASK 0x3fL\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
VALUE "Comments", "\0"\r
VALUE "CompanyName", "Internet2\0"\r
VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"\r
- VALUE "FileVersion", "2, 2, 1, 0\0"\r
+ VALUE "FileVersion", "2, 3, 0, 0\0"\r
#ifdef SHIBSP_LITE\r
VALUE "InternalName", "adfs-lite\0"\r
#else\r
VALUE "OriginalFilename", "adfs.so\0"\r
#endif\r
VALUE "PrivateBuild", "\0"\r
- VALUE "ProductName", "Shibboleth 2.2.1\0"\r
- VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+ VALUE "ProductName", "Shibboleth 2.3\0"\r
+ VALUE "ProductVersion", "2, 3, 0, 0\0"\r
VALUE "SpecialBuild", "\0"\r
END\r
END\r
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by adfs.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 101\r
-#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1000\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+//{{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
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
#include <apr_pools.h>
#endif
+#include <set>
#include <memory>
#include <fstream>
#include <sstream>
m_req->content_type = ap_psprintf(m_req->pool, type);
}
void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
#ifdef SHIB_DEFERRED_HEADERS
if (!m_rc)
// this happens on subrequests
return DONE;
}
long sendRedirect(const char* url) {
+ HTTPResponse::sendRedirect(url);
ap_table_set(m_req->headers_out, "Location", url);
return REDIRECT;
}
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..;\Apache2\include;"..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;"..\..\cpp-xmltooling""
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
StringPooling="true"
RuntimeLibrary="2"
OutputFile="$(OutDir)\mod_shib_20.so"
LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2\lib"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.0.63\Apache2\lib"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="..;\Apache2\include;"..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;"..\..\cpp-xmltooling""
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
StringPooling="true"
RuntimeLibrary="2"
OutputFile="$(OutDir)\mod_shib_20.so"
LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2\lib"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2.0.63\Apache2\lib"
ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..;\Apache2\include;"..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;"..\..\cpp-xmltooling""
PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
OutputFile="$(OutDir)\mod_shib_20.so"
LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2\lib"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.0.63\Apache2\lib"
GenerateDebugInformation="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..;\Apache2\include;"..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;"..\..\cpp-xmltooling""
PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
OutputFile="$(OutDir)\mod_shib_20.so"
LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2\lib"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2.0.63\Apache2\lib"
GenerateDebugInformation="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
Name="VCCLCompilerTool"\r
Optimization="2"\r
InlineFunctionExpansion="1"\r
- AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""\r
+ AdditionalIncludeDirectories="..;\Apache2.2.14\include;"..\..\cpp-xmltooling""\r
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
StringPooling="true"\r
RuntimeLibrary="2"\r
OutputFile="$(OutDir)\mod_shib_22.so"\r
LinkIncremental="1"\r
SuppressStartupBanner="true"\r
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2\lib"\r
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2.14\lib"\r
RandomizedBaseAddress="1"\r
DataExecutionPrevention="0"\r
TargetMachine="1"\r
Name="VCCLCompilerTool"\r
Optimization="2"\r
InlineFunctionExpansion="1"\r
- AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""\r
+ AdditionalIncludeDirectories="..;\httpd-2.2-x64\include;"..\..\cpp-xmltooling""\r
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
StringPooling="true"\r
RuntimeLibrary="2"\r
<Tool\r
Name="VCCLCompilerTool"\r
Optimization="0"\r
- AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""\r
+ AdditionalIncludeDirectories="..;\Apache2.2.14\include;"..\..\cpp-xmltooling""\r
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
MinimalRebuild="true"\r
BasicRuntimeChecks="3"\r
OutputFile="$(OutDir)\mod_shib_22.so"\r
LinkIncremental="2"\r
SuppressStartupBanner="true"\r
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2\lib"\r
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2.14\lib"\r
GenerateDebugInformation="true"\r
RandomizedBaseAddress="1"\r
DataExecutionPrevention="0"\r
<Tool\r
Name="VCCLCompilerTool"\r
Optimization="0"\r
- AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""\r
+ AdditionalIncludeDirectories="..;\httpd-2.2-x64\include;"..\..\cpp-xmltooling""\r
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
MinimalRebuild="true"\r
BasicRuntimeChecks="3"\r
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth Apache 1.3 Module\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "mod_shib_13\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "mod_shib_13.so\0"
VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth Apache 2.0 Module\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "mod_shib_20\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "mod_shib_20.so\0"
VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth Apache 2.2 Module\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "mod_shib_22\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "mod_shib_22.so\0"
VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-timestamp='2005-07-08'
+timestamp='2003-06-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
-
# Originally written by Per Bothner <per@bothner.com>.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
+ echo "$timestamp" ; exit 0 ;;
--version | -v )
- echo "$version" ; exit ;;
+ echo "$version" ; exit 0 ;;
--help | --h* | -h )
- echo "$usage"; exit ;;
+ echo "$usage"; exit 0 ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+esac ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+ VENDOR=redhat ;
+else
+ VENDOR= ;
+fi
+
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
- exit ;;
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
*:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
- macppc:MirBSD:*:*)
- echo powerppc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
+ if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
+ fi
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
- # A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha*:OpenVMS:*:*)
+ echo alpha-hp-vms
+ exit 0 ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
- exit ;;
+ exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
- exit ;;
+ exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
- exit ;;
+ exit 0;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
+ exit 0 ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
+ exit 0 ;;
*:OS/390:*:*)
echo i370-ibm-openedition
- exit ;;
- *:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
+ exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
+ exit 0;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
- exit ;;
+ exit 0;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
else
echo pyramid-pyramid-bsd
fi
- exit ;;
+ exit 0 ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
- exit ;;
+ exit 0 ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
- exit ;;
- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
esac ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ exit 0 ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
+ exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
- exit ;;
+ exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
- exit ;;
+ exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
- { echo "$SYSTEM_NAME"; exit; }
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
- exit ;;
+ exit 0 ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
- exit ;;
+ exit 0 ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
- exit ;;
+ exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
- exit ;;
+ exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
- exit ;;
+ exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
- exit ;;
+ exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
- exit ;;
+ exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
- exit ;;
+ exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
- exit ;;
+ exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
- exit ;;
+ exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
- exit ;;
+ exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
- exit ;;
+ exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
+ exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
- exit ;;
+ exit 0 ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
+ exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
exit(0);
}
EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
- then
- echo "$SYSTEM_NAME"
- else
- echo rs6000-ibm-aix3.2.5
- fi
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
- exit ;;
+ exit 0 ;;
*:AIX:*:[45])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
+ exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
- exit ;;
+ exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
- exit ;;
+ exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
+ exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
- exit ;;
+ exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
- exit ;;
+ exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
- exit ;;
+ exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
- exit ;;
+ exit 0 ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
- eval $set_cc_for_build
-
- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
- # generating 64-bit code. GNU and HP use different nomenclature:
- #
- # $ CC_FOR_BUILD=cc ./config.guess
- # => hppa2.0w-hp-hpux11.23
- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
- # => hppa64-hp-hpux11.23
-
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep __LP64__ >/dev/null
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
then
HP_ARCH="hppa2.0w"
else
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
+ exit 0 ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
- exit ;;
+ exit 0 ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
echo unknown-hitachi-hiuxwe2
- exit ;;
+ exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
- exit ;;
+ exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
- exit ;;
+ exit 0 ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
- exit ;;
+ exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
- exit ;;
+ exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
- exit ;;
+ exit 0 ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
- exit ;;
+ exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
- exit ;;
+ exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
- exit ;;
+ exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit ;;
+ exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
- exit ;;
+ exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
- exit ;;
+ exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
- exit ;;
+ exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ exit 0 ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
- exit ;;
+ exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ exit 0 ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ exit 0 ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ exit 0 ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ exit 0 ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:FreeBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
+ exit 0 ;;
+ *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
+ exit 0 ;;
i*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
+ exit 0 ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
+ exit 0 ;;
x86:Interix*:[34]*)
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
- exit ;;
+ exit 0 ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
- exit ;;
+ exit 0 ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
- exit ;;
+ exit 0 ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
+ exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
- exit ;;
+ exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
+ exit 0 ;;
*:GNU:*:*)
- # the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit ;;
+ exit 0 ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
- exit ;;
+ exit 0 ;;
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
- exit ;;
- crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
- exit ;;
- frv:Linux:*:*)
- echo frv-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
mips:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
;;
mips64:Linux:*:*)
eval $set_cc_for_build
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit ;;
+ echo powerpc-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit ;;
+ echo powerpc64-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit ;;
+ exit 0 ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
esac
- exit ;;
+ exit 0 ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit ;;
+ echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
+ exit 0 ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
+ exit 0 ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
- exit ;;
+ echo x86_64-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
- exit ;;
+ exit 0 ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
- exit ;;
+ exit 0 ;;
"")
# Either a pre-BFD a.out linker (linux-gnuoldld) or
# one that does not give us useful --help.
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
- exit ;;
+ exit 0 ;;
esac
# Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
LIBC=gnuaout
#endif
#endif
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- test x"${LIBC}" != x && {
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit
- }
- test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
- exit ;;
+ exit 0 ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
+ exit 0 ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
+ exit 0 ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
+ exit 0 ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
+ exit 0 ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
+ exit 0 ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
- exit ;;
- i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ exit 0 ;;
+ i*86:*:5:[78]*)
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
+ exit 0 ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
- exit ;;
+ exit 0 ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
echo i386-pc-msdosdjgpp
- exit ;;
+ exit 0 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
- exit ;;
+ exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
- exit ;;
+ exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
- exit ;;
+ exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
- exit ;;
+ exit 0 ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
- exit ;;
+ exit 0 ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
- exit ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
+ && echo i486-ncr-sysv4 && exit 0 ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
- exit ;;
+ exit 0 ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
- exit ;;
+ exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
- exit ;;
+ exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
else
echo ns32k-sni-sysv
fi
- exit ;;
+ exit 0 ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
- exit ;;
+ exit 0 ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
- exit ;;
+ exit 0 ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
+ exit 0 ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
- exit ;;
+ exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
- exit ;;
+ exit 0 ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
- exit ;;
+ exit 0 ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
- exit ;;
+ exit 0 ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
- exit ;;
+ exit 0 ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
- exit ;;
+ exit 0 ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
+ case `uname -p` in
*86) UNAME_PROCESSOR=i686 ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
+ powerpc) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:QNX:*:4*)
echo i386-pc-qnx
- exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
+ exit 0 ;;
+ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
- exit ;;
+ exit 0 ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
- exit ;;
+ exit 0 ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
+ exit 0 ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
+ exit 0 ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
- exit ;;
+ exit 0 ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
- exit ;;
+ exit 0 ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
- exit ;;
+ exit 0 ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
- exit ;;
+ exit 0 ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
- exit ;;
+ exit 0 ;;
*:ITS:*:*)
echo pdp10-unknown-its
- exit ;;
+ exit 0 ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
- esac ;;
- *:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
- i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
+ exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
+ printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
}
EOF
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
# Apollos put the system type in the environment.
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
- exit ;;
+ exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit ;;
+ exit 0 ;;
c34*)
echo c34-convex-bsd
- exit ;;
+ exit 0 ;;
c38*)
echo c38-convex-bsd
- exit ;;
+ exit 0 ;;
c4*)
echo c4-convex-bsd
- exit ;;
+ exit 0 ;;
esac
fi
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
-and
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+ ftp://ftp.gnu.org/pub/gnu/config/
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define if xmltooling library was found */
+#undef HAVE_XMLTOOLING
+
/* Name of package */
#undef PACKAGE
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-timestamp='2005-07-08'
+timestamp='2003-06-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
-
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
+ echo "$timestamp" ; exit 0 ;;
--version | -v )
- echo "$version" ; exit ;;
+ echo "$version" ; exit 0 ;;
--help | --h* | -h )
- echo "$usage"; exit ;;
+ echo "$usage"; exit 0 ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
*local*)
# First pass through any local machine types.
echo $1
- exit ;;
+ exit 0;;
* )
break ;;
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
- kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray)
+ -apple | -axis)
os=
basic_machine=$1
;;
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
- | bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
- | ms1 \
| msp430 \
| ns16k | ns32k \
- | or32 \
+ | openrisc | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
- | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | s390 | s390x \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
- | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | x86 | xscale | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
- m32c)
- basic_machine=$basic_machine-unknown
- ;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
- | bfin-* | bs2000-* \
+ | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
- | clipper-* | craynv-* | cydra-* \
+ | clipper-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | m32r-* | m32rle-* \
+ | ip2k-* \
+ | m32r-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* \
+ | m88110-* | m88k-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
- | mmix-* \
- | ms1-* \
| msp430-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
+ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | s390-* | s390x-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
- | sparclite-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
- | xstormy16-* | xtensa-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
| ymp-* \
| z8k-*)
;;
- m32c-*)
- ;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=a29k-amd
os=-udi
;;
- abacus)
- basic_machine=abacus-unknown
- ;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
amd64)
basic_machine=x86_64-pc
;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
amdahl)
basic_machine=580-amdahl
os=-sysv
basic_machine=j90-cray
os=-unicos
;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16c)
- basic_machine=cr16c-unknown
- os=-elf
- ;;
crds | unos)
basic_machine=m68k-crds
;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
da30 | da30-*)
basic_machine=m68k-da30
;;
basic_machine=m88k-motorola
os=-sysv3
;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
monitor)
basic_machine=m68k-rom68k
os=-coff
np1)
basic_machine=np1-gould
;;
+ nv1)
+ basic_machine=nv1-cray
+ os=-unicosmp
+ ;;
nsr-tandem)
basic_machine=nsr-tandem
;;
basic_machine=hppa1.1-oki
os=-proelf
;;
- openrisc | openrisc-*)
+ or32 | or32-*)
basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
+ os=-coff
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
sa29200)
basic_machine=a29k-amd
os=-udi
tower | tower-32)
basic_machine=m68k-ncr
;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
udi29k)
basic_machine=a29k-amd
os=-udi
basic_machine=hppa1.1-winbond
os=-proelf
;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
xps | xps100)
basic_machine=xps100-honeywell
;;
romp)
basic_machine=romp-ibm
;;
- mmix)
- basic_machine=mmix-knuth
- ;;
rs6000)
basic_machine=rs6000-ibm
;;
we32k)
basic_machine=we32k-att
;;
- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
sparc | sparcv8 | sparcv9 | sparcv9b)
basic_machine=sparc-sun
;;
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku*)
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
- -linux-dietlibc)
- os=-linux-dietlibc
- ;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-opened*)
os=-openedition
;;
- -os400*)
- os=-os400
- ;;
-wince*)
os=-wince
;;
-atheos*)
os=-atheos
;;
- -syllable*)
- os=-syllable
- ;;
-386bsd)
os=-bsd
;;
-sinix*)
os=-sysv4
;;
- -tpf*)
- os=-tpf
- ;;
-triton*)
os=-sysv3
;;
-kaos*)
os=-kaos
;;
- -zvmoe)
- os=-zvmoe
- ;;
-none)
;;
*)
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
*-be)
os=-beos
;;
- *-haiku)
- os=-haiku
- ;;
*-ibm)
os=-aix
;;
- *-knuth)
- os=-mmixware
- ;;
*-wec)
os=-proelf
;;
-mvs* | -opened*)
vendor=ibm
;;
- -os400*)
- vendor=ibm
- ;;
-ptx*)
vendor=sequent
;;
- -tpf*)
- vendor=ibm
- ;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
esac
echo $basic_machine$os
-exit
+exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
#define PACKAGE_NAME "shibboleth"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "shibboleth 2.2.1"
+#define PACKAGE_STRING "shibboleth 2.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "shibboleth"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.2.1"
+#define PACKAGE_VERSION "2.3"
/* Define to the necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef TM_IN_SYS_TIME */
/* Version number of package */
-#define VERSION "2.2.1"
+#define VERSION "2.3"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
-## $Id: Makefile.am 3088 2009-08-10 16:43:09Z cantor $
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $
AUTOMAKE_OPTIONS = foreign
postTemplate.html \
localLogout.html \
globalLogout.html \
+ partialLogout.html \
sslError.html
#
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
postTemplate.html \
localLogout.html \
globalLogout.html \
+ partialLogout.html \
sslError.html
CLEANFILES = \
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title>Authorization Failed</title>
</head>
<img src="<shibmlp logoLocation/>" alt="Logo" />
<h1>Authorization Failed</h1>
+<p>
Based on the information provided to this application about you, you are
not authorized to access the resource at "<shibmlp requestURL/>"
+</p>
-<p/>
-
+<p>
Please contact the administrator of this service or application if you
believe this to be an error at <a href="mailto:<shibmlp supportContact/>"><shibmlp supportContact/></a>
+</p>
</body>
</html>
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
# RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
#
# Load the Shibboleth module.
<Files *.sso>
SetHandler shib-handler
</Files>
-#
+
# Another way of addressing this is to apply Shibboleth
# globally to the site in "lazy" session mode:
# <Location />
</IfModule>
#
-# Configure the module for content
+# Configure the module for content.
#
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
# any requests, and there MUST be a require command as well. To
# enable Shibboleth but not specify any session/access requirements
# use "require shibboleth".
#
<Location /secure>
AuthType shibboleth
- ShibRequireSession On
+ ShibRequestSetting requireSession 1
require valid-user
</Location>
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
# RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
#
-# Load the SHIBBOLETH module
+# Load the Shibboleth module.
#
LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_20.so
</IfModule>
#
-# Configure the module for content
+# Configure the module for content.
#
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
# any requests, and there MUST be a require command as well. To
# enable Shibboleth but not specify any session/access requirements
# use "require shibboleth".
#
<Location /secure>
AuthType shibboleth
- ShibRequireSession On
+ ShibRequestSetting requireSession 1
require valid-user
</Location>
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
# RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
#
-# Load the SHIBBOLETH module
+# Load the Shibboleth module.
#
LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_22.so
</IfModule>
#
-# Configure the module for content
+# Configure the module for content.
#
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
# any requests, and there MUST be a require command as well. To
# enable Shibboleth but not specify any session/access requirements
# use "require shibboleth".
#
<Location /secure>
AuthType shibboleth
- ShibRequireSession On
+ ShibRequestSetting requireSession 1
require valid-user
</Location>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title>Global Logout</title>
</head>
<p><strong>Status of Global Logout:</strong> <shibmlp logoutStatus/></p>
-<shibmlpif statusCode>
- <p>Error from your identity provider:</p>
- <blockquote>
- <strong>Status:</strong> <shibmlp statusCode/><br>
- <shibmlpif statusCode2>
- <strong>Sub-Status:</strong> <shibmlp statusCode2/><br>
- </shibmlpif>
- <shibmlpif statusMessage>
- <strong>Message:</strong> <shibmlp statusMessage/><br>
- </shibmlpif>
- </blockquote>
-</shibmlpif>
-
<p>If the message above indicates success, you have been logged out of all
the applications and systems that support the logout mechanism.</p>
-<p>It is still strongly advised that you close your browser to complete the
-logout process.</p>
+<p>Regardless of the outcome, it is strongly advised that you close your browser
+to ensure that you complete the logout process.</p>
</body>
</html>
-@echo off\r
-setlocal\r
-\r
-set DAYS=\r
-set YEARS=\r
-set FQDN=\r
-set ENTITYID=\r
-set TEMP_DOMAIN_NAME=\r
-set PARAM=\r
-\r
-set PREFIX=%~dp0\r
-\r
-:opt_start\r
-set PARAM=%1\r
-if not defined PARAM goto opt_end\r
-if %1==-h goto opt_fqdn\r
-if %1==-e goto opt_entityid\r
-if %1==-y goto opt_years\r
-if %1==-f goto opt_force\r
-goto usage\r
-:opt_end\r
-\r
-if exist "%PREFIX%sp-key.pem" goto protect\r
-if exist "%PREFIX%sp-cert.pem" goto protect\r
-\r
-if not defined YEARS set YEARS=10\r
-set /a DAYS=%YEARS%*365\r
-\r
-if not defined FQDN goto guess_fqdn\r
-\r
-:generate\r
-set PATH=%PREFIX%..\..\lib;%PREFIX%..\..\bin\r
-set CNF="%PREFIX%sp-cert.cnf"\r
-echo # OpenSSL configuration file for creating sp-cert.pem >%CNF%\r
-echo [req] >>%CNF%\r
-echo prompt=no >>%CNF%\r
-echo default_bits=2048 >>%CNF%\r
-echo encrypt_key=no >>%CNF%\r
-echo default_md=sha1 >>%CNF%\r
-echo distinguished_name=dn >>%CNF%\r
-echo # PrintableStrings only >>%CNF%\r
-echo string_mask=MASK:0002 >>%CNF%\r
-echo x509_extensions=ext >>%CNF%\r
-echo [dn] >>%CNF%\r
-echo CN=%FQDN% >>%CNF%\r
-echo [ext] >>%CNF%\r
-if defined ENTITYID (echo subjectAltName=DNS:%FQDN%,URI:%ENTITYID% >>%CNF%) else (echo subjectAltName=DNS:%FQDN% >>%CNF%)\r
-echo subjectKeyIdentifier=hash >>%CNF%\r
-%PREFIX%..\..\bin\openssl.exe req -config %PREFIX%sp-cert.cnf -new -x509 -days %DAYS% -keyout %PREFIX%sp-key.pem -out %PREFIX%sp-cert.pem\r
-del %CNF%\r
-exit /b\r
-\r
-:protect\r
-echo The files sp-key.pem and/or sp-cert.pem already exist!\r
-echo Use -f option to force recreation of keypair.\r
-exit /b\r
-\r
-:opt_force\r
-if exist "%PREFIX%sp-key.pem" del "%PREFIX%sp-key.pem"\r
-if exist "%PREFIX%sp-cert.pem" del "%PREFIX%sp-cert.pem"\r
-shift\r
-goto opt_start\r
-\r
-:opt_fqdn\r
-set FQDN=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:opt_entityid\r
-set ENTITYID=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:opt_years\r
-set YEARS=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:usage\r
-echo usage: keygen [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert]\r
-exit /b\r
-\r
-:guess_fqdn\r
-for /F "tokens=2 delims=:" %%i in ('"ipconfig /all | findstr /c:"Primary DNS Suffix" /c:"Primary Dns Suffix""') do set TEMP_DOMAIN_NAME=%%i\r
-if defined TEMP_DOMAIN_NAME set FQDN=%TEMP_DOMAIN_NAME: =%\r
-set TEMP_DOMAIN_NAME=\r
-if defined USERDNSDOMAIN set FQDN=%USERDNSDOMAIN%\r
-\r
-for /F %%i in ('hostname') do set HOST=%%i\r
-if defined FQDN (set FQDN=%HOST%.%FQDN%) else (set FQDN=%HOST%)\r
-\r
-echo >%FQDN%\r
-for /F %%i in ('dir /b/l %FQDN%') do set FQDN=%%i\r
-del %FQDN%\r
-goto generate\r
+@echo off
+setlocal
+
+set DAYS=
+set YEARS=
+set FQDN=
+set ENTITYID=
+set TEMP_DOMAIN_NAME=
+set PARAM=
+
+set PREFIX=%~dp0
+
+:opt_start
+set PARAM=%1
+if not defined PARAM goto opt_end
+if %1==-h goto opt_fqdn
+if %1==-e goto opt_entityid
+if %1==-y goto opt_years
+if %1==-f goto opt_force
+goto usage
+:opt_end
+
+if exist "%PREFIX%sp-key.pem" goto protect
+if exist "%PREFIX%sp-cert.pem" goto protect
+
+if not defined YEARS set YEARS=10
+set /a DAYS=%YEARS%*365
+
+if not defined FQDN goto guess_fqdn
+
+:generate
+set PATH=%PREFIX%..\..\lib;%PREFIX%..\..\bin
+set CNF="%PREFIX%sp-cert.cnf"
+echo # OpenSSL configuration file for creating sp-cert.pem >%CNF%
+echo [req] >>%CNF%
+echo prompt=no >>%CNF%
+echo default_bits=2048 >>%CNF%
+echo encrypt_key=no >>%CNF%
+echo default_md=sha1 >>%CNF%
+echo distinguished_name=dn >>%CNF%
+echo # PrintableStrings only >>%CNF%
+echo string_mask=MASK:0002 >>%CNF%
+echo x509_extensions=ext >>%CNF%
+echo [dn] >>%CNF%
+echo CN=%FQDN% >>%CNF%
+echo [ext] >>%CNF%
+if defined ENTITYID (echo subjectAltName=DNS:%FQDN%,URI:%ENTITYID% >>%CNF%) else (echo subjectAltName=DNS:%FQDN% >>%CNF%)
+echo subjectKeyIdentifier=hash >>%CNF%
+%PREFIX%..\..\bin\openssl.exe req -config %PREFIX%sp-cert.cnf -new -x509 -days %DAYS% -keyout %PREFIX%sp-key.pem -out %PREFIX%sp-cert.pem
+del %CNF%
+exit /b
+
+:protect
+echo The files sp-key.pem and/or sp-cert.pem already exist!
+echo Use -f option to force recreation of keypair.
+exit /b
+
+:opt_force
+if exist "%PREFIX%sp-key.pem" del "%PREFIX%sp-key.pem"
+if exist "%PREFIX%sp-cert.pem" del "%PREFIX%sp-cert.pem"
+shift
+goto opt_start
+
+:opt_fqdn
+set FQDN=%2
+shift
+shift
+goto opt_start
+
+:opt_entityid
+set ENTITYID=%2
+shift
+shift
+goto opt_start
+
+:opt_years
+set YEARS=%2
+shift
+shift
+goto opt_start
+
+:usage
+echo usage: keygen [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert]
+exit /b
+
+:guess_fqdn
+for /F "tokens=2 delims=:" %%i in ('"ipconfig /all | findstr /c:"Primary DNS Suffix" /c:"Primary Dns Suffix""') do set TEMP_DOMAIN_NAME=%%i
+if defined TEMP_DOMAIN_NAME set FQDN=%TEMP_DOMAIN_NAME: =%
+set TEMP_DOMAIN_NAME=
+if defined USERDNSDOMAIN set FQDN=%USERDNSDOMAIN%
+
+for /F %%i in ('hostname') do set HOST=%%i
+if defined FQDN (set FQDN=%HOST%.%FQDN%) else (set FQDN=%HOST%)
+
+echo >%FQDN%
+for /F %%i in ('dir /b/l %FQDN%') do set FQDN=%%i
+del %FQDN%
+goto generate
openssl req -config sp-cert.cnf -new -x509 -days $DAYS -keyout sp-key.pem -out sp-cert.pem 2> /dev/null
fi
-chmod 600 sp-key.pem
rm sp-cert.cnf
+
+if [ -s sp-key.pem ] ; then
+ chmod 600 sp-key.pem
+fi
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title>Local Logout</title>
</head>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title>Unknown Identity Provider</title>
</head>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
+ <title>Partial Logout</title>
+</head>
+
+<body>
+
+<img src="<shibmlp logoLocation/>" alt="Logo" />
+<h1>Partial Logout</h1>
+
+<p>You remain logged into one or more applications accessed during your session.
+To complete the logout process, please close/exit your browser completely.</p>
+
+</body>
+</html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title><shibmlp errorType/></title>
</head>
<blockquote>
<strong>Status:</strong> <shibmlp statusCode/><br>
<shibmlpif statusCode2>
- <strong>Sub-Status:</strong> <shibmlp statusCode2/><br>
+ <strong>Sub-Status:</strong> <shibmlp statusCode2/><br/>
</shibmlpif>
<shibmlpif statusMessage>
- <strong>Message:</strong> <shibmlp statusMessage/><br>
+ <strong>Message:</strong> <shibmlp statusMessage/><br/>
</shibmlpif>
</blockquote>
</shibmlpif>
<!-- Default example directs to a specific IdP's SSO service (favoring SAML 2 over Shib 1). -->
<SessionInitiator type="Chaining" Location="/Login" isDefault="true" id="Intranet"
relayState="cookie" entityID="https://idp.example.org/shibboleth">
- <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
- <SessionInitiator type="Shib1" defaultACSIndex="5"/>
+ <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+ <SessionInitiator type="Shib1" acsIndex="5"/>
</SessionInitiator>
<!-- An example using an old-style WAYF, which means Shib 1 only unless an entityID is provided. -->
<SessionInitiator type="Chaining" Location="/WAYF" id="WAYF" relayState="cookie">
- <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
- <SessionInitiator type="Shib1" defaultACSIndex="5"/>
- <SessionInitiator type="WAYF" defaultACSIndex="5" URL="https://wayf.example.org/WAYF"/>
+ <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+ <SessionInitiator type="Shib1" acsIndex="5"/>
+ <SessionInitiator type="WAYF" acsIndex="5" URL="https://wayf.example.org/WAYF"/>
</SessionInitiator>
<!-- An example supporting the new-style of discovery service. -->
<SessionInitiator type="Chaining" Location="/DS" id="DS" relayState="cookie">
- <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
- <SessionInitiator type="Shib1" defaultACSIndex="5"/>
+ <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+ <SessionInitiator type="Shib1" acsIndex="5"/>
<SessionInitiator type="SAMLDS" URL="https://ds.example.org/DS/WAYF"/>
</SessionInitiator>
</Sessions>
<!--
- You should customize these pages! You can add attributes with values that can be plugged
- into your templates. You can remove the access attribute to cause the module to return a
- standard 403 Forbidden error code if authorization fails, and then customize that condition
- using your web server.
+ Allows overriding of error template filenames. You can also add attributes with values
+ that can be plugged into the templates.
-->
- <Errors session="sessionError.html"
- metadata="metadataError.html"
- access="accessError.html"
- ssl="sslError.html"
- localLogout="localLogout.html"
- globalLogout="globalLogout.html"
- supportContact="root@localhost"
+ <Errors supportContact="root@localhost"
logoLocation="/shibboleth-sp/logo.jpg"
styleSheet="/shibboleth-sp/main.css"/>
</TrustEngine>
<!-- Map to extract attributes from SAML assertions. -->
- <AttributeExtractor type="XML" path="attribute-map.xml"/>
+ <AttributeExtractor type="XML" validate="true" path="attribute-map.xml"/>
<!-- Use a SAML query if no attributes are supplied during SSO. -->
<AttributeResolver type="Query"/>
<!-- Default filtering policy for recognized attributes, lets other data pass. -->
- <AttributeFilter type="XML" path="attribute-policy.xml"/>
+ <AttributeFilter type="XML" validate="true" path="attribute-policy.xml"/>
<!-- Simple file-based resolver for using a single keypair. -->
<CredentialResolver type="File" key="sp-key.pem" certificate="sp-cert.pem"/>
</Policy>
</SecurityPolicies>
-</SPConfig>
\ No newline at end of file
+</SPConfig>
# Specify pid file to use
DAEMON_OPTS="$DAEMON_OPTS -p $PIDFILE"
+# Specify wait time to use
+DAEMON_OPTS="$DAEMON_OPTS -w 30"
+
# Exit if the package is not installed.
[ -x "$DAEMON" ] || exit 0
SHIBD_USER=root
pidfile=@-PKGRUNDIR-@/shibd.pid
prog=shibd
+VER=`cat /etc/redhat-release | awk '{print $3}' | awk -F . '{print $1}'`
RETVAL=0
start() {
if checkpid $kpid 2>&1; then
echo "process already running"
return -1
- else
+ else
echo "lock file found but no process running for pid $kpid, continuing"
fi
fi
if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
/sbin/restorecon $pidfile
fi
- daemon --user $SHIBD_USER --pidfile $pidfile $shibd -p $pidfile -f -w 3
+ if [ 5 -le $VER ] ; then
+ daemon --user $SHIBD_USER --pidfile $pidfile $shibd -p $pidfile -f -w 30
+ else
+ daemon --user $SHIBD_USER $shibd -p $pidfile -f -w 30
+ fi
RETVAL=$?
echo
stop() {
echo -n $"Stopping $prog: "
- if [ -f $pidfile ]; then
+ if [ -f $pidfile -a 5 -le $VER ] ; then
killproc -p $pidfile shibd
else
- killproc shibd
+ killproc shibd
fi
RETVAL=$?
stop
;;
status)
- status $shibd
+ status $shibd
RETVAL=$?
;;
restart)
# Specify pid file to use
DAEMON_OPTS="$DAEMON_OPTS -p $PID_FILE"
+
+# Specify wait time to use
+DAEMON_OPTS="$DAEMON_OPTS -w 30"
# Exit if the package is not installed.
test -x "$DAEMON" || exit 5
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
<title>POST Failed</title>
</head>
<img src="<shibmlp logoLocation/>" alt="Logo" />
<h1>POST Failed</h1>
-
+<p>
You have attemped to submit information without the protection
-of SSL to this site.<br>
+of SSL to this site.<br/>
+</p>
+<p>
For the protection of your submission and the integrity of the site,
this is not permitted. Please try accessing the server with a
URL starting with <strong>https://</strong> and report this problem
to <a href="mailto:<shibmlp supportContact/>"><shibmlp supportContact/></a>
+</p>
</body>
</html>
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for shibboleth 2.2.1.
+# Generated by GNU Autoconf 2.59 for shibboleth 2.3.
#
# Report bugs to <shibboleth-users@internet2.edu>.
#
# Identity of this package.
PACKAGE_NAME='shibboleth'
PACKAGE_TARNAME='shibboleth'
-PACKAGE_VERSION='2.2.1'
-PACKAGE_STRING='shibboleth 2.2.1'
+PACKAGE_VERSION='2.3'
+PACKAGE_STRING='shibboleth 2.3'
PACKAGE_BUGREPORT='shibboleth-users@internet2.edu'
# Factoring default headers for most tests.
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DX_PROJECT DX_CONFIG DX_DOCDIR DX_ENV DX_FLAG_doc DX_DOXYGEN ac_pt_DX_DOXYGEN DX_PERL ac_pt_DX_PERL DX_COND_doc_TRUE DX_COND_doc_FALSE DX_FLAG_dot DX_DOT ac_pt_DX_DOT DX_COND_dot_TRUE DX_COND_dot_FALSE DX_FLAG_man DX_COND_man_TRUE DX_COND_man_FALSE DX_FLAG_rtf DX_COND_rtf_TRUE DX_COND_rtf_FALSE DX_FLAG_xml DX_COND_xml_TRUE DX_COND_xml_FALSE DX_FLAG_chm DX_HHC ac_pt_DX_HHC DX_COND_chm_TRUE DX_COND_chm_FALSE DX_FLAG_chi DX_COND_chi_TRUE DX_COND_chi_FALSE DX_FLAG_html DX_COND_html_TRUE DX_COND_html_FALSE DX_FLAG_ps DX_LATEX ac_pt_DX_LATEX DX_MAKEINDEX ac_pt_DX_MAKEINDEX DX_DVIPS ac_pt_DX_DVIPS DX_EGREP ac_pt_DX_EGREP DX_COND_ps_TRUE DX_COND_ps_FALSE DX_FLAG_pdf DX_PDFLATEX ac_pt_DX_PDFLATEX DX_COND_pdf_TRUE DX_COND_pdf_FALSE DX_COND_latex_TRUE DX_COND_latex_FALSE DOXYGEN_PAPER_SIZE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS PKG_CONFIG LOG4SHIB_CONFIG LOG4CPP_CONFIG XMLTOOLINGXMLDIR OPENSAMLXMLDIR LITE_LIBS XMLSEC_LIBS NSAPI_INCLUDE BUILD_NSAPI_TRUE BUILD_NSAPI_FALSE FASTCGI_INCLUDE FASTCGI_LDFLAGS FASTCGI_LIBS BUILD_FASTCGI_TRUE BUILD_FASTCGI_FALSE MEMCACHED_INCLUDE MEMCACHED_LDFLAGS MEMCACHED_LIBS BUILD_MEMCACHED_TRUE BUILD_MEMCACHED_FALSE xs APXS APXS_CFLAGS APXS_INCLUDE APXS2 APR_CONFIG APXS2_CFLAGS APXS2_INCLUDE APXS22 APR1_CONFIG APXS22_CFLAGS APXS22_INCLUDE BUILD_AP13_TRUE BUILD_AP13_FALSE BUILD_AP20_TRUE BUILD_AP20_FALSE BUILD_AP22_TRUE BUILD_AP22_FALSE ODBC_CONFIG ODBC_CFLAGS ODBC_LIBS WANT_SUBDIRS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DX_PROJECT DX_CONFIG DX_DOCDIR DX_ENV DX_FLAG_doc DX_DOXYGEN ac_pt_DX_DOXYGEN DX_PERL ac_pt_DX_PERL DX_COND_doc_TRUE DX_COND_doc_FALSE DX_FLAG_dot DX_DOT ac_pt_DX_DOT DX_COND_dot_TRUE DX_COND_dot_FALSE DX_FLAG_man DX_COND_man_TRUE DX_COND_man_FALSE DX_FLAG_rtf DX_COND_rtf_TRUE DX_COND_rtf_FALSE DX_FLAG_xml DX_COND_xml_TRUE DX_COND_xml_FALSE DX_FLAG_chm DX_HHC ac_pt_DX_HHC DX_COND_chm_TRUE DX_COND_chm_FALSE DX_FLAG_chi DX_COND_chi_TRUE DX_COND_chi_FALSE DX_FLAG_html DX_COND_html_TRUE DX_COND_html_FALSE DX_FLAG_ps DX_LATEX ac_pt_DX_LATEX DX_MAKEINDEX ac_pt_DX_MAKEINDEX DX_DVIPS ac_pt_DX_DVIPS DX_EGREP ac_pt_DX_EGREP DX_COND_ps_TRUE DX_COND_ps_FALSE DX_FLAG_pdf DX_PDFLATEX ac_pt_DX_PDFLATEX DX_COND_pdf_TRUE DX_COND_pdf_FALSE DX_COND_latex_TRUE DX_COND_latex_FALSE DOXYGEN_PAPER_SIZE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS PKG_CONFIG LOG4SHIB_CONFIG LOG4CPP_CONFIG XMLTOOLINGXMLDIR OPENSAMLXMLDIR LITE_LIBS XMLSEC_LIBS NSAPI_INCLUDE BUILD_NSAPI_TRUE BUILD_NSAPI_FALSE FASTCGI_INCLUDE FASTCGI_LDFLAGS FASTCGI_LIBS BUILD_FASTCGI_TRUE BUILD_FASTCGI_FALSE MEMCACHED_INCLUDE MEMCACHED_LDFLAGS MEMCACHED_LIBS BUILD_MEMCACHED_TRUE BUILD_MEMCACHED_FALSE xs APXS APXS_CFLAGS APXS_INCLUDE APXS2 APR_CONFIG APU_CONFIG APXS2_CFLAGS APXS2_INCLUDE APXS22 APR1_CONFIG APU1_CONFIG APXS22_CFLAGS APXS22_INCLUDE BUILD_AP13_TRUE BUILD_AP13_FALSE BUILD_AP20_TRUE BUILD_AP20_FALSE BUILD_AP22_TRUE BUILD_AP22_FALSE ODBC_CONFIG ODBC_CFLAGS ODBC_LIBS WANT_SUBDIRS LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures shibboleth 2.2.1 to adapt to many kinds of systems.
+\`configure' configures shibboleth 2.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of shibboleth 2.2.1:";;
+ short | recursive ) echo "Configuration of shibboleth 2.3:";;
esac
cat <<\_ACEOF
--with-apxs=FILE Specifies where to find the Apache 1.3 apxs script.
--with-apxs2=FILE Specifies where to find the Apache 2.0 apxs script.
--with-apr=PATH where apr-config is installed
+ --with-apu=PATH where apu-config is installed
--with-apxs22=FILE Specifies where to find the Apache 2.2 apxs script.
--with-apr1=PATH where apr-1-config is installed
+ --with-apu1=PATH where apu-1-config is installed
--with-odbc=PATH directory where odbc is installed
Some influential environment variables:
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-shibboleth configure 2.2.1
+shibboleth configure 2.3
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by shibboleth $as_me 2.2.1, which was
+It was created by shibboleth $as_me 2.3, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE=shibboleth
- VERSION=2.2.1
+ VERSION=2.3
cat >>confdefs.h <<_ACEOF
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6103 "configure"' > conftest.$ac_ext
+ echo '#line 6105 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
# Provide some information about the compiler.
-echo "$as_me:7211:" \
+echo "$as_me:7213:" \
"checking for Fortran 77 compiler version" >&5
ac_compiler=`set X $ac_compile; echo $2`
{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8249: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8251: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8253: \$? = $ac_status" >&5
+ echo "$as_me:8255: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8482: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8484: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8486: \$? = $ac_status" >&5
+ echo "$as_me:8488: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8542: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8544: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8546: \$? = $ac_status" >&5
+ echo "$as_me:8548: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 9876 "configure"' > conftest.$ac_ext
+ echo '#line 9878 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10747 "configure"
+#line 10749 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10845 "configure"
+#line 10847 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13028: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13030: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:13032: \$? = $ac_status" >&5
+ echo "$as_me:13034: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13088: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13090: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:13092: \$? = $ac_status" >&5
+ echo "$as_me:13094: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 13599 "configure"' > conftest.$ac_ext
+ echo '#line 13601 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 14470 "configure"
+#line 14472 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 14568 "configure"
+#line 14570 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15395: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:15397: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:15399: \$? = $ac_status" >&5
+ echo "$as_me:15401: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15455: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:15457: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:15459: \$? = $ac_status" >&5
+ echo "$as_me:15461: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 16769 "configure"' > conftest.$ac_ext
+ echo '#line 16771 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17514: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17516: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17518: \$? = $ac_status" >&5
+ echo "$as_me:17520: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17747: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17749: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17751: \$? = $ac_status" >&5
+ echo "$as_me:17753: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17807: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17809: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17811: \$? = $ac_status" >&5
+ echo "$as_me:17813: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 19141 "configure"' > conftest.$ac_ext
+ echo '#line 19143 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 20012 "configure"
+#line 20014 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 20110 "configure"
+#line 20112 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
+
+# save and append master libs
+save_LIBS="$LIBS"
+LIBS="$XMLSEC_LIBS $LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <xmltooling/io/HTTPResponse.h>
+int
+main ()
+{
+xmltooling::HTTPResponse::sanitizeURL("http://test")
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_XMLTOOLING 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: unable to link with XMLTooling, or version was too old" >&5
+echo "$as_me: error: unable to link with XMLTooling, or version was too old" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+# restore master libs
+LIBS="$save_LIBS"
+
# Establish location of xmltooling catalog.
XMLTOOLINGXMLDIR=""
if test "x$with_xmltooling" = "x" ; then
# --enable-apache-20
# --with-apxs2 (DSO build, the normal way, uses apxs to derive build flags)
# --with-apr (DSO build, APR development package installed separately)
+# --with-apu (DSO build, APR-UTIL development package installed separately)
# Check whether --enable-apache-20 or --disable-apache-20 was given.
if test "${enable_apache_20+set}" = set; then
{ (exit 1); exit 1; }; }
fi
+ # APU settings
+
+# Check whether --with-apu or --without-apu was given.
+if test "${with_apu+set}" = set; then
+ withval="$with_apu"
+
+ echo "$as_me:$LINENO: checking for user-specified apu-config name/location" >&5
+echo $ECHO_N "checking for user-specified apu-config name/location... $ECHO_C" >&6
+ if test "$withval" != "no" ; then
+ if test "$withval" != "yes"; then
+ APR_CONFIG=$withval
+ echo "$as_me:$LINENO: result: \"$withval\"" >&5
+echo "${ECHO_T}\"$withval\"" >&6
+ fi
+ fi
+
+else
+
+ # Extract the first word of "apu-config", so it can be a program name with args.
+set dummy apu-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_APU_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $APU_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_APU_CONFIG="$APU_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="`$APXS2 -q SBINDIR`:$PATH"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_APU_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+APU_CONFIG=$ac_cv_path_APU_CONFIG
+
+if test -n "$APU_CONFIG"; then
+ echo "$as_me:$LINENO: result: $APU_CONFIG" >&5
+echo "${ECHO_T}$APU_CONFIG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+fi;
+ if test -f "${APU_CONFIG}"; then
+ APU_CFLAGS="`${APU_CONFIG} --includes`"
+ else
+ { { echo "$as_me:$LINENO: error: Unable to locate apu-config, may need --with-apu option." >&5
+echo "$as_me: error: Unable to locate apu-config, may need --with-apu option." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
# extract settings we need from APXS2 -q
APXS2_CC="`$APXS2 -q CC`"
- APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APR_CFLAGS"
+ APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APU_CFLAGS"
APXS2_INCLUDE="`$APXS2 -q INCLUDEDIR`"
fi
# --enable-apache-22
# --with-apxs22 (DSO build, the normal way, uses apxs to derive build flags)
# --with-apr1 (DSO build, APR development package installed separately)
+# --with-apu1 (DSO build, APR-UTIL development package installed separately)
# Check whether --enable-apache-22 or --disable-apache-22 was given.
if test "${enable_apache_22+set}" = set; then
{ (exit 1); exit 1; }; }
fi
+ # APU1 settings
+
+# Check whether --with-apu1 or --without-apu1 was given.
+if test "${with_apu1+set}" = set; then
+ withval="$with_apu1"
+
+ echo "$as_me:$LINENO: checking for user-specified apu-1-config name/location" >&5
+echo $ECHO_N "checking for user-specified apu-1-config name/location... $ECHO_C" >&6
+ if test "$withval" != "no" ; then
+ if test "$withval" != "yes"; then
+ APR1_CONFIG=$withval
+ echo "$as_me:$LINENO: result: \"$withval\"" >&5
+echo "${ECHO_T}\"$withval\"" >&6
+ fi
+ fi
+
+else
+
+ # Extract the first word of "apu-1-config", so it can be a program name with args.
+set dummy apu-1-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_APU1_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $APU1_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_APU1_CONFIG="$APU1_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="`$APXS22 -q SBINDIR`:$PATH"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_APU1_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+APU1_CONFIG=$ac_cv_path_APU1_CONFIG
+
+if test -n "$APU1_CONFIG"; then
+ echo "$as_me:$LINENO: result: $APU1_CONFIG" >&5
+echo "${ECHO_T}$APU1_CONFIG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+fi;
+ if test -f "${APU1_CONFIG}"; then
+ APU1_CFLAGS="`${APU1_CONFIG} --includes`"
+ else
+ { { echo "$as_me:$LINENO: error: Unable to locate apu-1-config, may need --with-apu1 option." >&5
+echo "$as_me: error: Unable to locate apu-1-config, may need --with-apu1 option." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
# extract settings we need from APXS22 -q
APXS22_CC="`$APXS22 -q CC`"
- APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS"
+ APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS $APU1_CFLAGS"
APXS22_INCLUDE="`$APXS22 -q INCLUDEDIR`"
fi
} >&5
cat >&5 <<_CSEOF
-This file was extended by shibboleth $as_me 2.2.1, which was
+This file was extended by shibboleth $as_me 2.3, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-shibboleth config.status 2.2.1
+shibboleth config.status 2.3
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
s,@APXS_INCLUDE@,$APXS_INCLUDE,;t t
s,@APXS2@,$APXS2,;t t
s,@APR_CONFIG@,$APR_CONFIG,;t t
+s,@APU_CONFIG@,$APU_CONFIG,;t t
s,@APXS2_CFLAGS@,$APXS2_CFLAGS,;t t
s,@APXS2_INCLUDE@,$APXS2_INCLUDE,;t t
s,@APXS22@,$APXS22,;t t
s,@APR1_CONFIG@,$APR1_CONFIG,;t t
+s,@APU1_CONFIG@,$APU1_CONFIG,;t t
s,@APXS22_CFLAGS@,$APXS22_CFLAGS,;t t
s,@APXS22_INCLUDE@,$APXS22_INCLUDE,;t t
s,@BUILD_AP13_TRUE@,$BUILD_AP13_TRUE,;t t
AC_PREREQ([2.50])
-AC_INIT([shibboleth], [2.2.1], [shibboleth-users@internet2.edu], [shibboleth])
+AC_INIT([shibboleth], [2.3], [shibboleth-users@internet2.edu], [shibboleth])
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE([shibboleth],[2.2.1])
+AM_INIT_AUTOMAKE([shibboleth],[2.3])
sinclude(doxygen.m4)
sinclude(acx_pthread.m4)
XMLSEC_LIBS="-lxmltooling"
AC_CHECK_HEADER([xmltooling/base.h],,
AC_MSG_ERROR([unable to find xmltooling header files]))
+
+
+# save and append master libs
+save_LIBS="$LIBS"
+LIBS="$XMLSEC_LIBS $LIBS"
+
+AC_TRY_LINK(
+ [#include <xmltooling/io/HTTPResponse.h>],
+ [xmltooling::HTTPResponse::sanitizeURL("http://test")],
+ [AC_DEFINE(HAVE_XMLTOOLING,1,[Define if xmltooling library was found])],
+ [AC_MSG_ERROR([unable to link with XMLTooling, or version was too old])])
+
+# restore master libs
+LIBS="$save_LIBS"
# Establish location of xmltooling catalog.
XMLTOOLINGXMLDIR=""
# --enable-apache-20
# --with-apxs2 (DSO build, the normal way, uses apxs to derive build flags)
# --with-apr (DSO build, APR development package installed separately)
+# --with-apu (DSO build, APR-UTIL development package installed separately)
AC_ARG_ENABLE(apache-20,
AC_HELP_STRING([--enable-apache-20], [enable the Apache 2.0 module]),
AC_MSG_ERROR([Unable to locate apr-config, may need --with-apr option.])
fi
+ # APU settings
+ AC_ARG_WITH(apu,
+ AC_HELP_STRING([--with-apu=PATH], [where apu-config is installed]),
+ [
+ AC_MSG_CHECKING(for user-specified apu-config name/location)
+ if test "$withval" != "no" ; then
+ if test "$withval" != "yes"; then
+ APR_CONFIG=$withval
+ AC_MSG_RESULT("$withval")
+ fi
+ fi
+ ],
+ [
+ AC_PATH_PROG(APU_CONFIG, apu-config,,[`$APXS2 -q SBINDIR`]:[$PATH])
+ ])
+ if test -f "${APU_CONFIG}"; then
+ APU_CFLAGS="`${APU_CONFIG} --includes`"
+ else
+ AC_MSG_ERROR([Unable to locate apu-config, may need --with-apu option.])
+ fi
+
# extract settings we need from APXS2 -q
APXS2_CC="`$APXS2 -q CC`"
- APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APR_CFLAGS"
+ APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APU_CFLAGS"
APXS2_INCLUDE="`$APXS2 -q INCLUDEDIR`"
fi
# --enable-apache-22
# --with-apxs22 (DSO build, the normal way, uses apxs to derive build flags)
# --with-apr1 (DSO build, APR development package installed separately)
+# --with-apu1 (DSO build, APR-UTIL development package installed separately)
AC_ARG_ENABLE(apache-22,
AC_HELP_STRING([--enable-apache-22], [enable the Apache 2.2 module]),
AC_MSG_ERROR([Unable to locate apr-1-config, may need --with-apr1 option.])
fi
+ # APU1 settings
+ AC_ARG_WITH(apu1,
+ AC_HELP_STRING([--with-apu1=PATH], [where apu-1-config is installed]),
+ [
+ AC_MSG_CHECKING(for user-specified apu-1-config name/location)
+ if test "$withval" != "no" ; then
+ if test "$withval" != "yes"; then
+ APR1_CONFIG=$withval
+ AC_MSG_RESULT("$withval")
+ fi
+ fi
+ ],
+ [
+ AC_PATH_PROG(APU1_CONFIG, apu-1-config,,[`$APXS22 -q SBINDIR`]:[$PATH])
+ ])
+ if test -f "${APU1_CONFIG}"; then
+ APU1_CFLAGS="`${APU1_CONFIG} --includes`"
+ else
+ AC_MSG_ERROR([Unable to locate apu-1-config, may need --with-apu1 option.])
+ fi
+
# extract settings we need from APXS22 -q
APXS22_CC="`$APXS22 -q CC`"
- APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS"
+ APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS $APU1_CFLAGS"
APXS22_INCLUDE="`$APXS22 -q INCLUDEDIR`"
fi
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
-Version 2.2.1
+Version 2.3
Welcome to Internet2's Shibboleth
Release Notes
Shibboleth Native SP
-2.2.1
+2.3
NOTE: The shibboleth2.xml configuration format in this release
is fully compatible with the 2.1 release, but there are some small
changes required to eliminate various warnings about deprecated options.
List of issues addressed by this release:
-https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC
+https://bugs.internet2.edu/jira/browse/SSPCPP/fixforversion/10261
Fully Supported
-AUTOMAKE_OPTIONS = foreign\r
-\r
-if BUILD_FASTCGI\r
-\r
-fastcgidir = $(libdir)/@PACKAGE@\r
-\r
-fastcgi_PROGRAMS = shibauthorizer shibresponder\r
-\r
-shibauthorizer_SOURCES = shibauthorizer.cpp\r
-shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibauthorizer_LDADD = \\r
- $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-shibresponder_SOURCES = shibresponder.cpp\r
-shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibresponder_LDADD = \\r
- $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-endif\r
-\r
-EXTRA_DIST = \\r
- shibauthorizer.cpp \\r
- shibauthorizer.vcproj \\r
- shibauthorizer.rc \\r
- shibresponder.cpp \\r
- shibresponder.vcproj \\r
- shibresponder.rc \\r
- resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+if BUILD_FASTCGI
+
+fastcgidir = $(libdir)/@PACKAGE@
+
+fastcgi_PROGRAMS = shibauthorizer shibresponder
+
+shibauthorizer_SOURCES = shibauthorizer.cpp
+shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibauthorizer_LDADD = \
+ $(top_builddir)/shibsp/libshibsp-lite.la
+
+shibresponder_SOURCES = shibresponder.cpp
+shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibresponder_LDADD = \
+ $(top_builddir)/shibsp/libshibsp-lite.la
+
+endif
+
+EXTRA_DIST = \
+ shibauthorizer.cpp \
+ shibauthorizer.vcproj \
+ shibauthorizer.rc \
+ shibresponder.cpp \
+ shibresponder.vcproj \
+ shibresponder.rc \
+ resource.h
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by isapi_shib.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 101\r
-#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1000\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+//{{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
-/*\r
- * Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer\r
-\r
- Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
- SHIB_RETURN_OK,\r
- SHIB_RETURN_KO,\r
- SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGIAuth : public AbstractSPRequest\r
-{\r
- FCGX_Request* m_req;\r
- int m_port;\r
- string m_scheme,m_hostname;\r
- multimap<string,string> m_response_headers;\r
-public:\r
- map<string,string> m_request_headers;\r
-\r
- ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
- : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {\r
- const char* server_name_str = hostname;\r
- if (!server_name_str || !*server_name_str)\r
- server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
- m_hostname = server_name_str;\r
-\r
- m_port = port;\r
- if (!m_port) {\r
- char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
- m_port = strtol(server_port_str, &server_port_str, 10);\r
- if (*server_port_str) {\r
- cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
- throw runtime_error("Unable to determine server port.");\r
- }\r
- }\r
-\r
- const char* server_scheme_str = scheme;\r
- if (!server_scheme_str || !*server_scheme_str)\r
- server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
- m_scheme = server_scheme_str;\r
-\r
- setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
- }\r
-\r
- ~ShibTargetFCGIAuth() { }\r
-\r
- const char* getScheme() const {\r
- return m_scheme.c_str();\r
- }\r
- const char* getHostname() const {\r
- return m_hostname.c_str();\r
- }\r
- int getPort() const {\r
- return m_port;\r
- }\r
- const char* getMethod() const {\r
- return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
- }\r
- string getContentType() const {\r
- const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
- return s ? s : "";\r
- }\r
- long getContentLength() const {\r
- const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
- return s ? atol(s) : 0;\r
- }\r
- string getRemoteAddr() const {\r
- string ret = AbstractSPRequest::getRemoteAddr();\r
- if (!ret.empty())\r
- return ret;\r
- const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
- return s ? s : "";\r
- }\r
- void log(SPLogLevel level, const string& msg) const {\r
- AbstractSPRequest::log(level,msg);\r
- if (level >= SPError)\r
- cerr << "shib: " << msg;\r
- }\r
- void clearHeader(const char* rawname, const char* cginame) {\r
- // No need, since we use environment variables.\r
- }\r
- void setHeader(const char* name, const char* value) {\r
- if (value)\r
- m_request_headers[name] = value;\r
- else\r
- m_request_headers.erase(name);\r
- }\r
- string getHeader(const char* name) const {\r
- // Look in the local map first.\r
- map<string,string>::const_iterator i = m_request_headers.find(name);\r
- if (i != m_request_headers.end())\r
- return i->second;\r
- // Nothing set locally and this isn't a "secure" call, so check the request.\r
- string hdr("HTTP_");\r
- for (; *name; ++name) {\r
- if (*name=='-')\r
- hdr += '_';\r
- else\r
- hdr += toupper(*name);\r
- }\r
- char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
- return s ? s : "";\r
- }\r
- string getSecureHeader(const char* name) const {\r
- // Look in the local map only.\r
- map<string,string>::const_iterator i = m_request_headers.find(name);\r
- if (i != m_request_headers.end())\r
- return i->second;\r
- return "";\r
- }\r
- void setRemoteUser(const char* user) {\r
- if (user)\r
- m_request_headers["REMOTE_USER"] = user;\r
- else\r
- m_request_headers.erase("REMOTE_USER");\r
- }\r
- string getRemoteUser() const {\r
- map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");\r
- if (i != m_request_headers.end())\r
- return i->second;\r
- else {\r
- char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
- if (remote_user)\r
- return remote_user;\r
- }\r
- return "";\r
- }\r
- void setAuthType(const char* authtype) {\r
- if (authtype)\r
- m_request_headers["AUTH_TYPE"] = authtype;\r
- else\r
- m_request_headers.erase("AUTH_TYPE");\r
- }\r
- string getAuthType() const {\r
- map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
- if (i != m_request_headers.end())\r
- return i->second;\r
- else {\r
- char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
- if (auth_type)\r
- return auth_type;\r
- }\r
- return "";\r
- }\r
- void setResponseHeader(const char* name, const char* value) {\r
- // Set for later.\r
- if (value)\r
- m_response_headers.insert(make_pair(name,value));\r
- else\r
- m_response_headers.erase(name);\r
- }\r
- const char* getQueryString() const {\r
- return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
- }\r
- const char* getRequestBody() const {\r
- throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");\r
- }\r
-\r
- long sendResponse(istream& in, long status) {\r
- string hdr = string("Connection: close\r\n");\r
- for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
-\r
- // We can't return 200 OK here or else the filter is bypassed\r
- // so custom Shib errors will get turned into a generic page.\r
- const char* codestr="Status: 500 Server Error";\r
- switch (status) {\r
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break;\r
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;\r
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;\r
- }\r
- cout << codestr << "\r\n" << hdr << "\r\n";\r
- char buf[1024];\r
- while (in) {\r
- in.read(buf,1024);\r
- cout.write(buf, in.gcount());\r
- }\r
- return SHIB_RETURN_DONE;\r
- }\r
-\r
- long sendRedirect(const char* url) {\r
- string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
- "Content-Type: text/html\r\n"\r
- "Content-Length: 40\r\n"\r
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
- "Cache-Control: private,no-store,no-cache\r\n";\r
- for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
-\r
- cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
- return SHIB_RETURN_DONE;\r
- }\r
-\r
- long returnDecline() {\r
- return SHIB_RETURN_KO;\r
- }\r
-\r
- long returnOK() {\r
- return SHIB_RETURN_OK;\r
- }\r
-\r
- const vector<string>& getClientCertificates() const {\r
- static vector<string> g_NoCerts;\r
- return g_NoCerts;\r
- }\r
-};\r
-\r
-static void print_ok(const map<string,string>& headers)\r
-{\r
- cout << "Status: 200 OK" << "\r\n";\r
- for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {\r
- cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";\r
- }\r
- cout << "\r\n";\r
-}\r
-\r
-static void print_error(const char* msg)\r
-{\r
- cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
- SPConfig* g_Config=&SPConfig::getConfig();\r
- g_Config->setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::RequestMapping |\r
- SPConfig::InProcess |\r
- SPConfig::Logging |\r
- SPConfig::Handlers\r
- );\r
- if (!g_Config->init()) {\r
- cerr << "failed to initialize Shibboleth libraries" << endl;\r
- exit(1);\r
- }\r
-\r
- try {\r
- if (!g_Config->instantiate(NULL, true))\r
- throw runtime_error("unknown error");\r
- }\r
- catch (exception& ex) {\r
- g_Config->term();\r
- cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
- exit(1);\r
- }\r
-\r
- string g_ServerScheme;\r
- string g_ServerName;\r
- int g_ServerPort=0;\r
-\r
- // Load "authoritative" URL fields.\r
- char* var = getenv("SHIBSP_SERVER_NAME");\r
- if (var)\r
- g_ServerName = var;\r
- var = getenv("SHIBSP_SERVER_SCHEME");\r
- if (var)\r
- g_ServerScheme = var;\r
- var = getenv("SHIBSP_SERVER_PORT");\r
- if (var)\r
- g_ServerPort = atoi(var);\r
-\r
- streambuf* cout_streambuf = cout.rdbuf();\r
- streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
- FCGX_Request request;\r
-\r
- FCGX_Init();\r
- FCGX_InitRequest(&request, 0, 0);\r
-\r
- cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
- while (FCGX_Accept_r(&request) == 0)\r
- {\r
- // Note that the default bufsize (0) will cause the use of iostream\r
- // methods that require positioning (such as peek(), seek(),\r
- // unget() and putback()) to fail (in favour of more efficient IO).\r
- fcgi_streambuf cout_fcgi_streambuf(request.out);\r
- fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
- cout.rdbuf(&cout_fcgi_streambuf);\r
- cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
- try {\r
- xmltooling::NDC ndc("FastCGI shibauthorizer");\r
- ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
- pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);\r
- if (res.first) {\r
- sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");\r
- switch(res.second) {\r
- case SHIB_RETURN_OK:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_KO:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_DONE:\r
- continue;\r
-\r
- default:\r
- cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;\r
- print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
- continue;\r
- }\r
- }\r
-\r
- res = sta.getServiceProvider().doExport(sta);\r
- if (res.first) {\r
- sta.log(SPRequest::SPDebug, "shib: doExport handled request");\r
- switch(res.second) {\r
- case SHIB_RETURN_OK:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_KO:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_DONE:\r
- continue;\r
-\r
- default:\r
- cerr << "shib: doExport returned an unexpected result: " << res.second << endl;\r
- print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
- continue;\r
- }\r
- }\r
-\r
- res = sta.getServiceProvider().doAuthorization(sta);\r
- if (res.first) {\r
- sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");\r
- switch(res.second) {\r
- case SHIB_RETURN_OK:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_KO:\r
- print_ok(sta.m_request_headers);\r
- continue;\r
-\r
- case SHIB_RETURN_DONE:\r
- continue;\r
-\r
- default:\r
- cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;\r
- print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
- continue;\r
- }\r
- }\r
-\r
- print_ok(sta.m_request_headers);\r
-\r
- }\r
- catch (exception& e) {\r
- cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;\r
- print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");\r
- }\r
-\r
- // If the output streambufs had non-zero bufsizes and\r
- // were constructed outside of the accept loop (i.e.\r
- // their destructor won't be called here), they would\r
- // have to be flushed here.\r
- }\r
- cout << "Request loop ended." << endl;\r
-\r
- cout.rdbuf(cout_streambuf);\r
- cerr.rdbuf(cerr_streambuf);\r
-\r
- if (g_Config)\r
- g_Config->term();\r
-\r
- return 0;\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer
+
+ Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);
+static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+
+typedef enum {
+ SHIB_RETURN_OK,
+ SHIB_RETURN_KO,
+ SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGIAuth : public AbstractSPRequest
+{
+ FCGX_Request* m_req;
+ int m_port;
+ string m_scheme,m_hostname;
+ multimap<string,string> m_response_headers;
+public:
+ map<string,string> m_request_headers;
+
+ ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+ : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {
+ const char* server_name_str = hostname;
+ if (!server_name_str || !*server_name_str)
+ server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+ m_hostname = server_name_str;
+
+ m_port = port;
+ if (!m_port) {
+ char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+ m_port = strtol(server_port_str, &server_port_str, 10);
+ if (*server_port_str) {
+ cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+ throw runtime_error("Unable to determine server port.");
+ }
+ }
+
+ const char* server_scheme_str = scheme;
+ if (!server_scheme_str || !*server_scheme_str)
+ server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+ m_scheme = server_scheme_str;
+
+ setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+ }
+
+ ~ShibTargetFCGIAuth() { }
+
+ const char* getScheme() const {
+ return m_scheme.c_str();
+ }
+ const char* getHostname() const {
+ return m_hostname.c_str();
+ }
+ int getPort() const {
+ return m_port;
+ }
+ const char* getMethod() const {
+ return FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+ }
+ string getContentType() const {
+ const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+ return s ? s : "";
+ }
+ long getContentLength() const {
+ const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+ return s ? atol(s) : 0;
+ }
+ string getRemoteAddr() const {
+ string ret = AbstractSPRequest::getRemoteAddr();
+ if (!ret.empty())
+ return ret;
+ const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+ return s ? s : "";
+ }
+ void log(SPLogLevel level, const string& msg) const {
+ AbstractSPRequest::log(level,msg);
+ if (level >= SPError)
+ cerr << "shib: " << msg;
+ }
+ void clearHeader(const char* rawname, const char* cginame) {
+ // No need, since we use environment variables.
+ }
+ void setHeader(const char* name, const char* value) {
+ if (value)
+ m_request_headers[name] = value;
+ else
+ m_request_headers.erase(name);
+ }
+ string getHeader(const char* name) const {
+ // Look in the local map first.
+ map<string,string>::const_iterator i = m_request_headers.find(name);
+ if (i != m_request_headers.end())
+ return i->second;
+ // Nothing set locally and this isn't a "secure" call, so check the request.
+ string hdr("HTTP_");
+ for (; *name; ++name) {
+ if (*name=='-')
+ hdr += '_';
+ else
+ hdr += toupper(*name);
+ }
+ char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+ return s ? s : "";
+ }
+ string getSecureHeader(const char* name) const {
+ // Look in the local map only.
+ map<string,string>::const_iterator i = m_request_headers.find(name);
+ if (i != m_request_headers.end())
+ return i->second;
+ return "";
+ }
+ void setRemoteUser(const char* user) {
+ if (user)
+ m_request_headers["REMOTE_USER"] = user;
+ else
+ m_request_headers.erase("REMOTE_USER");
+ }
+ string getRemoteUser() const {
+ map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");
+ if (i != m_request_headers.end())
+ return i->second;
+ else {
+ char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);
+ if (remote_user)
+ return remote_user;
+ }
+ return "";
+ }
+ void setAuthType(const char* authtype) {
+ if (authtype)
+ m_request_headers["AUTH_TYPE"] = authtype;
+ else
+ m_request_headers.erase("AUTH_TYPE");
+ }
+ string getAuthType() const {
+ map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");
+ if (i != m_request_headers.end())
+ return i->second;
+ else {
+ char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);
+ if (auth_type)
+ return auth_type;
+ }
+ return "";
+ }
+ void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
+ // Set for later.
+ if (value)
+ m_response_headers.insert(make_pair(name,value));
+ else
+ m_response_headers.erase(name);
+ }
+ const char* getQueryString() const {
+ return FCGX_GetParam("QUERY_STRING", m_req->envp);
+ }
+ const char* getRequestBody() const {
+ throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");
+ }
+
+ long sendResponse(istream& in, long status) {
+ string hdr = string("Connection: close\r\n");
+ for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+ hdr += i->first + ": " + i->second + "\r\n";
+
+ // We can't return 200 OK here or else the filter is bypassed
+ // so custom Shib errors will get turned into a generic page.
+ const char* codestr="Status: 500 Server Error";
+ switch (status) {
+ case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break;
+ case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;
+ case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;
+ }
+ cout << codestr << "\r\n" << hdr << "\r\n";
+ char buf[1024];
+ while (in) {
+ in.read(buf,1024);
+ cout.write(buf, in.gcount());
+ }
+ return SHIB_RETURN_DONE;
+ }
+
+ long sendRedirect(const char* url) {
+ HTTPResponse::sendRedirect(url);
+ string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n";
+ for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+ hdr += i->first + ": " + i->second + "\r\n";
+ hdr += "\r\n";
+
+ cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+ return SHIB_RETURN_DONE;
+ }
+
+ long returnDecline() {
+ return SHIB_RETURN_KO;
+ }
+
+ long returnOK() {
+ return SHIB_RETURN_OK;
+ }
+
+ const vector<string>& getClientCertificates() const {
+ static vector<string> g_NoCerts;
+ return g_NoCerts;
+ }
+};
+
+static void print_ok(const map<string,string>& headers)
+{
+ cout << "Status: 200 OK" << "\r\n";
+ for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {
+ cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";
+ }
+ cout << "\r\n";
+}
+
+static void print_error(const char* msg)
+{
+ cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+ SPConfig* g_Config=&SPConfig::getConfig();
+ g_Config->setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::RequestMapping |
+ SPConfig::InProcess |
+ SPConfig::Logging |
+ SPConfig::Handlers
+ );
+ if (!g_Config->init()) {
+ cerr << "failed to initialize Shibboleth libraries" << endl;
+ exit(1);
+ }
+
+ try {
+ if (!g_Config->instantiate(NULL, true))
+ throw runtime_error("unknown error");
+ }
+ catch (exception& ex) {
+ g_Config->term();
+ cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+ exit(1);
+ }
+
+ string g_ServerScheme;
+ string g_ServerName;
+ int g_ServerPort=0;
+
+ // Load "authoritative" URL fields.
+ char* var = getenv("SHIBSP_SERVER_NAME");
+ if (var)
+ g_ServerName = var;
+ var = getenv("SHIBSP_SERVER_SCHEME");
+ if (var)
+ g_ServerScheme = var;
+ var = getenv("SHIBSP_SERVER_PORT");
+ if (var)
+ g_ServerPort = atoi(var);
+
+ streambuf* cout_streambuf = cout.rdbuf();
+ streambuf* cerr_streambuf = cerr.rdbuf();
+
+ FCGX_Request request;
+
+ FCGX_Init();
+ FCGX_InitRequest(&request, 0, 0);
+
+ cout << "Shibboleth initialization complete. Starting request loop." << endl;
+ while (FCGX_Accept_r(&request) == 0)
+ {
+ // Note that the default bufsize (0) will cause the use of iostream
+ // methods that require positioning (such as peek(), seek(),
+ // unget() and putback()) to fail (in favour of more efficient IO).
+ fcgi_streambuf cout_fcgi_streambuf(request.out);
+ fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+ cout.rdbuf(&cout_fcgi_streambuf);
+ cerr.rdbuf(&cerr_fcgi_streambuf);
+
+ try {
+ xmltooling::NDC ndc("FastCGI shibauthorizer");
+ ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+ pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);
+ if (res.first) {
+ sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");
+ switch(res.second) {
+ case SHIB_RETURN_OK:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_KO:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_DONE:
+ continue;
+
+ default:
+ cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;
+ print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+ continue;
+ }
+ }
+
+ res = sta.getServiceProvider().doExport(sta);
+ if (res.first) {
+ sta.log(SPRequest::SPDebug, "shib: doExport handled request");
+ switch(res.second) {
+ case SHIB_RETURN_OK:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_KO:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_DONE:
+ continue;
+
+ default:
+ cerr << "shib: doExport returned an unexpected result: " << res.second << endl;
+ print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+ continue;
+ }
+ }
+
+ res = sta.getServiceProvider().doAuthorization(sta);
+ if (res.first) {
+ sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");
+ switch(res.second) {
+ case SHIB_RETURN_OK:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_KO:
+ print_ok(sta.m_request_headers);
+ continue;
+
+ case SHIB_RETURN_DONE:
+ continue;
+
+ default:
+ cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;
+ print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+ continue;
+ }
+ }
+
+ print_ok(sta.m_request_headers);
+
+ }
+ catch (exception& e) {
+ cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;
+ print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");
+ }
+
+ // If the output streambufs had non-zero bufsizes and
+ // were constructed outside of the accept loop (i.e.
+ // their destructor won't be called here), they would
+ // have to be flushed here.
+ }
+ cout << "Request loop ended." << endl;
+
+ cout.rdbuf(cout_streambuf);
+ cerr.rdbuf(cerr_streambuf);
+
+ if (g_Config)
+ g_Config->term();
+
+ return 0;
+}
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
FILEFLAGSMASK 0x3fL\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
VALUE "Comments", "\0"\r
VALUE "CompanyName", "Internet2\0"\r
VALUE "FileDescription", "Shibboleth FastCGI Authorizer\0"\r
- VALUE "FileVersion", "2, 2, 1, 0\0"\r
+ VALUE "FileVersion", "2, 3, 0, 0\0"\r
VALUE "InternalName", "shibauthorizer\0"\r
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"\r
VALUE "LegalTrademarks", "\0"\r
VALUE "OriginalFilename", "shibauthorizer.exe\0"\r
VALUE "PrivateBuild", "\0"\r
- VALUE "ProductName", "Shibboleth 2.2.1\0"\r
- VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+ VALUE "ProductName", "Shibboleth 2.3\0"\r
+ VALUE "ProductVersion", "2, 3, 0, 0\0"\r
VALUE "SpecialBuild", "\0"\r
END\r
END\r
-/*\r
- * Copyright 2001-2007 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler\r
-\r
- Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
- SHIB_RETURN_OK,\r
- SHIB_RETURN_KO,\r
- SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGI : public AbstractSPRequest\r
-{\r
- FCGX_Request* m_req;\r
- const char* m_body;\r
- multimap<string,string> m_headers;\r
- int m_port;\r
- string m_scheme,m_hostname;\r
-\r
-public:\r
- ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
- : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {\r
-\r
- const char* server_name_str = hostname;\r
- if (!server_name_str || !*server_name_str)\r
- server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
- m_hostname = server_name_str;\r
-\r
- m_port = port;\r
- if (!m_port) {\r
- char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
- m_port = strtol(server_port_str, &server_port_str, 10);\r
- if (*server_port_str) {\r
- cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
- throw runtime_error("Unable to determine server port.");\r
- }\r
- }\r
-\r
- const char* server_scheme_str = scheme;\r
- if (!server_scheme_str || !*server_scheme_str)\r
- server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
- m_scheme = server_scheme_str;\r
-\r
- setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
- }\r
-\r
- ~ShibTargetFCGI() { }\r
-\r
- const char* getScheme() const {\r
- return m_scheme.c_str();\r
- }\r
- const char* getHostname() const {\r
- return m_hostname.c_str();\r
- }\r
- int getPort() const {\r
- return m_port;\r
- }\r
- const char* getMethod() const {\r
- return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
- }\r
- string getContentType() const {\r
- const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
- return s ? s : "";\r
- }\r
- long getContentLength() const {\r
- const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
- return s ? atol(s) : 0;\r
- }\r
- string getRemoteUser() const {\r
- const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
- return s ? s : "";\r
- }\r
- string getRemoteAddr() const {\r
- string ret = AbstractSPRequest::getRemoteAddr();\r
- if (!ret.empty())\r
- return ret;\r
- const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
- return s ? s : "";\r
- }\r
- void log(SPLogLevel level, const string& msg) const {\r
- AbstractSPRequest::log(level,msg);\r
- if (level >= SPError)\r
- cerr << "shib: " << msg;\r
- }\r
-\r
- string getHeader(const char* name) const {\r
- string hdr("HTTP_");\r
- for (; *name; ++name) {\r
- if (*name=='-')\r
- hdr += '_';\r
- else\r
- hdr += toupper(*name);\r
- }\r
- char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
- return s ? s : "";\r
- }\r
-\r
- void setResponseHeader(const char* name, const char* value) {\r
- // Set for later.\r
- if (value)\r
- m_headers.insert(make_pair(name,value));\r
- else\r
- m_headers.erase(name);\r
- }\r
-\r
- const char* getQueryString() const {\r
- return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
- }\r
-\r
- const char* getRequestBody() const {\r
- return m_body;\r
- }\r
-\r
- long sendResponse(istream& in, long status) {\r
- string hdr = string("Connection: close\r\n");\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
-\r
- const char* codestr="Status: 200 OK";\r
- switch (status) {\r
- case XMLTOOLING_HTTP_STATUS_ERROR: codestr="Status: 500 Server Error"; break;\r
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break;\r
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;\r
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;\r
- }\r
- cout << codestr << "\r\n" << hdr << "\r\n";\r
- char buf[1024];\r
- while (in) {\r
- in.read(buf,1024);\r
- cout.write(buf, in.gcount());\r
- }\r
- return SHIB_RETURN_DONE;\r
- }\r
-\r
- long sendRedirect(const char* url) {\r
- string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
- "Content-Type: text/html\r\n"\r
- "Content-Length: 40\r\n"\r
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
- "Cache-Control: private,no-store,no-cache\r\n";\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
-\r
- cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
- return SHIB_RETURN_DONE;\r
- }\r
-\r
- long returnDecline() {\r
- return SHIB_RETURN_KO;\r
- }\r
- long returnOK() {\r
- return SHIB_RETURN_OK;\r
- }\r
-\r
- const vector<string>& getClientCertificates() const {\r
- static vector<string> g_NoCerts;\r
- return g_NoCerts;\r
- }\r
-\r
- // Not used in the extension.\r
-\r
- virtual void clearHeader(const char* rawname, const char* cginame) {\r
- throw runtime_error("clearHeader not implemented by FastCGI responder.");\r
- }\r
-\r
- virtual void setHeader(const char* name, const char* value) {\r
- throw runtime_error("setHeader not implemented by FastCGI responder.");\r
- }\r
-\r
- virtual void setRemoteUser(const char* user) {\r
- throw runtime_error("setRemoteUser not implemented by FastCGI responder.");\r
- }\r
-};\r
-\r
-// Maximum number of bytes allowed to be read from stdin\r
-static const unsigned long STDIN_MAX = 1000000;\r
-\r
-static long gstdin(FCGX_Request* request, char** content)\r
-{\r
- char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);\r
- unsigned long clen = STDIN_MAX;\r
-\r
- if (clenstr) {\r
- clen = strtol(clenstr, &clenstr, 10);\r
- if (*clenstr) {\r
- cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;\r
- clen = STDIN_MAX;\r
- }\r
-\r
- // *always* put a cap on the amount of data that will be read\r
- if (clen > STDIN_MAX)\r
- clen = STDIN_MAX;\r
-\r
- *content = new char[clen];\r
-\r
- cin.read(*content, clen);\r
- clen = cin.gcount();\r
- }\r
- else {\r
- // *never* read stdin when CONTENT_LENGTH is missing or unparsable\r
- *content = 0;\r
- clen = 0;\r
- }\r
-\r
- // Chew up any remaining stdin - this shouldn't be necessary\r
- // but is because mod_fastcgi doesn't handle it correctly.\r
-\r
- // ignore() doesn't set the eof bit in some versions of glibc++\r
- // so use gcount() instead of eof()...\r
- do cin.ignore(1024); while (cin.gcount() == 1024);\r
-\r
- return clen;\r
-}\r
-\r
-static void print_ok() {\r
- cout << "Status: 200 OK" << "\r\n\r\n";\r
-}\r
-\r
-static void print_error(const char* msg) {\r
- cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
- SPConfig* g_Config=&SPConfig::getConfig();\r
- g_Config->setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::RequestMapping |\r
- SPConfig::InProcess |\r
- SPConfig::Logging |\r
- SPConfig::Handlers\r
- );\r
- if (!g_Config->init()) {\r
- cerr << "failed to initialize Shibboleth libraries" << endl;\r
- exit(1);\r
- }\r
-\r
- try {\r
- if (!g_Config->instantiate(NULL, true))\r
- throw runtime_error("unknown error");\r
- }\r
- catch (exception& ex) {\r
- g_Config->term();\r
- cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
- exit(1);\r
- }\r
-\r
- string g_ServerScheme;\r
- string g_ServerName;\r
- int g_ServerPort=0;\r
-\r
- // Load "authoritative" URL fields.\r
- char* var = getenv("SHIBSP_SERVER_NAME");\r
- if (var)\r
- g_ServerName = var;\r
- var = getenv("SHIBSP_SERVER_SCHEME");\r
- if (var)\r
- g_ServerScheme = var;\r
- var = getenv("SHIBSP_SERVER_PORT");\r
- if (var)\r
- g_ServerPort = atoi(var);\r
-\r
- streambuf* cin_streambuf = cin.rdbuf();\r
- streambuf* cout_streambuf = cout.rdbuf();\r
- streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
- FCGX_Request request;\r
-\r
- FCGX_Init();\r
- FCGX_InitRequest(&request, 0, 0);\r
-\r
- cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
- while (FCGX_Accept_r(&request) == 0) {\r
- // Note that the default bufsize (0) will cause the use of iostream\r
- // methods that require positioning (such as peek(), seek(),\r
- // unget() and putback()) to fail (in favour of more efficient IO).\r
- fcgi_streambuf cin_fcgi_streambuf(request.in);\r
- fcgi_streambuf cout_fcgi_streambuf(request.out);\r
- fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
- cin.rdbuf(&cin_fcgi_streambuf);\r
- cout.rdbuf(&cout_fcgi_streambuf);\r
- cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
- // Although FastCGI supports writing before reading,\r
- // many http clients (browsers) don't support it (so\r
- // the connection deadlocks until a timeout expires!).\r
- char* content;\r
- gstdin(&request, &content);\r
-\r
- try {\r
- xmltooling::NDC ndc("FastCGI shibresponder");\r
- ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
- pair<bool,long> res = stf.getServiceProvider().doHandler(stf);\r
- if (res.first) {\r
- stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");\r
- switch(res.second) {\r
- case SHIB_RETURN_OK:\r
- print_ok();\r
- break;\r
-\r
- case SHIB_RETURN_KO:\r
- cerr << "shib: doHandler failed to handle the request" << endl;\r
- print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");\r
- break;\r
-\r
- case SHIB_RETURN_DONE:\r
- // response already handled\r
- break;\r
-\r
- default:\r
- cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;\r
- print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");\r
- break;\r
- }\r
- }\r
- else {\r
- cerr << "shib: doHandler failed to handle request." << endl;\r
- print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");\r
- }\r
-\r
- }\r
- catch (exception& e) {\r
- cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;\r
- print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");\r
- }\r
-\r
- delete[] content;\r
-\r
- // If the output streambufs had non-zero bufsizes and\r
- // were constructed outside of the accept loop (i.e.\r
- // their destructor won't be called here), they would\r
- // have to be flushed here.\r
- }\r
-\r
- cout << "Request loop ended." << endl;\r
-\r
- cin.rdbuf(cin_streambuf);\r
- cout.rdbuf(cout_streambuf);\r
- cerr.rdbuf(cerr_streambuf);\r
-\r
- if (g_Config)\r
- g_Config->term();\r
-\r
- return 0;\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler
+
+ Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);
+static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+
+typedef enum {
+ SHIB_RETURN_OK,
+ SHIB_RETURN_KO,
+ SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGI : public AbstractSPRequest
+{
+ FCGX_Request* m_req;
+ const char* m_body;
+ multimap<string,string> m_headers;
+ int m_port;
+ string m_scheme,m_hostname;
+
+public:
+ ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+ : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {
+
+ const char* server_name_str = hostname;
+ if (!server_name_str || !*server_name_str)
+ server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+ m_hostname = server_name_str;
+
+ m_port = port;
+ if (!m_port) {
+ char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+ m_port = strtol(server_port_str, &server_port_str, 10);
+ if (*server_port_str) {
+ cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+ throw runtime_error("Unable to determine server port.");
+ }
+ }
+
+ const char* server_scheme_str = scheme;
+ if (!server_scheme_str || !*server_scheme_str)
+ server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+ m_scheme = server_scheme_str;
+
+ setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+ }
+
+ ~ShibTargetFCGI() { }
+
+ const char* getScheme() const {
+ return m_scheme.c_str();
+ }
+ const char* getHostname() const {
+ return m_hostname.c_str();
+ }
+ int getPort() const {
+ return m_port;
+ }
+ const char* getMethod() const {
+ return FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+ }
+ string getContentType() const {
+ const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+ return s ? s : "";
+ }
+ long getContentLength() const {
+ const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+ return s ? atol(s) : 0;
+ }
+ string getRemoteUser() const {
+ const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);
+ return s ? s : "";
+ }
+ string getRemoteAddr() const {
+ string ret = AbstractSPRequest::getRemoteAddr();
+ if (!ret.empty())
+ return ret;
+ const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+ return s ? s : "";
+ }
+ void log(SPLogLevel level, const string& msg) const {
+ AbstractSPRequest::log(level,msg);
+ if (level >= SPError)
+ cerr << "shib: " << msg;
+ }
+
+ string getHeader(const char* name) const {
+ string hdr("HTTP_");
+ for (; *name; ++name) {
+ if (*name=='-')
+ hdr += '_';
+ else
+ hdr += toupper(*name);
+ }
+ char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+ return s ? s : "";
+ }
+
+ void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
+ // Set for later.
+ if (value)
+ m_headers.insert(make_pair(name,value));
+ else
+ m_headers.erase(name);
+ }
+
+ const char* getQueryString() const {
+ return FCGX_GetParam("QUERY_STRING", m_req->envp);
+ }
+
+ const char* getRequestBody() const {
+ return m_body;
+ }
+
+ long sendResponse(istream& in, long status) {
+ string hdr = string("Connection: close\r\n");
+ for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+ hdr += i->first + ": " + i->second + "\r\n";
+
+ const char* codestr="Status: 200 OK";
+ switch (status) {
+ case XMLTOOLING_HTTP_STATUS_ERROR: codestr="Status: 500 Server Error"; break;
+ case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break;
+ case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;
+ case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;
+ }
+ cout << codestr << "\r\n" << hdr << "\r\n";
+ char buf[1024];
+ while (in) {
+ in.read(buf,1024);
+ cout.write(buf, in.gcount());
+ }
+ return SHIB_RETURN_DONE;
+ }
+
+ long sendRedirect(const char* url) {
+ HTTPResponse::sendRedirect(url);
+ string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n";
+ for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+ hdr += i->first + ": " + i->second + "\r\n";
+ hdr += "\r\n";
+
+ cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+ return SHIB_RETURN_DONE;
+ }
+
+ long returnDecline() {
+ return SHIB_RETURN_KO;
+ }
+ long returnOK() {
+ return SHIB_RETURN_OK;
+ }
+
+ const vector<string>& getClientCertificates() const {
+ static vector<string> g_NoCerts;
+ return g_NoCerts;
+ }
+
+ // Not used in the extension.
+
+ virtual void clearHeader(const char* rawname, const char* cginame) {
+ throw runtime_error("clearHeader not implemented by FastCGI responder.");
+ }
+
+ virtual void setHeader(const char* name, const char* value) {
+ throw runtime_error("setHeader not implemented by FastCGI responder.");
+ }
+
+ virtual void setRemoteUser(const char* user) {
+ throw runtime_error("setRemoteUser not implemented by FastCGI responder.");
+ }
+};
+
+// Maximum number of bytes allowed to be read from stdin
+static const unsigned long STDIN_MAX = 1000000;
+
+static long gstdin(FCGX_Request* request, char** content)
+{
+ char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);
+ unsigned long clen = STDIN_MAX;
+
+ if (clenstr) {
+ clen = strtol(clenstr, &clenstr, 10);
+ if (*clenstr) {
+ cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;
+ clen = STDIN_MAX;
+ }
+
+ // *always* put a cap on the amount of data that will be read
+ if (clen > STDIN_MAX)
+ clen = STDIN_MAX;
+
+ *content = new char[clen];
+
+ cin.read(*content, clen);
+ clen = cin.gcount();
+ }
+ else {
+ // *never* read stdin when CONTENT_LENGTH is missing or unparsable
+ *content = 0;
+ clen = 0;
+ }
+
+ // Chew up any remaining stdin - this shouldn't be necessary
+ // but is because mod_fastcgi doesn't handle it correctly.
+
+ // ignore() doesn't set the eof bit in some versions of glibc++
+ // so use gcount() instead of eof()...
+ do cin.ignore(1024); while (cin.gcount() == 1024);
+
+ return clen;
+}
+
+static void print_ok() {
+ cout << "Status: 200 OK" << "\r\n\r\n";
+}
+
+static void print_error(const char* msg) {
+ cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+ SPConfig* g_Config=&SPConfig::getConfig();
+ g_Config->setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::RequestMapping |
+ SPConfig::InProcess |
+ SPConfig::Logging |
+ SPConfig::Handlers
+ );
+ if (!g_Config->init()) {
+ cerr << "failed to initialize Shibboleth libraries" << endl;
+ exit(1);
+ }
+
+ try {
+ if (!g_Config->instantiate(NULL, true))
+ throw runtime_error("unknown error");
+ }
+ catch (exception& ex) {
+ g_Config->term();
+ cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+ exit(1);
+ }
+
+ string g_ServerScheme;
+ string g_ServerName;
+ int g_ServerPort=0;
+
+ // Load "authoritative" URL fields.
+ char* var = getenv("SHIBSP_SERVER_NAME");
+ if (var)
+ g_ServerName = var;
+ var = getenv("SHIBSP_SERVER_SCHEME");
+ if (var)
+ g_ServerScheme = var;
+ var = getenv("SHIBSP_SERVER_PORT");
+ if (var)
+ g_ServerPort = atoi(var);
+
+ streambuf* cin_streambuf = cin.rdbuf();
+ streambuf* cout_streambuf = cout.rdbuf();
+ streambuf* cerr_streambuf = cerr.rdbuf();
+
+ FCGX_Request request;
+
+ FCGX_Init();
+ FCGX_InitRequest(&request, 0, 0);
+
+ cout << "Shibboleth initialization complete. Starting request loop." << endl;
+ while (FCGX_Accept_r(&request) == 0) {
+ // Note that the default bufsize (0) will cause the use of iostream
+ // methods that require positioning (such as peek(), seek(),
+ // unget() and putback()) to fail (in favour of more efficient IO).
+ fcgi_streambuf cin_fcgi_streambuf(request.in);
+ fcgi_streambuf cout_fcgi_streambuf(request.out);
+ fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+ cin.rdbuf(&cin_fcgi_streambuf);
+ cout.rdbuf(&cout_fcgi_streambuf);
+ cerr.rdbuf(&cerr_fcgi_streambuf);
+
+ // Although FastCGI supports writing before reading,
+ // many http clients (browsers) don't support it (so
+ // the connection deadlocks until a timeout expires!).
+ char* content;
+ gstdin(&request, &content);
+
+ try {
+ xmltooling::NDC ndc("FastCGI shibresponder");
+ ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+ pair<bool,long> res = stf.getServiceProvider().doHandler(stf);
+ if (res.first) {
+ stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");
+ switch(res.second) {
+ case SHIB_RETURN_OK:
+ print_ok();
+ break;
+
+ case SHIB_RETURN_KO:
+ cerr << "shib: doHandler failed to handle the request" << endl;
+ print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");
+ break;
+
+ case SHIB_RETURN_DONE:
+ // response already handled
+ break;
+
+ default:
+ cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;
+ print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");
+ break;
+ }
+ }
+ else {
+ cerr << "shib: doHandler failed to handle request." << endl;
+ print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");
+ }
+
+ }
+ catch (exception& e) {
+ cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;
+ print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");
+ }
+
+ delete[] content;
+
+ // If the output streambufs had non-zero bufsizes and
+ // were constructed outside of the accept loop (i.e.
+ // their destructor won't be called here), they would
+ // have to be flushed here.
+ }
+
+ cout << "Request loop ended." << endl;
+
+ cin.rdbuf(cin_streambuf);
+ cout.rdbuf(cout_streambuf);
+ cerr.rdbuf(cerr_streambuf);
+
+ if (g_Config)
+ g_Config->term();
+
+ return 0;
+}
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
FILEFLAGSMASK 0x3fL\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
VALUE "Comments", "\0"\r
VALUE "CompanyName", "Internet2\0"\r
VALUE "FileDescription", "Shibboleth FastCGI Responder\0"\r
- VALUE "FileVersion", "2, 2, 1, 0\0"\r
+ VALUE "FileVersion", "2, 3, 0, 0\0"\r
VALUE "InternalName", "shibresponder\0"\r
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"\r
VALUE "LegalTrademarks", "\0"\r
VALUE "OriginalFilename", "shibresponder.exe\0"\r
VALUE "PrivateBuild", "\0"\r
- VALUE "ProductName", "Shibboleth 2.2.1\0"\r
- VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+ VALUE "ProductName", "Shibboleth 2.3\0"\r
+ VALUE "ProductVersion", "2, 3, 0, 0\0"\r
VALUE "SpecialBuild", "\0"\r
END\r
END\r
#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 <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <process.h>
#include <xmltooling/unicode.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
#include <xercesc/util/Base64.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
#include <windows.h>
#include <httpfilt.h>
#include <httpext.h>
flag=props->getBool("catchAll");
g_catchAll = flag.first && flag.second;
-<<<<<<< .mine
- 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 {
- 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) {
- ostringstream keystr;
- keystr << randkey << randkey2 << randkey3 << randkey4;
- g_spoofKey = keystr.str();
- }
- else {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
- g_Config->term();
- g_Config=NULL;
- return FALSE;
- }
- }
- }
-
-=======
pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
if (unsetValue.first)
g_unsetHeaderValue = unsetValue.second;
}
}
->>>>>>> .r3097
props = props->getPropertySet("ISAPI");
if (props) {
flag = props->getBool("normalizeRequest");
return getSecureHeader("remote-user");
}
void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
// Set for later.
if (value)
m_headers.insert(make_pair(name,value));
return SF_STATUS_REQ_FINISHED;
}
long sendRedirect(const char* url) {
- // XXX: Don't support the httpRedirect option, yet.
+ HTTPResponse::sendRedirect(url);
string hdr=string("Location: ") + url + "\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 40\r\n"
return buf.empty() ? "" : buf;
}
void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
// Set for later.
if (value)
m_headers.insert(make_pair(name,value));
return HSE_STATUS_SUCCESS;
}
long sendRedirect(const char* url) {
+ HTTPResponse::sendRedirect(url);
string hdr=string("Location: ") + url + "\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 40\r\n"
+++ /dev/null
-/*\r
- * Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * isapi_shib.cpp\r
- *\r
- * Shibboleth ISAPI filter\r
- */\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _CRT_RAND_S\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/Base64.hpp>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <set>\r
-#include <sstream>\r
-#include <fstream>\r
-#include <stdexcept>\r
-#include <process.h>\r
-\r
-#include <windows.h>\r
-#include <httpfilt.h>\r
-#include <httpext.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-// globals\r
-namespace {\r
- static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);\r
- static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
- static const XMLCh name[] = UNICODE_LITERAL_4(n,a,m,e);\r
- static const XMLCh port[] = UNICODE_LITERAL_4(p,o,r,t);\r
- static const XMLCh sslport[] = UNICODE_LITERAL_7(s,s,l,p,o,r,t);\r
- static const XMLCh scheme[] = UNICODE_LITERAL_6(s,c,h,e,m,e);\r
- static const XMLCh id[] = UNICODE_LITERAL_2(i,d);\r
- static const XMLCh Alias[] = UNICODE_LITERAL_5(A,l,i,a,s);\r
- static const XMLCh Site[] = UNICODE_LITERAL_4(S,i,t,e);\r
-\r
- struct site_t {\r
- site_t(const DOMElement* e)\r
- {\r
- auto_ptr_char n(e->getAttributeNS(NULL,name));\r
- auto_ptr_char s(e->getAttributeNS(NULL,scheme));\r
- auto_ptr_char p(e->getAttributeNS(NULL,port));\r
- auto_ptr_char p2(e->getAttributeNS(NULL,sslport));\r
- if (n.get()) m_name=n.get();\r
- if (s.get()) m_scheme=s.get();\r
- if (p.get()) m_port=p.get();\r
- if (p2.get()) m_sslport=p2.get();\r
- e = XMLHelper::getFirstChildElement(e, Alias);\r
- while (e) {\r
- if (e->hasChildNodes()) {\r
- auto_ptr_char alias(e->getFirstChild()->getNodeValue());\r
- m_aliases.insert(alias.get());\r
- }\r
- e = XMLHelper::getNextSiblingElement(e, Alias);\r
- }\r
- }\r
- string m_scheme,m_port,m_sslport,m_name;\r
- set<string> m_aliases;\r
- };\r
-\r
- HINSTANCE g_hinstDLL;\r
- SPConfig* g_Config = NULL;\r
- map<string,site_t> g_Sites;\r
- bool g_bNormalizeRequest = true;\r
- string g_unsetHeaderValue,g_spoofKey;\r
- bool g_checkSpoofing = true;\r
- bool g_catchAll = false;\r
- bool g_bSafeHeaderNames = false;\r
- vector<string> g_NoCerts;\r
-}\r
-\r
-BOOL LogEvent(\r
- LPCSTR lpUNCServerName,\r
- WORD wType,\r
- DWORD dwEventID,\r
- PSID lpUserSid,\r
- LPCSTR message)\r
-{\r
- LPCSTR messages[] = {message, NULL};\r
-\r
- HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");\r
- BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
- return (DeregisterEventSource(hElog) && res);\r
-}\r
-\r
-extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)\r
-{\r
- if (fdwReason==DLL_PROCESS_ATTACH)\r
- g_hinstDLL=hinstDLL;\r
- return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)\r
-{\r
- if (!pVer)\r
- return FALSE;\r
-\r
- if (!g_Config) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
- "Extension mode startup not possible, is the DLL loaded as a filter?");\r
- return FALSE;\r
- }\r
-\r
- pVer->dwExtensionVersion=HSE_VERSION;\r
- strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);\r
- return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI TerminateExtension(DWORD)\r
-{\r
- return TRUE; // cleanup should happen when filter unloads\r
-}\r
-\r
-extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)\r
-{\r
- if (!pVer)\r
- return FALSE;\r
- else if (g_Config) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
- "Reentrant filter initialization, ignoring...");\r
- return TRUE;\r
- }\r
-\r
- g_Config=&SPConfig::getConfig();\r
- g_Config->setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::RequestMapping |\r
- SPConfig::InProcess |\r
- SPConfig::Logging |\r
- SPConfig::Handlers\r
- );\r
- if (!g_Config->init()) {\r
- g_Config=NULL;\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
- "Filter startup failed during library initialization, check native log for help.");\r
- return FALSE;\r
- }\r
-\r
- try {\r
- if (!g_Config->instantiate(NULL, true))\r
- throw runtime_error("unknown error");\r
- }\r
- catch (exception& ex) {\r
- g_Config->term();\r
- g_Config=NULL;\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
- "Filter startup failed to load configuration, check native log for details.");\r
- return FALSE;\r
- }\r
-\r
- // Access implementation-specifics and site mappings.\r
- ServiceProvider* sp=g_Config->getServiceProvider();\r
- Locker locker(sp);\r
- const PropertySet* props=sp->getPropertySet("InProcess");\r
- if (props) {\r
- pair<bool,bool> flag=props->getBool("checkSpoofing");\r
- g_checkSpoofing = !flag.first || flag.second;\r
- flag=props->getBool("catchAll");\r
- g_catchAll = flag.first && flag.second;\r
-\r
- pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");\r
- if (unsetValue.first)\r
- g_unsetHeaderValue = unsetValue.second;\r
- if (g_checkSpoofing) {\r
- unsetValue = props->getString("spoofKey");\r
- if (unsetValue.first)\r
- g_spoofKey = unsetValue.second;\r
- else {\r
- unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;\r
- if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {\r
- ostringstream keystr;\r
- keystr << randkey << randkey2 << randkey3 << randkey4;\r
- g_spoofKey = keystr.str();\r
- }\r
- else {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
- "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");\r
- g_Config->term();\r
- g_Config=NULL;\r
- return FALSE;\r
- }\r
- }\r
- }\r
-\r
- props = props->getPropertySet("ISAPI");\r
- if (props) {\r
- flag = props->getBool("normalizeRequest");\r
- g_bNormalizeRequest = !flag.first || flag.second;\r
- flag = props->getBool("safeHeaderNames");\r
- g_bSafeHeaderNames = flag.first && flag.second;\r
- const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);\r
- while (child) {\r
- auto_ptr_char id(child->getAttributeNS(NULL,id));\r
- if (id.get())\r
- g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));\r
- child=XMLHelper::getNextSiblingElement(child,Site);\r
- }\r
- }\r
- }\r
-\r
- pVer->dwFilterVersion=HTTP_FILTER_REVISION;\r
- strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);\r
- pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |\r
- SF_NOTIFY_SECURE_PORT |\r
- SF_NOTIFY_NONSECURE_PORT |\r
- SF_NOTIFY_PREPROC_HEADERS |\r
- SF_NOTIFY_LOG);\r
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");\r
- return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI TerminateFilter(DWORD)\r
-{\r
- if (g_Config)\r
- g_Config->term();\r
- g_Config = NULL;\r
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");\r
- return TRUE;\r
-}\r
-\r
-/* Next up, some suck-free versions of various APIs.\r
-\r
- You DON'T require people to guess the buffer size and THEN tell them the right size.\r
- Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that\r
- constant strings aren't typed as such, making it just that much harder. These versions\r
- are now updated to use a special growable buffer object, modeled after the standard\r
- string class. The standard string won't work because they left out the option to\r
- pre-allocate a non-constant buffer.\r
-*/\r
-\r
-class dynabuf\r
-{\r
-public:\r
- dynabuf() { bufptr=NULL; buflen=0; }\r
- dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }\r
- ~dynabuf() { delete[] bufptr; }\r
- size_t length() const { return bufptr ? strlen(bufptr) : 0; }\r
- size_t size() const { return buflen; }\r
- bool empty() const { return length()==0; }\r
- void reserve(size_t s, bool keep=false);\r
- void erase() { if (bufptr) memset(bufptr,0,buflen); }\r
- operator char*() { return bufptr; }\r
- bool operator ==(const char* s) const;\r
- bool operator !=(const char* s) const { return !(*this==s); }\r
-private:\r
- char* bufptr;\r
- size_t buflen;\r
-};\r
-\r
-void dynabuf::reserve(size_t s, bool keep)\r
-{\r
- if (s<=buflen)\r
- return;\r
- char* p=new char[s];\r
- if (keep)\r
- while (buflen--)\r
- p[buflen]=bufptr[buflen];\r
- buflen=s;\r
- delete[] bufptr;\r
- bufptr=p;\r
-}\r
-\r
-bool dynabuf::operator==(const char* s) const\r
-{\r
- if (buflen==NULL || s==NULL)\r
- return (buflen==NULL && s==NULL);\r
- else\r
- return strcmp(bufptr,s)==0;\r
-}\r
-\r
-void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
- s.reserve(size);\r
- s.erase();\r
- size=s.size();\r
-\r
- while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {\r
- // Grumble. Check the error.\r
- DWORD e=GetLastError();\r
- if (e==ERROR_INSUFFICIENT_BUFFER)\r
- s.reserve(size);\r
- else\r
- break;\r
- }\r
- if (bRequired && s.empty())\r
- throw ERROR_NO_DATA;\r
-}\r
-\r
-void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
- s.reserve(size);\r
- s.erase();\r
- size=s.size();\r
-\r
- while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {\r
- // Grumble. Check the error.\r
- DWORD e=GetLastError();\r
- if (e==ERROR_INSUFFICIENT_BUFFER)\r
- s.reserve(size);\r
- else\r
- break;\r
- }\r
- if (bRequired && s.empty())\r
- throw ERROR_NO_DATA;\r
-}\r
-\r
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,\r
- LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
- s.reserve(size);\r
- s.erase();\r
- size=s.size();\r
-\r
- while (!pn->GetHeader(pfc,lpszName,s,&size)) {\r
- // Grumble. Check the error.\r
- DWORD e=GetLastError();\r
- if (e==ERROR_INSUFFICIENT_BUFFER)\r
- s.reserve(size);\r
- else\r
- break;\r
- }\r
- if (bRequired && s.empty())\r
- throw ERROR_NO_DATA;\r
-}\r
-\r
-/****************************************************************************/\r
-// ISAPI Filter\r
-\r
-class ShibTargetIsapiF : public AbstractSPRequest\r
-{\r
- PHTTP_FILTER_CONTEXT m_pfc;\r
- PHTTP_FILTER_PREPROC_HEADERS m_pn;\r
- multimap<string,string> m_headers;\r
- int m_port;\r
- string m_scheme,m_hostname;\r
- mutable string m_remote_addr,m_content_type,m_method;\r
- dynabuf m_allhttp;\r
- bool m_firsttime;\r
-\r
-public:\r
- ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)\r
- : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {\r
-\r
- // URL path always come from IIS.\r
- dynabuf var(256);\r
- GetHeader(pn,pfc,"url",var,256,false);\r
- setRequestURI(var);\r
-\r
- // Port may come from IIS or from site def.\r
- if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {\r
- GetServerVariable(pfc,"SERVER_PORT",var,10);\r
- m_port = atoi(var);\r
- }\r
- else if (pfc->fIsSecurePort) {\r
- m_port = atoi(site.m_sslport.c_str());\r
- }\r
- else {\r
- m_port = atoi(site.m_port.c_str());\r
- }\r
-\r
- // Scheme may come from site def or be derived from IIS.\r
- m_scheme=site.m_scheme;\r
- if (m_scheme.empty() || !g_bNormalizeRequest)\r
- m_scheme=pfc->fIsSecurePort ? "https" : "http";\r
-\r
- GetServerVariable(pfc,"SERVER_NAME",var,32);\r
-\r
- // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
- m_hostname = var;\r
- if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
- m_hostname=site.m_name;\r
-\r
- if (!g_spoofKey.empty()) {\r
- GetHeader(pn, pfc, "ShibSpoofCheck:", var, 32, false);\r
- if (!var.empty() && g_spoofKey == (char*)var)\r
- m_firsttime = false;\r
- }\r
-\r
- if (!m_firsttime)\r
- log(SPDebug, "ISAPI filter running more than once");\r
- }\r
- ~ShibTargetIsapiF() { }\r
-\r
- const char* getScheme() const {\r
- return m_scheme.c_str();\r
- }\r
- const char* getHostname() const {\r
- return m_hostname.c_str();\r
- }\r
- int getPort() const {\r
- return m_port;\r
- }\r
- const char* getQueryString() const {\r
- const char* uri = getRequestURI();\r
- uri = (uri ? strchr(uri, '?') : NULL);\r
- return uri ? (uri + 1) : NULL;\r
- }\r
- const char* getMethod() const {\r
- if (m_method.empty()) {\r
- dynabuf var(5);\r
- GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);\r
- if (!var.empty())\r
- m_method = var;\r
- }\r
- return m_method.c_str();\r
- }\r
- string getContentType() const {\r
- if (m_content_type.empty()) {\r
- dynabuf var(32);\r
- GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);\r
- if (!var.empty())\r
- m_content_type = var;\r
- }\r
- return m_content_type;\r
- }\r
- string getRemoteAddr() const {\r
- m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
- if (m_remote_addr.empty()) {\r
- dynabuf var(16);\r
- GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);\r
- if (!var.empty())\r
- m_remote_addr = var;\r
- }\r
- return m_remote_addr;\r
- }\r
- void log(SPLogLevel level, const string& msg) {\r
- AbstractSPRequest::log(level,msg);\r
- if (level >= SPCrit)\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
- }\r
- string makeSafeHeader(const char* rawname) const {\r
- string hdr;\r
- for (; *rawname; ++rawname) {\r
- if (isalnum(*rawname))\r
- hdr += *rawname;\r
- }\r
- return (hdr + ':');\r
- }\r
- void clearHeader(const char* rawname, const char* cginame) {\r
- if (g_checkSpoofing && m_firsttime) {\r
- if (m_allhttp.empty())\r
- GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);\r
- string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');\r
- if (strstr(m_allhttp, hdr.c_str()))\r
- throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));\r
- }\r
- if (g_bSafeHeaderNames) {\r
- string hdr = makeSafeHeader(rawname);\r
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
- }\r
- else if (!strcmp(rawname,"REMOTE_USER")) {\r
- m_pn->SetHeader(m_pfc, "remote-user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
- m_pn->SetHeader(m_pfc, "remote_user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
- }\r
- else {\r
- string hdr = string(rawname) + ':';\r
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
- }\r
- }\r
- void setHeader(const char* name, const char* value) {\r
- string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));\r
- }\r
- string getSecureHeader(const char* name) const {\r
- string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
- dynabuf buf(256);\r
- GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
- return string(buf.empty() ? "" : buf);\r
- }\r
- string getHeader(const char* name) const {\r
- string hdr(name);\r
- hdr += ':';\r
- dynabuf buf(256);\r
- GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
- return string(buf.empty() ? "" : buf);\r
- }\r
- void setRemoteUser(const char* user) {\r
- setHeader("remote-user", user);\r
- if (!user || !*user)\r
- m_pfc->pFilterContext = NULL;\r
- else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))\r
- strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);\r
- }\r
- string getRemoteUser() const {\r
- return getSecureHeader("remote-user");\r
- }\r
- void setResponseHeader(const char* name, const char* value) {\r
- // Set for later.\r
- if (value)\r
- m_headers.insert(make_pair(name,value));\r
- else\r
- m_headers.erase(name);\r
- }\r
- long sendResponse(istream& in, long status) {\r
- string hdr = string("Connection: close\r\n");\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
- const char* codestr="200 OK";\r
- switch (status) {\r
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="401 Authorization Required"; break;\r
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="403 Forbidden"; break;\r
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;\r
- case XMLTOOLING_HTTP_STATUS_ERROR: codestr="500 Server Error"; break;\r
- }\r
- m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);\r
- char buf[1024];\r
- while (in) {\r
- in.read(buf,1024);\r
- DWORD resplen = in.gcount();\r
- m_pfc->WriteClient(m_pfc, buf, &resplen, 0);\r
- }\r
- return SF_STATUS_REQ_FINISHED;\r
- }\r
- long sendRedirect(const char* url) {\r
- // XXX: Don't support the httpRedirect option, yet.\r
- string hdr=string("Location: ") + url + "\r\n"\r
- "Content-Type: text/html\r\n"\r
- "Content-Length: 40\r\n"\r
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
- "Cache-Control: private,no-store,no-cache\r\n";\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
- m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);\r
- static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
- DWORD resplen=40;\r
- m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);\r
- return SF_STATUS_REQ_FINISHED;\r
- }\r
- long returnDecline() {\r
- return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
- }\r
- long returnOK() {\r
- return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
- }\r
-\r
- const vector<string>& getClientCertificates() const {\r
- return g_NoCerts;\r
- }\r
-\r
- // The filter never processes the POST, so stub these methods.\r
- long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }\r
- const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }\r
-};\r
-\r
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)\r
-{\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);\r
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"\r
- "<H1>Shibboleth Filter Error</H1>";\r
- DWORD resplen=strlen(xmsg);\r
- pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);\r
- resplen=strlen(msg);\r
- pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);\r
- static const char* xmsg2="</BODY></HTML>";\r
- resplen=strlen(xmsg2);\r
- pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);\r
- return SF_STATUS_REQ_FINISHED;\r
-}\r
-\r
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)\r
-{\r
- // Is this a log notification?\r
- if (notificationType==SF_NOTIFY_LOG) {\r
- if (pfc->pFilterContext)\r
- ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);\r
- return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
- }\r
-\r
- PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;\r
- try\r
- {\r
- // Determine web site number. This can't really fail, I don't think.\r
- dynabuf buf(128);\r
- GetServerVariable(pfc,"INSTANCE_ID",buf,10);\r
-\r
- // Match site instance to host name, skip if no match.\r
- map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
- if (map_i==g_Sites.end())\r
- return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-\r
- ostringstream threadid;\r
- threadid << "[" << getpid() << "] isapi_shib" << '\0';\r
- xmltooling::NDC ndc(threadid.str().c_str());\r
-\r
- ShibTargetIsapiF stf(pfc, pn, map_i->second);\r
-\r
- // "false" because we don't override the Shib settings\r
- pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);\r
- if (!g_spoofKey.empty())\r
- pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast<char*>(g_spoofKey.c_str()));\r
- if (res.first) return res.second;\r
-\r
- // "false" because we don't override the Shib settings\r
- res = stf.getServiceProvider().doExport(stf);\r
- if (res.first) return res.second;\r
-\r
- res = stf.getServiceProvider().doAuthorization(stf);\r
- if (res.first) return res.second;\r
-\r
- return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
- }\r
- catch(bad_alloc) {\r
- return WriteClientError(pfc,"Out of Memory");\r
- }\r
- catch(long e) {\r
- if (e==ERROR_NO_DATA)\r
- return WriteClientError(pfc,"A required variable or header was empty.");\r
- else\r
- return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");\r
- }\r
- catch (exception& e) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
- return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");\r
- }\r
- catch(...) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw an unknown exception.");\r
- if (g_catchAll)\r
- return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");\r
- throw;\r
- }\r
-\r
- return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");\r
-}\r
-\r
-\r
-/****************************************************************************/\r
-// ISAPI Extension\r
-\r
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)\r
-{\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
- lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);\r
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";\r
- DWORD resplen=strlen(xmsg);\r
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);\r
- resplen=strlen(msg);\r
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);\r
- static const char* xmsg2="</BODY></HTML>";\r
- resplen=strlen(xmsg2);\r
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);\r
- return HSE_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-class ShibTargetIsapiE : public AbstractSPRequest\r
-{\r
- LPEXTENSION_CONTROL_BLOCK m_lpECB;\r
- multimap<string,string> m_headers;\r
- mutable vector<string> m_certs;\r
- mutable string m_body;\r
- mutable bool m_gotBody;\r
- int m_port;\r
- string m_scheme,m_hostname,m_uri;\r
- mutable string m_remote_addr,m_remote_user;\r
-\r
-public:\r
- ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)\r
- : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {\r
- dynabuf ssl(5);\r
- GetServerVariable(lpECB,"HTTPS",ssl,5);\r
- bool SSL=(ssl=="on" || ssl=="ON");\r
-\r
- // Scheme may come from site def or be derived from IIS.\r
- m_scheme=site.m_scheme;\r
- if (m_scheme.empty() || !g_bNormalizeRequest)\r
- m_scheme = SSL ? "https" : "http";\r
-\r
- // URL path always come from IIS.\r
- dynabuf url(256);\r
- GetServerVariable(lpECB,"URL",url,255);\r
-\r
- // Port may come from IIS or from site def.\r
- dynabuf port(11);\r
- if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))\r
- GetServerVariable(lpECB,"SERVER_PORT",port,10);\r
- else if (SSL) {\r
- strncpy(port,site.m_sslport.c_str(),10);\r
- static_cast<char*>(port)[10]=0;\r
- }\r
- else {\r
- strncpy(port,site.m_port.c_str(),10);\r
- static_cast<char*>(port)[10]=0;\r
- }\r
- m_port = atoi(port);\r
-\r
- dynabuf var(32);\r
- GetServerVariable(lpECB, "SERVER_NAME", var, 32);\r
-\r
- // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
- m_hostname=var;\r
- if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
- m_hostname=site.m_name;\r
-\r
- /*\r
- * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if\r
- * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",\r
- * which is the default. No perfect way to tell, but we can take a good guess by checking\r
- * whether the URL is a substring of the PATH_INFO:\r
- *\r
- * e.g. for /Shibboleth.sso/SAML/POST\r
- *\r
- * Bad mode (default):\r
- * URL: /Shibboleth.sso\r
- * PathInfo: /Shibboleth.sso/SAML/POST\r
- *\r
- * Good mode:\r
- * URL: /Shibboleth.sso\r
- * PathInfo: /SAML/POST\r
- */\r
-\r
- string uri;\r
-\r
- // Clearly we're only in bad mode if path info exists at all.\r
- if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {\r
- if (strstr(lpECB->lpszPathInfo,url))\r
- // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.\r
- uri = lpECB->lpszPathInfo;\r
- else {\r
- uri = url;\r
- uri += lpECB->lpszPathInfo;\r
- }\r
- }\r
- else {\r
- uri = url;\r
- }\r
-\r
- // For consistency with Apache, let's add the query string.\r
- if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {\r
- uri += '?';\r
- uri += lpECB->lpszQueryString;\r
- }\r
-\r
- setRequestURI(uri.c_str());\r
- }\r
- ~ShibTargetIsapiE() { }\r
-\r
- const char* getScheme() const {\r
- return m_scheme.c_str();\r
- }\r
- const char* getHostname() const {\r
- return m_hostname.c_str();\r
- }\r
- int getPort() const {\r
- return m_port;\r
- }\r
- const char* getMethod() const {\r
- return m_lpECB->lpszMethod;\r
- }\r
- string getContentType() const {\r
- return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";\r
- }\r
- long getContentLength() const {\r
- return m_lpECB->cbTotalBytes;\r
- }\r
- string getRemoteUser() const {\r
- if (m_remote_user.empty()) {\r
- dynabuf var(16);\r
- GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);\r
- if (!var.empty())\r
- m_remote_user = var;\r
- }\r
- return m_remote_user;\r
- }\r
- string getRemoteAddr() const {\r
- m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
- if (m_remote_addr.empty()) {\r
- dynabuf var(16);\r
- GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);\r
- if (!var.empty())\r
- m_remote_addr = var;\r
- }\r
- return m_remote_addr;\r
- }\r
- void log(SPLogLevel level, const string& msg) const {\r
- AbstractSPRequest::log(level,msg);\r
- if (level >= SPCrit)\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
- }\r
- string getHeader(const char* name) const {\r
- string hdr("HTTP_");\r
- for (; *name; ++name) {\r
- if (*name=='-')\r
- hdr += '_';\r
- else\r
- hdr += toupper(*name);\r
- }\r
- dynabuf buf(128);\r
- GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);\r
- return buf.empty() ? "" : buf;\r
- }\r
- void setResponseHeader(const char* name, const char* value) {\r
- // Set for later.\r
- if (value)\r
- m_headers.insert(make_pair(name,value));\r
- else\r
- m_headers.erase(name);\r
- }\r
- const char* getQueryString() const {\r
- return m_lpECB->lpszQueryString;\r
- }\r
- const char* getRequestBody() const {\r
- if (m_gotBody)\r
- return m_body.c_str();\r
- if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?\r
- throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");\r
- else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {\r
- m_gotBody=true;\r
- DWORD datalen=m_lpECB->cbTotalBytes;\r
- if (m_lpECB->cbAvailable > 0) {\r
- m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
- datalen-=m_lpECB->cbAvailable;\r
- }\r
- char buf[8192];\r
- while (datalen) {\r
- DWORD buflen=8192;\r
- BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);\r
- if (!ret)\r
- throw IOException("Error reading request body from browser.");\r
- else if (!buflen)\r
- throw IOException("Socket closed while reading request body from browser.");\r
- m_body.append(buf, buflen);\r
- datalen-=buflen;\r
- }\r
- }\r
- else if (m_lpECB->cbAvailable) {\r
- m_gotBody=true;\r
- m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
- }\r
- return m_body.c_str();\r
- }\r
- long sendResponse(istream& in, long status) {\r
- string hdr = string("Connection: close\r\n");\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
- const char* codestr="200 OK";\r
- switch (status) {\r
- case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="401 Authorization Required"; break;\r
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="403 Forbidden"; break;\r
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;\r
- case XMLTOOLING_HTTP_STATUS_ERROR: codestr="500 Server Error"; break;\r
- }\r
- m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());\r
- char buf[1024];\r
- while (in) {\r
- in.read(buf,1024);\r
- DWORD resplen = in.gcount();\r
- m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);\r
- }\r
- return HSE_STATUS_SUCCESS;\r
- }\r
- long sendRedirect(const char* url) {\r
- string hdr=string("Location: ") + url + "\r\n"\r
- "Content-Type: text/html\r\n"\r
- "Content-Length: 40\r\n"\r
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
- "Cache-Control: private,no-store,no-cache\r\n";\r
- for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
- hdr += i->first + ": " + i->second + "\r\n";\r
- hdr += "\r\n";\r
- m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());\r
- static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
- DWORD resplen=40;\r
- m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);\r
- return HSE_STATUS_SUCCESS;\r
- }\r
- // Decline happens in the POST processor if this isn't the shire url\r
- // Note that it can also happen with HTAccess, but we don't support that, yet.\r
- long returnDecline() {\r
- return WriteClientError(\r
- m_lpECB,\r
- "ISAPI extension can only be invoked to process Shibboleth protocol requests."\r
- "Make sure the mapped file extension doesn't match actual content."\r
- );\r
- }\r
- long returnOK() {\r
- return HSE_STATUS_SUCCESS;\r
- }\r
-\r
- const vector<string>& getClientCertificates() const {\r
- if (m_certs.empty()) {\r
- char CertificateBuf[8192];\r
- CERT_CONTEXT_EX ccex;\r
- ccex.cbAllocated = sizeof(CertificateBuf);\r
- ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;\r
- DWORD dwSize = sizeof(ccex);\r
-\r
- if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {\r
- if (ccex.CertContext.cbCertEncoded) {\r
- xsecsize_t outlen;\r
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);\r
- m_certs.push_back(reinterpret_cast<char*>(serialized));\r
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE\r
- XMLString::release(&serialized);\r
-#else\r
- XMLString::release((char**)&serialized);\r
-#endif\r
- }\r
- }\r
- }\r
- return m_certs;\r
- }\r
-\r
- // Not used in the extension.\r
- void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }\r
- void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }\r
- void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }\r
-};\r
-\r
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)\r
-{\r
- try {\r
- ostringstream threadid;\r
- threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';\r
- xmltooling::NDC ndc(threadid.str().c_str());\r
-\r
- // Determine web site number. This can't really fail, I don't think.\r
- dynabuf buf(128);\r
- GetServerVariable(lpECB,"INSTANCE_ID",buf,10);\r
-\r
- // Match site instance to host name, skip if no match.\r
- map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
- if (map_i==g_Sites.end())\r
- return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check <ISAPI> mappings in configuration).");\r
-\r
- ShibTargetIsapiE ste(lpECB, map_i->second);\r
- pair<bool,long> res = ste.getServiceProvider().doHandler(ste);\r
- if (res.first) return res.second;\r
-\r
- return WriteClientError(lpECB, "Shibboleth Extension failed to process request");\r
-\r
- }\r
- catch(bad_alloc) {\r
- return WriteClientError(lpECB,"Out of Memory");\r
- }\r
- catch(long e) {\r
- if (e==ERROR_NO_DATA)\r
- return WriteClientError(lpECB,"A required variable or header was empty.");\r
- else\r
- return WriteClientError(lpECB,"Server detected unexpected IIS error.");\r
- }\r
- catch (exception& e) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
- return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");\r
- }\r
- catch(...) {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw an unknown exception.");\r
- if (g_catchAll)\r
- return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");\r
- throw;\r
- }\r
-\r
- // If we get here we've got an error.\r
- return HSE_STATUS_ERROR;\r
-}\r
+++ /dev/null
-/*
- * Copyright 2001-2009 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 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
-
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-// 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 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)
- {
- auto_ptr_char n(e->getAttributeNS(NULL,name));
- auto_ptr_char s(e->getAttributeNS(NULL,scheme));
- auto_ptr_char p(e->getAttributeNS(NULL,port));
- auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
- if (n.get()) m_name=n.get();
- if (s.get()) m_scheme=s.get();
- if (p.get()) m_port=p.get();
- if (p2.get()) m_sslport=p2.get();
- e = XMLHelper::getFirstChildElement(e, Alias);
- while (e) {
- if (e->hasChildNodes()) {
- auto_ptr_char alias(e->getFirstChild()->getNodeValue());
- m_aliases.insert(alias.get());
- }
- e = XMLHelper::getNextSiblingElement(e, Alias);
- }
- }
- string m_scheme,m_port,m_sslport,m_name;
- set<string> m_aliases;
- };
-
- struct context_t {
- char* m_user;
- bool m_checked;
- };
-
- HINSTANCE g_hinstDLL;
- SPConfig* g_Config = NULL;
- map<string,site_t> g_Sites;
- bool g_bNormalizeRequest = true;
- string g_unsetHeaderValue;
- bool g_checkSpoofing = true;
- bool g_catchAll = false;
- vector<string> g_NoCerts;
-}
-
-BOOL LogEvent(
- LPCSTR lpUNCServerName,
- WORD wType,
- DWORD dwEventID,
- PSID lpUserSid,
- LPCSTR message)
-{
- LPCSTR messages[] = {message, NULL};
-
- HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
- BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
- return (DeregisterEventSource(hElog) && res);
-}
-
-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) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "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)
-{
- if (!pVer)
- return FALSE;
- else if (g_Config) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Reentrant filter initialization, ignoring...");
- return TRUE;
- }
-
- g_Config=&SPConfig::getConfig();
- g_Config->setFeatures(
- SPConfig::Listener |
- SPConfig::Caching |
- SPConfig::RequestMapping |
- SPConfig::InProcess |
- SPConfig::Logging |
- SPConfig::Handlers
- );
- if (!g_Config->init()) {
- g_Config=NULL;
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter startup failed during library initialization, check native log for help.");
- return FALSE;
- }
-
- try {
- if (!g_Config->instantiate(NULL, true))
- throw runtime_error("unknown error");
- }
- catch (exception& ex) {
- g_Config->term();
- g_Config=NULL;
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter startup failed to load configuration, check native log for details.");
- 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,const char*> unsetValue=props->getString("unsetHeaderValue");
- if (unsetValue.first)
- g_unsetHeaderValue = unsetValue.second;
- pair<bool,bool> flag=props->getBool("checkSpoofing");
- g_checkSpoofing = !flag.first || flag.second;
- flag=props->getBool("catchAll");
- g_catchAll = flag.first && flag.second;
-
- props = props->getPropertySet("ISAPI");
- if (props) {
- flag = props->getBool("normalizeRequest");
- g_bNormalizeRequest = !flag.first || flag.second;
- const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
- while (child) {
- auto_ptr_char id(child->getAttributeNS(NULL,id));
- if (id.get())
- g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
- child=XMLHelper::getNextSiblingElement(child,Site);
- }
- }
- }
-
- 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);
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
- return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
- if (g_Config)
- g_Config->term();
- g_Config = NULL;
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut 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=NULL; 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==NULL || s==NULL)
- return (buflen==NULL && s==NULL);
- else
- return strcmp(bufptr,s)==0;
-}
-
-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())
- throw ERROR_NO_DATA;
-}
-
-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())
- throw ERROR_NO_DATA;
-}
-
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
- LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!pn->GetHeader(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())
- throw ERROR_NO_DATA;
-}
-
-/****************************************************************************/
-// 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;
-
-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) {
-
- // URL path always come from IIS.
- dynabuf var(256);
- GetHeader(pn,pfc,"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(pfc,"SERVER_PORT",var,10);
- 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(pfc,"SERVER_NAME",var,32);
-
- // 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;
-
- if (!pfc->pFilterContext) {
- pfc->pFilterContext = pfc->AllocMem(pfc, sizeof(context_t), NULL);
- if (static_cast<context_t*>(pfc->pFilterContext)) {
- static_cast<context_t*>(pfc->pFilterContext)->m_user = NULL;
- static_cast<context_t*>(pfc->pFilterContext)->m_checked = false;
- }
- }
- }
- ~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, '?') : NULL);
- return uri ? (uri + 1) : NULL;
- }
- const char* getMethod() const {
- if (m_method.empty()) {
- dynabuf var(5);
- GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
- if (!var.empty())
- m_method = var;
- }
- return m_method.c_str();
- }
- string getContentType() const {
- if (m_content_type.empty()) {
- dynabuf var(32);
- GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
- if (!var.empty())
- m_content_type = var;
- }
- return m_content_type;
- }
- string getRemoteAddr() const {
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- void log(SPLogLevel level, const string& msg) {
- AbstractSPRequest::log(level,msg);
- if (level >= SPError)
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
- }
- void clearHeader(const char* rawname, const char* cginame) {
- if (g_checkSpoofing && m_pfc->pFilterContext && !static_cast<context_t*>(m_pfc->pFilterContext)->m_checked) {
- if (m_allhttp.empty())
- GetServerVariable(m_pfc,"ALL_HTTP",m_allhttp,4096);
- if (strstr(m_allhttp, cginame))
- throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
- }
- string hdr(!strcmp(rawname,"REMOTE_USER") ? "remote-user" : rawname);
- hdr += ':';
- 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(name);
- hdr += ':';
- m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
- }
- string getHeader(const char* name) const {
- string hdr(name);
- hdr += ':';
- dynabuf buf(256);
- GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
- return string(buf);
- }
- void setRemoteUser(const char* user) {
- setHeader("remote-user", user);
- if (m_pfc->pFilterContext) {
- if (!user || !*user)
- static_cast<context_t*>(m_pfc->pFilterContext)->m_user = NULL;
- else if (static_cast<context_t*>(m_pfc->pFilterContext)->m_user = (char*)m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
- strcpy(static_cast<context_t*>(m_pfc->pFilterContext)->m_user, user);
- }
- }
- string getRemoteUser() const {
- return getHeader("remote-user");
- }
- void setResponseHeader(const char* name, const char* value) {
- // Set for later.
- if (value)
- m_headers.insert(make_pair(name,value));
- else
- m_headers.erase(name);
- }
- 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_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, (DWORD)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) {
- // XXX: Don't support the httpRedirect option, yet.
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n";
- for (multimap<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, "302 Please Wait", (DWORD)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."); }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
- "<H1>Shibboleth Filter Error</H1>";
- DWORD resplen=strlen(xmsg);
- pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
- resplen=strlen(msg);
- pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
- static const char* xmsg2="</BODY></HTML>";
- resplen=strlen(xmsg2);
- pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
- return SF_STATUS_REQ_FINISHED;
-}
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
- // Is this a log notification?
- if (notificationType==SF_NOTIFY_LOG) {
- if (pfc->pFilterContext && static_cast<context_t*>(pfc->pFilterContext)->m_user)
- ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=static_cast<context_t*>(pfc->pFilterContext)->m_user;
- 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);
-
- // 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;
-
- ostringstream threadid;
- threadid << "[" << getpid() << "] isapi_shib" << '\0';
- xmltooling::NDC ndc(threadid.str().c_str());
-
- ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
- // "false" because we don't override the Shib settings
- pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
- if (pfc->pFilterContext)
- static_cast<context_t*>(pfc->pFilterContext)->m_checked = true;
- if (res.first) return res.second;
-
- // "false" because we don't override the Shib settings
- 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(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 (exception& e) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
- return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
- }
- catch(...) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw 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)
-{
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
- lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
- DWORD resplen=strlen(xmsg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
- resplen=strlen(msg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
- static const char* xmsg2="</BODY></HTML>";
- resplen=strlen(xmsg2);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)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) {
- dynabuf ssl(5);
- GetServerVariable(lpECB,"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(lpECB,"URL",url,255);
-
- // Port may come from IIS or from site def.
- dynabuf port(11);
- if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
- GetServerVariable(lpECB,"SERVER_PORT",port,10);
- else if (SSL) {
- strncpy(port,site.m_sslport.c_str(),10);
- static_cast<char*>(port)[10]=0;
- }
- else {
- strncpy(port,site.m_port.c_str(),10);
- static_cast<char*>(port)[10]=0;
- }
- m_port = atoi(port);
-
- dynabuf var(32);
- GetServerVariable(lpECB, "SERVER_NAME", var, 32);
-
- // 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 {
- uri = url;
- uri += lpECB->lpszPathInfo;
- }
- }
- else {
- 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 {
- if (m_remote_user.empty()) {
- dynabuf var(16);
- GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
- if (!var.empty())
- m_remote_user = var;
- }
- return m_remote_user;
- }
- string getRemoteAddr() const {
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- void log(SPLogLevel level, const string& msg) const {
- AbstractSPRequest::log(level,msg);
- if (level >= SPError)
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
- }
- string getHeader(const char* name) const {
- string hdr("HTTP_");
- for (; *name; ++name) {
- if (*name=='-')
- hdr += '_';
- else
- hdr += toupper(*name);
- }
- dynabuf buf(128);
- GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
- return buf.empty() ? "" : buf;
- }
- void setResponseHeader(const char* name, const char* value) {
- // Set for later.
- if (value)
- m_headers.insert(make_pair(name,value));
- else
- m_headers.erase(name);
- }
- 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)
- throw IOException("Error reading request body from browser.");
- 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";
- const char* codestr="200 OK";
- switch (status) {
- 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_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 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) {
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n";
- for (multimap<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, "302 Moved", 0, (LPDWORD)hdr.c_str());
- static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
- DWORD resplen=40;
- m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
- return HSE_STATUS_SUCCESS;
- }
- // Decline happens in the POST processor if this isn't the shire 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, NULL)) {
- if (ccex.CertContext.cbCertEncoded) {
- xsecsize_t outlen;
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
- m_certs.push_back(reinterpret_cast<char*>(serialized));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
- XMLString::release(&serialized);
-#else
- XMLString::release((char**)&serialized);
-#endif
- }
- }
- }
- 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"); }
-};
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
- try {
- ostringstream threadid;
- threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
- xmltooling::NDC ndc(threadid.str().c_str());
-
- // Determine web site number. This can't really fail, I don't think.
- dynabuf buf(128);
- GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
-
- // 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 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(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 (exception& e) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
- return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
- }
- catch(...) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw 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;
-}
+++ /dev/null
-/*
- * Copyright 2001-2009 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 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/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-// 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 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)
- {
- auto_ptr_char n(e->getAttributeNS(NULL,name));
- auto_ptr_char s(e->getAttributeNS(NULL,scheme));
- auto_ptr_char p(e->getAttributeNS(NULL,port));
- auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
- if (n.get()) m_name=n.get();
- if (s.get()) m_scheme=s.get();
- if (p.get()) m_port=p.get();
- if (p2.get()) m_sslport=p2.get();
- e = XMLHelper::getFirstChildElement(e, Alias);
- while (e) {
- if (e->hasChildNodes()) {
- auto_ptr_char alias(e->getFirstChild()->getNodeValue());
- 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 = NULL;
- 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;
-}
-
-BOOL LogEvent(
- LPCSTR lpUNCServerName,
- WORD wType,
- DWORD dwEventID,
- PSID lpUserSid,
- LPCSTR message)
-{
- LPCSTR messages[] = {message, NULL};
-
- HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
- BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
- return (DeregisterEventSource(hElog) && res);
-}
-
-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) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "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)
-{
- if (!pVer)
- return FALSE;
- else if (g_Config) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Reentrant filter initialization, ignoring...");
- return TRUE;
- }
-
- g_Config=&SPConfig::getConfig();
- g_Config->setFeatures(
- SPConfig::Listener |
- SPConfig::Caching |
- SPConfig::RequestMapping |
- SPConfig::InProcess |
- SPConfig::Logging |
- SPConfig::Handlers
- );
- if (!g_Config->init()) {
- g_Config=NULL;
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter startup failed during library initialization, check native log for help.");
- return FALSE;
- }
-
- try {
- if (!g_Config->instantiate(NULL, true))
- throw runtime_error("unknown error");
- }
- catch (exception& ex) {
- g_Config->term();
- g_Config=NULL;
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter startup failed to load configuration, check native log for details.");
- 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);
- ostringstream keystr;
- keystr << randkey << randkey2 << randkey3 << randkey4;
- g_spoofKey = keystr.str();
- }
- else {
- _set_invalid_parameter_handler(old);
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
- "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
- locker.assign(); // pops lock on SP config
- g_Config->term();
- g_Config=NULL;
- 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;
- const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
- while (child) {
- auto_ptr_char id(child->getAttributeNS(NULL,id));
- if (id.get())
- g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
- child=XMLHelper::getNextSiblingElement(child,Site);
- }
- }
- }
-
- 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);
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
- return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
- if (g_Config)
- g_Config->term();
- g_Config = NULL;
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut 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=NULL; 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==NULL || s==NULL)
- return (buflen==NULL && s==NULL);
- else
- return strcmp(bufptr,s)==0;
-}
-
-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())
- throw ERROR_NO_DATA;
-}
-
-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())
- throw ERROR_NO_DATA;
-}
-
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
- LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
- s.reserve(size);
- s.erase();
- size=s.size();
-
- while (!pn->GetHeader(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())
- throw ERROR_NO_DATA;
-}
-
-/****************************************************************************/
-// 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) {
-
- // URL path always come from IIS.
- dynabuf var(256);
- GetHeader(pn,pfc,"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(pfc,"SERVER_PORT",var,10);
- 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(pfc,"SERVER_NAME",var,32);
-
- // 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;
-
- if (!g_spoofKey.empty()) {
- GetHeader(pn, pfc, "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, '?') : NULL);
- return uri ? (uri + 1) : NULL;
- }
- const char* getMethod() const {
- if (m_method.empty()) {
- dynabuf var(5);
- GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
- if (!var.empty())
- m_method = var;
- }
- return m_method.c_str();
- }
- string getContentType() const {
- if (m_content_type.empty()) {
- dynabuf var(32);
- GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
- if (!var.empty())
- m_content_type = var;
- }
- return m_content_type;
- }
- string getRemoteAddr() const {
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- void log(SPLogLevel level, const string& msg) {
- AbstractSPRequest::log(level,msg);
- if (level >= SPCrit)
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
- }
- 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) {
- if (g_checkSpoofing && m_firsttime) {
- if (m_allhttp.empty())
- GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);
- 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_user:", 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(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
- return string(buf.empty() ? "" : buf);
- }
- string getHeader(const char* name) const {
- string hdr(name);
- hdr += ':';
- dynabuf buf(256);
- GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
- return string(buf.empty() ? "" : buf);
- }
- void setRemoteUser(const char* user) {
- setHeader("remote-user", user);
- if (!user || !*user)
- m_pfc->pFilterContext = NULL;
- else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
- strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
- }
- string getRemoteUser() const {
- return getSecureHeader("remote-user");
- }
- void setResponseHeader(const char* name, const char* value) {
- // Set for later.
- if (value)
- m_headers.insert(make_pair(name,value));
- else
- m_headers.erase(name);
- }
- 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_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, (DWORD)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) {
- // XXX: Don't support the httpRedirect option, yet.
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n";
- for (multimap<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, "302 Please Wait", (DWORD)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."); }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
- "<H1>Shibboleth Filter Error</H1>";
- DWORD resplen=strlen(xmsg);
- pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
- resplen=strlen(msg);
- pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
- static const char* xmsg2="</BODY></HTML>";
- resplen=strlen(xmsg2);
- pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
- return SF_STATUS_REQ_FINISHED;
-}
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
- // 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);
-
- // 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;
-
- ostringstream threadid;
- threadid << "[" << getpid() << "] isapi_shib" << '\0';
- xmltooling::NDC ndc(threadid.str().c_str());
-
- ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
- // "false" because we don't override the Shib settings
- 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;
-
- // "false" because we don't override the Shib settings
- 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(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 (exception& e) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
- return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
- }
- catch(...) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw 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)
-{
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
- lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
- DWORD resplen=strlen(xmsg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
- resplen=strlen(msg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
- static const char* xmsg2="</BODY></HTML>";
- resplen=strlen(xmsg2);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)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) {
- dynabuf ssl(5);
- GetServerVariable(lpECB,"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(lpECB,"URL",url,255);
-
- // Port may come from IIS or from site def.
- dynabuf port(11);
- if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
- GetServerVariable(lpECB,"SERVER_PORT",port,10);
- else if (SSL) {
- strncpy(port,site.m_sslport.c_str(),10);
- static_cast<char*>(port)[10]=0;
- }
- else {
- strncpy(port,site.m_port.c_str(),10);
- static_cast<char*>(port)[10]=0;
- }
- m_port = atoi(port);
-
- dynabuf var(32);
- GetServerVariable(lpECB, "SERVER_NAME", var, 32);
-
- // 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 {
- uri = url;
- uri += lpECB->lpszPathInfo;
- }
- }
- else {
- 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 {
- if (m_remote_user.empty()) {
- dynabuf var(16);
- GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
- if (!var.empty())
- m_remote_user = var;
- }
- return m_remote_user;
- }
- string getRemoteAddr() const {
- m_remote_addr = AbstractSPRequest::getRemoteAddr();
- if (m_remote_addr.empty()) {
- dynabuf var(16);
- GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
- if (!var.empty())
- m_remote_addr = var;
- }
- return m_remote_addr;
- }
- void log(SPLogLevel level, const string& msg) const {
- AbstractSPRequest::log(level,msg);
- if (level >= SPCrit)
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
- }
- string getHeader(const char* name) const {
- string hdr("HTTP_");
- for (; *name; ++name) {
- if (*name=='-')
- hdr += '_';
- else
- hdr += toupper(*name);
- }
- dynabuf buf(128);
- GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
- return buf.empty() ? "" : buf;
- }
- void setResponseHeader(const char* name, const char* value) {
- // Set for later.
- if (value)
- m_headers.insert(make_pair(name,value));
- else
- m_headers.erase(name);
- }
- 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)
- throw IOException("Error reading request body from browser.");
- 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";
- const char* codestr="200 OK";
- switch (status) {
- 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_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 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) {
- string hdr=string("Location: ") + url + "\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 40\r\n"
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n";
- for (multimap<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, "302 Moved", 0, (LPDWORD)hdr.c_str());
- static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
- DWORD resplen=40;
- m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
- return HSE_STATUS_SUCCESS;
- }
- // Decline happens in the POST processor if this isn't the shire 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, NULL)) {
- if (ccex.CertContext.cbCertEncoded) {
- xsecsize_t outlen;
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
- m_certs.push_back(reinterpret_cast<char*>(serialized));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
- XMLString::release(&serialized);
-#else
- XMLString::release((char**)&serialized);
-#endif
- }
- }
- }
- 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"); }
-};
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
- try {
- ostringstream threadid;
- threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
- xmltooling::NDC ndc(threadid.str().c_str());
-
- // Determine web site number. This can't really fail, I don't think.
- dynabuf buf(128);
- GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
-
- // 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 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(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 (exception& e) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
- return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
- }
- catch(...) {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw 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;
-}
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth ISAPI Filter / Extension\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "isapi_shib\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "isapi_shib.dll\0"
VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
# ltmain.sh - Provide generalized library-building support services.
# NOTE: Changing this file will not affect anything until you rerun configure.
#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
# Free Software Foundation, Inc.
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# function.
progpath="$0"
-# RH: define SED for historic ltconfig's generated by Libtool 1.3
-[ -z "$SED" ] && SED=sed
-
# The name of this program:
progname=`echo "$progpath" | $SED $basename`
modename="$progname"
PROGRAM=ltmain.sh
PACKAGE=libtool
-VERSION=1.5.6
-TIMESTAMP=" (1.1220.2.95 2004/04/11 05:50:42)"
-
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
# Check that we have a working $echo.
if test "X$1" = X--no-reexec; then
Xsed="${SED}"' -e 1s/^X//'
sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
# test EBCDIC or ASCII
-case `echo A|tr A '\301'` in
- A) # EBCDIC based system
- SP2NL="tr '\100' '\n'"
- NL2SP="tr '\r\n' '\100\100'"
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ SP2NL='tr \040 \012'
+ NL2SP='tr \015\012 \040\040'
;;
- *) # Assume ASCII based system
- SP2NL="tr '\040' '\012'"
- NL2SP="tr '\015\012' '\040\040'"
+ *) # EBCDIC based system
+ SP2NL='tr \100 \n'
+ NL2SP='tr \r\n \100\100'
;;
esac
# These must not be set unconditionally because not all systems understand
# e.g. LANG=C (notably SCO).
# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
- save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
- save_LANG="$LANG"; LANG=C; export LANG
-fi
+for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test \"\${$lt_var+set}\" = set; then
+ save_$lt_var=\$$lt_var
+ $lt_var=C
+ export $lt_var
+ fi"
+done
# Make sure IFS has a sensible default
-: ${IFS="
-"}
+lt_nl='
+'
+IFS=" $lt_nl"
if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
$echo "$modename: not configured to build any kind of library" 1>&2
show="$echo"
show_help=
execute_dlfiles=
+duplicate_deps=no
+preserve_args=
lo2o="s/\\.lo\$/.${objext}/"
o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
#####################################
# Shell function definitions:
# This seems to be the best place for them
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $mkdir "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || {
+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+ exit $EXIT_FAILURE
+ }
+ fi
+
+ $echo "X$my_tmpdir" | $Xsed
+}
+
+
# func_win32_libid arg
# return the library type of file 'arg'
#
# Need a lot of goo to handle *both* DLLs and import libs
# Has to be a shell function in order to 'eat' the argument
# that is supplied when $file_magic_command is called.
-func_win32_libid () {
+func_win32_libid ()
+{
win32_libid_type="unknown"
win32_fileres=`file -L $1 2>/dev/null`
case $win32_fileres in
if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
$EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
win32_nmres=`eval $NM -f posix -A $1 | \
- sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
- if test "X$win32_nmres" = "Ximport" ; then
- win32_libid_type="x86 archive import"
- else
- win32_libid_type="x86 archive static"
- fi
+ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
fi
;;
*DLL*)
# Only attempt this if the compiler in the base compile
# command doesn't match the default compiler.
# arg is usually of the form 'gcc ...'
-func_infer_tag () {
+func_infer_tag ()
+{
if test -n "$available_tags" && test -z "$tagname"; then
CC_quoted=
for arg in $CC; do
esac
fi
}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ extracted_serial=`expr $extracted_serial + 1`
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir="$my_gentop/$my_xlib_u"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $exit_status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
# End of Shell function definitions
#####################################
# Darwin sucks
eval std_shrext=\"$shrext_cmds\"
+disable_libs=no
+
# Parse our command line options once, thoroughly.
while test "$#" -gt 0
do
--version)
$echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
$echo
- $echo "Copyright (C) 2003 Free Software Foundation, Inc."
+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
$echo "This is free software; see the source for copying conditions. There is NO"
$echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
- exit $EXIT_SUCCESS
+ exit $?
;;
--config)
for tagname in $taglist; do
${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
done
- exit $EXIT_SUCCESS
+ exit $?
;;
--debug)
else
$echo "disable static libraries"
fi
- exit $EXIT_SUCCESS
+ exit $?
;;
--finish) mode="finish" ;;
preserve_args="$preserve_args $arg"
;;
- --tag) prevopt="--tag" prev=tag ;;
+ --tag)
+ prevopt="--tag"
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
--tag=*)
set tag "$optarg" ${1+"$@"}
shift
exit $EXIT_FAILURE
fi
+case $disable_libs in
+no)
+ ;;
+shared)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+static)
+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+ ;;
+esac
+
# If this variable is set in any of the actions, the command in it
# will be execed at the end. This prevents here-documents from being
# left over by shells.
# Infer the operation mode.
if test -z "$mode"; then
$echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
- $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
case $nonopt in
*cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
mode=link
for arg
do
- case "$arg_mode" in
+ case $arg_mode in
arg )
# do not "continue". Instead, add this to base_compile
lastarg="$arg"
case $lastarg in
# Double-quote args containing other shell metacharacters.
# Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
lastarg="\"$lastarg\""
;;
*.f90) xform=f90 ;;
*.for) xform=for ;;
*.java) xform=java ;;
+ *.obj) xform=obj ;;
esac
libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
esac
done
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ test "X$libobj" != "X$qlibobj" \
+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
if test "X$xdir" = "X$obj"; then
$run $rm $removelist
exit $EXIT_FAILURE
fi
- $echo $srcfile > "$lockfile"
+ $echo "$srcfile" > "$lockfile"
fi
if test -n "$fix_srcfile_path"; then
eval srcfile=\"$fix_srcfile_path\"
fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
$run $rm "$libobj" "${libobj}T"
fbsd_hideous_sh_bug=$base_compile
if test "$pic_mode" != no; then
- command="$base_compile $srcfile $pic_flag"
+ command="$base_compile $qsrcfile $pic_flag"
else
# Don't build PIC code
- command="$base_compile $srcfile"
+ command="$base_compile $qsrcfile"
fi
if test ! -d "${xdir}$objdir"; then
$show "$mkdir ${xdir}$objdir"
$run $mkdir ${xdir}$objdir
- status=$?
- if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
- exit $status
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $exit_status
fi
fi
if test "$build_old_libs" = yes; then
if test "$pic_mode" != yes; then
# Don't build PIC code
- command="$base_compile $srcfile"
+ command="$base_compile $qsrcfile"
else
- command="$base_compile $srcfile $pic_flag"
+ command="$base_compile $qsrcfile $pic_flag"
fi
if test "$compiler_c_o" = yes; then
command="$command -o $obj"
no_install=no
objs=
non_pic_objects=
+ notinst_path= # paths that contain not-installed libtool libraries
precious_files_regex=
prefer_static_libs=no
preload=no
for arg
do
case $arg in
- -all-static | -static)
- if test "X$arg" = "X-all-static"; then
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
$echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
fi
if test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
- else
+ prefer_static_libs=yes
+ ;;
+ -static)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
- fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
build_libtool_libs=no
build_old_libs=yes
- prefer_static_libs=yes
break
;;
esac
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
prev=
continue
;;
+ darwin_framework|darwin_framework_skip)
+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
*)
eval "$prev=\"\$arg\""
prev=
continue
;;
+ -framework|-arch|-isysroot)
+ case " $CC " in
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ prev=darwin_framework_skip ;;
+ *) compiler_flags="$compiler_flags $arg"
+ prev=darwin_framework ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
-inst-prefix-dir)
prev=inst_prefix
continue
absdir=`cd "$dir" && pwd`
if test -z "$absdir"; then
$echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
- exit $EXIT_FAILURE
+ absdir="$dir"
+ notinst_path="$notinst_path $dir"
fi
dir="$absdir"
;;
esac
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$dir:"*) ;;
*) dllsearchpath="$dllsearchpath:$dir";;
esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
;;
esac
continue
-l*)
if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
case $host in
- *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
# These systems don't actually have a C or math library (as such)
continue
;;
- *-*-mingw* | *-*-os2*)
+ *-*-os2*)
# These systems don't actually have a C library (as such)
test "X$arg" = "X-lc" && continue
;;
- *-*-openbsd* | *-*-freebsd*)
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
test "X$arg" = "X-lc" && continue
;;
# Rhapsody C and math libraries are in the System framework
deplibs="$deplibs -framework System"
continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
esac
elif test "X$arg" = "X-lc_r"; then
case $host in
- *-*-openbsd* | *-*-freebsd*)
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc_r directly, use -pthread flag.
continue
;;
continue
;;
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
- deplibs="$deplibs $arg"
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
continue
;;
continue
;;
- # gcc -m* arguments should be passed to the linker via $compiler_flags
- # in order to pass architecture information to the linker
- # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo
- # but this is not reliable with gcc because gcc may use -mfoo to
- # select a different linker, different libraries, etc, while
- # -Wl,-mfoo simply passes -mfoo to the linker.
- -m*)
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -pg pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+ -t[45]*|-txscale*|@*)
+
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
esac
compile_command="$compile_command $arg"
finalize_command="$finalize_command $arg"
- if test "$with_gcc" = "yes" ; then
- compiler_flags="$compiler_flags $arg"
- fi
+ compiler_flags="$compiler_flags $arg"
continue
;;
continue
;;
- -static)
+ -static | -static-libtool-libs)
# The effects of -static are defined in a previous loop.
# We used to do the same as -all-static on platforms that
# didn't have a PIC flag, but the assumption that the effects
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if test ! -d "$output_objdir"; then
$show "$mkdir $output_objdir"
$run $mkdir $output_objdir
- status=$?
- if test "$status" -ne 0 && test ! -d "$output_objdir"; then
- exit $status
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $exit_status
fi
fi
newlib_search_path=
need_relink=no # whether we're linking any uninstalled libtool libraries
notinst_deplibs= # not-installed libtool libraries
- notinst_path= # paths that contain not-installed libtool libraries
case $linkmode in
lib)
passes="conv link"
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
- deplibs="$deplib $deplibs"
+ compiler_flags="$compiler_flags $deplib"
fi
continue
;;
$echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
continue
fi
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
for search_ext in .la $std_shrext .so .a; do
fi
case $linkmode in
lib)
- if test "$deplibs_check_method" != pass_all; then
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
$echo
$echo "*** Warning: Trying to link with static lib archive $deplib."
$echo "*** I have the capability to make that library automatically link in when"
esac # case $deplib
if test "$found" = yes || test -f "$lib"; then :
else
- $echo "$modename: cannot find the library \`$lib'" 1>&2
+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
exit $EXIT_FAILURE
fi
# it will not redefine variables installed, or shouldnotlink
installed=yes
shouldnotlink=no
+ avoidtemprpath=
+
# Read the .la file
case $lib in
dir="$libdir"
absdir="$libdir"
fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
else
- dir="$ladir/$objdir"
- absdir="$abs_ladir/$objdir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
fi # $installed = yes
name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
if test "$linkmode,$pass" = "prog,link"; then
if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ { { test "$prefer_static_libs" = no ||
+ test "$prefer_static_libs,$installed" = "built,yes"; } ||
+ test -z "$old_library"; }; then
# We need to hardcode the library path
- if test -n "$shlibpath_var"; then
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
# Make sure the rpath contains only unique directories.
case "$temp_rpath " in
*" $dir "*) ;;
*" $absdir "*) ;;
- *) temp_rpath="$temp_rpath $dir" ;;
+ *) temp_rpath="$temp_rpath $absdir" ;;
esac
fi
fi
link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes ; then
+ use_static_libs=no
+ fi
if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
if test "$installed" = no; then
notinst_deplibs="$notinst_deplibs $lib"
need_relink=yes
if test "$hardcode_direct" = no; then
add="$dir/$linklib"
case $host in
- *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
*-*-darwin* )
# if the lib is a module then we can not link against
# it, someone is ignoring the new warnings I added
- if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then
+ if /usr/bin/file -L $add 2> /dev/null |
+ $EGREP ": [^:]* bundle" >/dev/null ; then
$echo "** Warning, lib $linklib is a module, not a shared library"
if test -z "$old_library" ; then
$echo
add_dir="-L$dir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
- case "$libdir" in
+ case $libdir in
[\\/]*)
add_dir="$add_dir -L$inst_prefix_dir$libdir"
;;
add_dir="-L$libdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
- case "$libdir" in
+ case $libdir in
[\\/]*)
add_dir="$add_dir -L$inst_prefix_dir$libdir"
;;
fi
fi
else
- convenience="$convenience $dir/$old_library"
- old_convenience="$old_convenience $dir/$old_library"
deplibs="$dir/$old_library $deplibs"
link_static=yes
fi
*) continue ;;
esac
case " $deplibs " in
- *" $depdepl "*) ;;
- *) deplibs="$depdepl $deplibs" ;;
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
esac
case " $deplibs " in
- *" $path "*) ;;
- *) deplibs="$deplibs $path" ;;
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
esac
done
fi # link_all_deplibs != no
# which has an extra 1 added just for fun
#
case $version_type in
- darwin|linux|osf|windows)
+ darwin|linux|osf|windows|none)
current=`expr $number_major + $number_minor`
age="$number_minor"
revision="$number_revision"
# Check that each of the things are valid numbers.
case $current in
- [0-9]*) ;;
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
- $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
esac
case $revision in
- [0-9]*) ;;
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
- $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
esac
case $age in
- [0-9]*) ;;
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
- $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
versuffix="$major.$age.$revision"
# Darwin ld doesn't like 0 for these options...
minor_current=`expr $current + 1`
- verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
;;
freebsd-aout)
fi
# Eliminate all temporary directories.
- for path in $notinst_path; do
- lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
- deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
- dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
- done
+# for path in $notinst_path; do
+# lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+# deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+# dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+# done
if test -n "$xrpath"; then
# If the user specified any rpath flags, then add them.
*-*-netbsd*)
# Don't link with libc until the a.out ld.so is fixed.
;;
- *-*-openbsd* | *-*-freebsd*)
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
;;
*)
# Add libc to deplibs on all other systems if necessary.
int main() { return 0; }
EOF
$rm conftest
- $LTCC -o conftest conftest.c $deplibs
- if test "$?" -eq 0 ; then
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
ldd_output=`ldd conftest`
for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
+ name=`expr $i : '-l\(.*\)'`
# If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" -ne "0"; then
+ if test "$name" != "" && test "$name" != "0"; then
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $i "*)
# Error occurred in the first compile. Let's try to salvage
# the situation: Compile a separate program for each library.
for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
+ name=`expr $i : '-l\(.*\)'`
# If $name is empty we are operating on a -L argument.
if test "$name" != "" && test "$name" != "0"; then
$rm conftest
- $LTCC -o conftest conftest.c $i
- # Did it work?
- if test "$?" -eq 0 ; then
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
ldd_output=`ldd conftest`
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
droppeddeps=yes
$echo
$echo "*** Warning! Library $i is needed by this library but I was not able to"
- $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** make it link in! You will probably need to install it or some"
$echo "*** library that it depends on before this library will be fully"
$echo "*** functional. Installing it before continuing would be even better."
fi
set dummy $deplibs_check_method
file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
for a_deplib in $deplibs; do
- name="`expr $a_deplib : '-l\(.*\)'`"
+ name=`expr $a_deplib : '-l\(.*\)'`
# If $name is empty we are operating on a -L argument.
if test "$name" != "" && test "$name" != "0"; then
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
set dummy $deplibs_check_method
match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
for a_deplib in $deplibs; do
- name="`expr $a_deplib : '-l\(.*\)'`"
+ name=`expr $a_deplib : '-l\(.*\)'`
# If $name is empty we are operating on a -L argument.
if test -n "$name" && test "$name" != "0"; then
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
deplibs=$newdeplibs
fi
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+
# All the library-specific variables (install_libdir is set above).
library_names=
old_library=
fi
lib="$output_objdir/$realname"
+ linknames=
for link
do
linknames="$linknames $link"
# The command line is too long to execute in one step.
$show "using reloadable object file for export list..."
skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
fi
done
IFS="$save_ifs"
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
else
gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
generated="$generated $gentop"
- for xlib in $convenience; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
fi
fi
-
+
if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
linker_flags="$linker_flags $flag"
fi
fi
- if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+ if test "X$skipped_export" != "X:" &&
+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
:
else
save_libobjs=$libobjs
fi
save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
# Clear the reloadable object creation command queue and
# initialize k to one.
delfiles=
last_robj=
k=1
- output=$output_objdir/$save_output-${k}.$objext
+ output=$output_objdir/$output_la-${k}.$objext
# Loop over the list of objects to be linked.
for obj in $save_libobjs
do
eval test_cmds=\"$reload_cmds $objlist $last_robj\"
if test "X$objlist" = X ||
- { len=`expr "X$test_cmds" : ".*"` &&
+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
test "$len" -le "$max_cmd_len"; }; then
objlist="$objlist $obj"
else
# the last one created.
eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
fi
- last_robj=$output_objdir/$save_output-${k}.$objext
+ last_robj=$output_objdir/$output_la-${k}.$objext
k=`expr $k + 1`
- output=$output_objdir/$save_output-${k}.$objext
+ output=$output_objdir/$output_la-${k}.$objext
objlist=$obj
len=1
fi
eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
fi
- # Set up a command to remove the reloadale object files
+ # Set up a command to remove the reloadable object files
# after they are used.
i=0
while test "$i" -lt "$k"
do
i=`expr $i + 1`
- delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
done
$echo "creating a temporary reloadable object file: $output"
IFS="$save_ifs"
eval cmd=\"$cmd\"
$show "$cmd"
- $run eval "$cmd" || exit $?
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
done
IFS="$save_ifs"
# Restore the uninstalled library and exit
if test "$mode" = relink; then
$run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ fi
+ fi
+
exit $EXIT_SUCCESS
fi
reload_conv_objs=
gentop=
# reload_cmds runs $LD directly, so let us get rid of
- # -Wl from whole_archive_flag_spec
+ # -Wl from whole_archive_flag_spec and hope we can get by with
+ # turning comma into space..
wl=
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
- eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
else
gentop="$output_objdir/${obj}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
generated="$generated $gentop"
- for xlib in $convenience; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
fi
fi
;;
esac
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
compile_command="$compile_command $compile_deplibs"
finalize_command="$finalize_command $finalize_deplibs"
fi
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$libdir:"*) ;;
*) dllsearchpath="$dllsearchpath:$libdir";;
esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
;;
esac
done
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$output.exp"
+ export_symbols="$output_objdir/$outputname.exp"
$run $rm $export_symbols
- $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
else
- $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
- $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
$run eval 'mv "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
fi
fi
#endif
/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
const char *name;
lt_ptr address;
}
esac
# Now compile the dynamic symbol file.
- $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
- $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
# Clean up the generated files.
$show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
$run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
# Transform the symbol file into the correct name.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ case $host in
+ *cygwin* | *mingw* )
+ if test -f "$output_objdir/${outputname}.def" ; then
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ else
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ fi
+ ;;
+ * )
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ ;;
+ esac
;;
*)
$echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
# really was required.
# Nullify the symbol file.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
fi
if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
# Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
link_command="$compile_command$compile_rpath"
# We have no uninstalled library dependencies, so finalize right now.
$show "$link_command"
$run eval "$link_command"
- status=$?
+ exit_status=$?
# Delete the generated files.
if test -n "$dlsyms"; then
$run $rm "$output_objdir/${outputname}S.${objext}"
fi
- exit $status
+ exit $exit_status
fi
if test -n "$shlibpath_var"; then
if test "$fast_install" != no; then
link_command="$finalize_var$compile_command$finalize_rpath"
if test "$fast_install" = yes; then
- relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
else
# fast_install is set to needless
relink_command=
fi
done
relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
fi
# Quote $echo for shipping.
esac
case $host in
*cygwin* | *mingw* )
- cwrappersource=`$echo ${objdir}/lt-${output}.c`
- cwrapper=`$echo ${output}.exe`
- $rm $cwrappersource $cwrapper
- trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+ output_name=`basename $output`
+ output_path=`dirname $output`
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
cat > $cwrappersource <<EOF
#include <malloc.h>
#include <stdarg.h>
#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
#if defined(PATH_MAX)
# define LT_PATHMAX PATH_MAX
#endif
#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
#endif
#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
defined (__OS2__)
-#define HAVE_DOS_BASED_FILE_SYSTEM
-#ifndef DIR_SEPARATOR_2
-#define DIR_SEPARATOR_2 '\\'
-#endif
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
#endif
#ifndef DIR_SEPARATOR_2
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
#define XFREE(stale) do { \
if (stale) { free ((void *) stale); stale = 0; } \
} while (0)
+/* -DDEBUG is fairly common in CFLAGS. */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
const char *program_name = NULL;
void * xmalloc (size_t num);
char * xstrdup (const char *string);
-char * basename (const char *name);
-char * fnqualify(const char *path);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int check_executable(const char *path);
char * strendzap(char *str, const char *pat);
void lt_fatal (const char *message, ...);
char **newargz;
int i;
- program_name = (char *) xstrdup ((char *) basename (argv[0]));
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ DEBUG("(main) argv[0] : %s\n",argv[0]);
+ DEBUG("(main) program_name : %s\n",program_name);
newargz = XMALLOC(char *, argc+2);
EOF
- cat >> $cwrappersource <<EOF
- newargz[0] = "$SHELL";
+ cat >> $cwrappersource <<EOF
+ newargz[0] = (char *) xstrdup("$SHELL");
EOF
- cat >> $cwrappersource <<"EOF"
- newargz[1] = fnqualify(argv[0]);
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = find_executable(argv[0]);
+ if (newargz[1] == NULL)
+ lt_fatal("Couldn't find %s", argv[0]);
+ DEBUG("(main) found exe at : %s\n",newargz[1]);
/* we know the script has the same name, without the .exe */
/* so make sure newargz[1] doesn't end in .exe */
strendzap(newargz[1],".exe");
for (i = 1; i < argc; i++)
newargz[i+1] = xstrdup(argv[i]);
newargz[argc+1] = NULL;
+
+ for (i=0; i<argc+1; i++)
+ {
+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
+ ;
+ }
+
EOF
- cat >> $cwrappersource <<EOF
+ case $host_os in
+ mingw*)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",(char const **)newargz);
+EOF
+ ;;
+ *)
+ cat >> $cwrappersource <<EOF
execv("$SHELL",newargz);
EOF
+ ;;
+ esac
- cat >> $cwrappersource <<"EOF"
+ cat >> $cwrappersource <<"EOF"
+ return 127;
}
void *
;
}
-char *
-basename (const char *name)
+const char *
+base_name (const char *name)
{
const char *base;
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
/* Skip over the disk name in MSDOS pathnames. */
- if (isalpha (name[0]) && name[1] == ':')
+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
name += 2;
#endif
for (base = name; *name; name++)
if (IS_DIR_SEPARATOR (*name))
base = name + 1;
- return (char *) base;
+ return base;
+}
+
+int
+check_executable(const char * path)
+{
+ struct stat st;
+
+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0) &&
+ (
+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+ ((st.st_mode & S_IXUSR) == S_IXUSR))
+ )
+ return 1;
+ else
+ return 0;
}
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise */
char *
-fnqualify(const char *path)
+find_executable (const char* wrapper)
{
- size_t size;
- char *p;
+ int has_slash = 0;
+ const char* p;
+ const char* p_next;
+ /* static buffer for getcwd */
char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char* concat_name;
+
+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
- assert(path != NULL);
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
- /* Is it qualified already? */
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (isalpha (path[0]) && path[1] == ':')
- return xstrdup (path);
+ }
#endif
- if (IS_DIR_SEPARATOR (path[0]))
- return xstrdup (path);
- /* prepend the current directory */
- /* doesn't handle '~' */
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char* path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char* q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR(*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal ("getcwd failed");
- size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
- p = XMALLOC(char, size);
- sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
- return p;
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ return NULL;
}
char *
va_end (ap);
}
EOF
- # we should really use a build-platform specific compiler
- # here, but OTOH, the wrappers (shell script and this C one)
- # are only useful if you want to execute the "real" binary.
- # Since the "real" binary is built for $host, then this
- # wrapper might as well be built for $host, too.
- $run $LTCC -s -o $cwrapper $cwrappersource
- ;;
- esac
- $rm $output
- trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
$echo > $output "\
#! $SHELL
Xsed='${SED} -e 1s/^X//'
sed_quote_subst='$sed_quote_subst'
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
relink_command=\"$relink_command\"
# Backslashes separate directories on plain windows
*-*-mingw | *-*-os2*)
$echo >> $output "\
- exec \$progdir\\\\\$program \${1+\"\$@\"}
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
"
;;
*)
$echo >> $output "\
- exec \$progdir/\$program \${1+\"\$@\"}
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
"
;;
esac
$echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ \$echo \"\$0: cannot exec \$program \$*\"
exit $EXIT_FAILURE
fi
else
# The program doesn't exist.
- \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
\$echo \"This script is just a wrapper for \$program.\" 1>&2
$echo \"See the $PACKAGE documentation for more information.\" 1>&2
exit $EXIT_FAILURE
if test -n "$addlibs"; then
gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
generated="$generated $gentop"
- # Add in members from convenience archives.
- for xlib in $addlibs; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
- done
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
fi
# Do each command in the archive commands.
if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
cmds=$old_archive_from_new_cmds
else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+ exit $exit_status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
eval cmds=\"$old_archive_cmds\"
if len=`expr "X$cmds" : ".*"` &&
objlist=
concat_cmds=
save_oldobjs=$oldobjs
- # GNU ar 2.10+ was changed to match POSIX; thus no paths are
- # encoded into archives. This makes 'ar r' malfunction in
- # this piecewise linking case whenever conflicting object
- # names appear in distinct ar calls; check, warn and compensate.
- if (for obj in $save_oldobjs
- do
- $echo "X$obj" | $Xsed -e 's%^.*/%%'
- done | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
- $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
- AR_FLAGS=cq
- fi
+
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
oldobjs="$objlist $obj"
objlist="$objlist $obj"
eval test_cmds=\"$old_archive_cmds\"
- if len=`expr "X$test_cmds" : ".*"` &&
+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
test "$len" -le "$max_cmd_len"; then
:
else
done
# Quote the link command for shipping.
relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
if test "$hardcode_automatic" = yes ; then
relink_command=
fi
# install_prog (especially on Windows NT).
if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
# Allow the use of GNU shtool's install command.
- $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+ $echo "X$nonopt" | grep shtool > /dev/null; then
# Aesthetically quote it.
arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
arg="\"$arg\""
;;
esac
shift
else
install_prog=
- arg="$nonopt"
+ arg=$nonopt
fi
# The real first argument should be the name of the installation program.
# Aesthetically quote it.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
arg="\"$arg\""
;;
esac
do
if test -n "$dest"; then
files="$files $dest"
- dest="$arg"
+ dest=$arg
continue
fi
case $arg in
-d) isdir=yes ;;
- -f) prev="-f" ;;
- -g) prev="-g" ;;
- -m) prev="-m" ;;
- -o) prev="-o" ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o) prev=$arg ;;
-s)
stripme=" -s"
continue
;;
- -*) ;;
-
+ -*)
+ ;;
*)
# If the previous option needed an argument, then skip it.
if test -n "$prev"; then
prev=
else
- dest="$arg"
+ dest=$arg
continue
fi
;;
# Aesthetically quote the argument.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
arg="\"$arg\""
;;
esac
if test -n "$inst_prefix_dir"; then
# Stick the inst_prefix_dir data into the link command.
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
else
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
fi
$echo "$modename: warning: relinking \`$file'" 1>&2
if test "$#" -gt 0; then
# Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
for linkname
do
if test "$linkname" != "$realname"; then
- $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
fi
done
fi
IFS="$save_ifs"
eval cmd=\"$cmd\"
$show "$cmd"
- $run eval "$cmd" || exit $?
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
done
IFS="$save_ifs"
fi
notinst_deplibs=
relink_command=
- # To insure that "foo" is sourced, and not "foo.exe",
- # finese the cygwin/MSYS system by explicitly sourcing "foo."
- # which disallows the automatic-append-.exe behavior.
- case $build in
- *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
- *) wrapperdot=${wrapper} ;;
- esac
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
# If there is no directory component, then add one.
- case $file in
- */* | *\\*) . ${wrapperdot} ;;
- *) . ./${wrapperdot} ;;
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
esac
# Check the variables that should have been set.
done
relink_command=
- # To insure that "foo" is sourced, and not "foo.exe",
- # finese the cygwin/MSYS system by explicitly sourcing "foo."
- # which disallows the automatic-append-.exe behavior.
- case $build in
- *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
- *) wrapperdot=${wrapper} ;;
- esac
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
# If there is no directory component, then add one.
- case $file in
- */* | *\\*) . ${wrapperdot} ;;
- *) . ./${wrapperdot} ;;
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
esac
outputname=
if test "$fast_install" = no && test -n "$relink_command"; then
if test "$finalize" = yes && test -z "$run"; then
- tmpdir="/tmp"
- test -n "$TMPDIR" && tmpdir="$TMPDIR"
- tmpdir="$tmpdir/libtool-$$"
- save_umask=`umask`
- umask 0077
- if $mkdir "$tmpdir"; then
- umask $save_umask
- else
- umask $save_umask
- $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
- continue
- fi
+ tmpdir=`func_mktempdir`
file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
outputname="$tmpdir/$file"
# Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
$show "$relink_command"
if $run eval "$relink_command"; then :
fi
# remove .exe since cygwin /usr/bin/install will append another
- # one anyways
+ # one anyway
case $install_prog,$host in
*/usr/bin/install*,*cygwin*)
case $file:$destfile in
# Exit here if they wanted silent mode.
test "$show" = : && exit $EXIT_SUCCESS
- $echo "----------------------------------------------------------------------"
+ $echo "X----------------------------------------------------------------------" | $Xsed
$echo "Libraries have been installed in:"
for libdir in $libdirs; do
$echo " $libdir"
$echo
$echo "See any operating system documentation about shared libraries for"
$echo "more information, such as the ld(1) and ld.so(8) manual pages."
- $echo "----------------------------------------------------------------------"
+ $echo "X----------------------------------------------------------------------" | $Xsed
exit $EXIT_SUCCESS
;;
fi
# Restore saved environment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
- if test "${save_LANG+set}" = set; then
- LANG="$save_LANG"; export LANG
- fi
+ for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
# Now prepare to actually exec the command.
exec_cmd="\$cmd$args"
rmfiles="$rmfiles $objdir/$n"
done
test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
- test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
- if test "$mode" = uninstall; then
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
if test -n "$library_names"; then
# Do each command in the postuninstall commands.
cmds=$postuninstall_cmds
IFS="$save_ifs"
fi
# FIXME: should reinstall the best remaining shared library.
- fi
+ ;;
+ esac
fi
;;
-dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
-export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
+ try to export only the symbols listed in SYMFILE
-export-symbols-regex REGEX
- try to export only the symbols matching REGEX
+ try to export only the symbols matching REGEX
-LLIBDIR search LIBDIR for required installed libraries
-lNAME OUTPUT-FILE requires the installed library libNAME
-module build a library that can dlopened
-release RELEASE specify package release information
-rpath LIBDIR the created library will eventually be installed in LIBDIR
-R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -static do not do any dynamic linking of libtool libraries
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
-version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
+ specify library version info [each variable defaults to 0]
All other options (arguments beginning with \`-') are ignored.
$echo
$echo "Try \`$modename --help' for more information about other modes."
-exit $EXIT_SUCCESS
+exit $?
# The TAGs below are defined such that we never get into a situation
# in which we disable both kinds of libraries. Given conflicting
# configuration. But we'll never go from static-only to shared-only.
# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-build_libtool_libs=no
-build_old_libs=yes
+disable_libs=shared
# ### END LIBTOOL TAG CONFIG: disable-shared
# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+disable_libs=static
# ### END LIBTOOL TAG CONFIG: disable-static
# Local Variables:
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = memcache-store.la\r
-\r
-AM_CFLAGS = $(MEMCACHED_CFLAGS)\r
-AM_CXXFLAGS = $(MEMCACHED_CFLAGS)\r
-\r
-memcache_store_la_LIBADD = \\r
- $(MEMCACHED_LIBS)\r
-\r
-memcache_store_la_SOURCES = \\r
- memcache-store.cpp\r
-\r
-memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-\r
-install-exec-hook:\r
- for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = memcache-store.la
+
+AM_CFLAGS = $(MEMCACHED_CFLAGS)
+AM_CXXFLAGS = $(MEMCACHED_CFLAGS)
+
+memcache_store_la_LIBADD = \
+ $(MEMCACHED_LIBS)
+
+memcache_store_la_SOURCES = \
+ memcache-store.cpp
+
+memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+
+install-exec-hook:
+ for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
-/*\r
- * Copyright 2001-2008 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * memcache-store.cpp\r
- *\r
- * Storage Service using memcache (pre memcache tags)\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-# define MCEXT_EXPORTS __declspec(dllexport)\r
-#else\r
-# define MCEXT_EXPORTS\r
-#endif\r
-\r
-#include <xmltooling/base.h>\r
-\r
-#include <iostream> \r
-#include <libmemcached/memcached.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <xmltooling/logging.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/StorageService.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-namespace xmltooling {\r
- static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);\r
- static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);\r
- static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);\r
- \r
- class mc_record {\r
- public:\r
- string value;\r
- time_t expiration;\r
- mc_record(){};\r
- mc_record(string _v, time_t _e) :\r
- value(_v), expiration(_e)\r
- {}\r
- };\r
-\r
- class MemcacheBase {\r
- public:\r
- MemcacheBase(const DOMElement* e);\r
- ~MemcacheBase();\r
- \r
- bool addMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix = true);\r
- bool setMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix = true);\r
- bool replaceMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix = true);\r
- bool getMemcache(const char *key,\r
- string &dest,\r
- uint32_t *flags,\r
- bool use_prefix = true);\r
- bool deleteMemcache(const char *key,\r
- time_t timeout,\r
- bool use_prefix = true);\r
-\r
- void serialize(mc_record &source, string &dest);\r
- void serialize(list<string> &source, string &dest);\r
- void deserialize(string &source, mc_record &dest);\r
- void deserialize(string &source, list<string> &dest);\r
-\r
- bool addSessionToUser(string &key, string &user);\r
- bool addLock(string what, bool use_prefix = true);\r
- void deleteLock(string what, bool use_prefix = true);\r
-\r
- protected:\r
- const DOMElement* m_root; // can only use this during initialization\r
- Category& log;\r
- memcached_st *memc;\r
- string m_memcacheHosts;\r
- string m_prefix;\r
- Mutex* m_lock;\r
- };\r
- \r
- class MemcacheStorageService : public StorageService, public MemcacheBase {\r
-\r
- public:\r
- MemcacheStorageService(const DOMElement* e);\r
- ~MemcacheStorageService();\r
- \r
- bool createString(const char* context, const char* key, const char* value, time_t expiration);\r
- int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);\r
- int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0);\r
- bool deleteString(const char* context, const char* key);\r
- \r
- bool createText(const char* context, const char* key, const char* value, time_t expiration) {\r
- return createString(context, key, value, expiration);\r
- }\r
- int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) {\r
- return readString(context, key, pvalue, pexpiration, version);\r
- }\r
- int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) {\r
- return updateString(context, key, value, expiration, version);\r
- }\r
- bool deleteText(const char* context, const char* key) {\r
- return deleteString(context, key);\r
- }\r
- \r
- void reap(const char* context) {}\r
-\r
- void updateContext(const char* context, time_t expiration);\r
- void deleteContext(const char* context);\r
-\r
- private:\r
-\r
- Category& m_log;\r
- bool m_buildMap;\r
-\r
-\r
- };\r
-\r
- StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {\r
- return new MemcacheStorageService(e);\r
- }\r
-\r
-};\r
-\r
-bool MemcacheBase::addLock(string what, bool use_prefix) {\r
- string lock_name = what + ":LOCK";\r
- string set_val = "1";\r
- unsigned tries = 5;\r
- while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {\r
- if (tries-- == 0) {\r
- log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());\r
- return false;\r
- }\r
- log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());\r
- \r
- // sleep 100ms\r
-#ifdef WIN32\r
- Sleep(100);\r
-#else\r
- struct timeval tv = { 0, 100000 };\r
- select(0, 0, 0, 0, &tv);\r
-#endif\r
- }\r
- return true;\r
-}\r
-\r
-void MemcacheBase::deleteLock(string what, bool use_prefix) {\r
-\r
- string lock_name = what + ":LOCK";\r
- deleteMemcache(lock_name.c_str(), 0, use_prefix);\r
- return;\r
-\r
-} \r
-\r
-void MemcacheBase::deserialize(string &source, mc_record &dest) {\r
- istringstream is(source, stringstream::in | stringstream::out);\r
- is >> dest.expiration;\r
- is.ignore(1); // ignore delimiter\r
- dest.value = is.str().c_str() + is.tellg();\r
-}\r
-\r
-void MemcacheBase::deserialize(string &source, list<string> &dest) {\r
- istringstream is(source, stringstream::in | stringstream::out);\r
- while (!is.eof()) {\r
- string s;\r
- is >> s;\r
- dest.push_back(s);\r
- } \r
-}\r
-\r
-void MemcacheBase::serialize(mc_record &source, string &dest) {\r
- ostringstream os(stringstream::in | stringstream::out);\r
- os << source.expiration;\r
- os << "-"; // delimiter\r
- os << source.value;\r
- dest = os.str();\r
-}\r
-\r
-void MemcacheBase::serialize(list<string> &source, string &dest) { \r
- ostringstream os(stringstream::in | stringstream::out);\r
- for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {\r
- if (iter != source.begin()) {\r
- os << endl;\r
- }\r
- os << *iter;\r
- }\r
- dest = os.str();\r
-}\r
-\r
-bool MemcacheBase::addSessionToUser(string &key, string &user) {\r
-\r
- if (! addLock(user, false)) {\r
- return false;\r
- }\r
-\r
- // Aquired lock\r
-\r
- string sessid = m_prefix + key; // add specific prefix to session\r
- string delimiter = ";";\r
- string user_key = "UDATA:";\r
- user_key += user;\r
- string user_val;\r
- uint32_t flags;\r
- bool result = getMemcache(user_key.c_str(), user_val, &flags, false);\r
-\r
- if (result) {\r
- bool already_there = false;\r
- // skip delimiters at beginning.\r
- string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);\r
- \r
- // find first "non-delimiter".\r
- string::size_type pos = user_val.find_first_of(delimiter, lastPos);\r
- \r
- while (string::npos != pos || string::npos != lastPos) {\r
- // found a token, add it to the vector.\r
- string session = user_val.substr(lastPos, pos - lastPos);\r
- if (strcmp(session.c_str(), sessid.c_str()) == 0) {\r
- already_there = true;\r
- break;\r
- }\r
- \r
- // skip delimiters. Note the "not_of"\r
- lastPos = user_val.find_first_not_of(delimiter, pos);\r
- \r
- // find next "non-delimiter"\r
- pos = user_val.find_first_of(delimiter, lastPos);\r
- }\r
- \r
- if (!already_there) {\r
- user_val += delimiter + sessid;\r
- replaceMemcache(user_key.c_str(), user_val, 0, 0, false);\r
- }\r
- } else {\r
- addMemcache(user_key.c_str(), sessid, 0, 0, false);\r
- }\r
-\r
- deleteLock(user, false);\r
- return true;\r
- \r
-}\r
-\r
-bool MemcacheBase::deleteMemcache(const char *key,\r
- time_t timeout,\r
- bool use_prefix) {\r
- memcached_return rv;\r
- string final_key;\r
- bool success;\r
-\r
- if (use_prefix) {\r
- final_key = m_prefix + key;\r
- } else {\r
- final_key = key;\r
- }\r
-\r
- m_lock->lock();\r
- rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);\r
- m_lock->unlock();\r
-\r
- if (rv == MEMCACHED_SUCCESS) {\r
- success = true;\r
- } else if (rv == MEMCACHED_NOTFOUND) {\r
- // Key wasn't there... No biggie.\r
- success = false;\r
- } else if (rv == MEMCACHED_ERRNO) {\r
- // System error\r
- log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
- success = false;\r
- } else {\r
- log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv));\r
- // shouldn't be here\r
- success = false;\r
- }\r
-\r
- return success;\r
-}\r
-\r
-bool MemcacheBase::getMemcache(const char *key,\r
- string &dest,\r
- uint32_t *flags,\r
- bool use_prefix) {\r
- memcached_return rv;\r
- size_t len;\r
- char *result;\r
- string final_key;\r
- bool success;\r
- \r
- if (use_prefix) {\r
- final_key = m_prefix + key;\r
- } else {\r
- final_key = key;\r
- }\r
-\r
- m_lock->lock();\r
- result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
- m_lock->unlock();\r
-\r
- if (rv == MEMCACHED_SUCCESS) {\r
- dest = result;\r
- free(result);\r
- success = true;\r
- } else if (rv == MEMCACHED_NOTFOUND) {\r
- log.debug("Key %s not found in memcache...", key);\r
- success = false;\r
- } else if (rv == MEMCACHED_ERRNO) {\r
- // System error\r
- log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
- success = false;\r
- } else {\r
- log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv));\r
- success = false;\r
- }\r
-\r
- return success;\r
-}\r
-\r
-bool MemcacheBase::addMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix) {\r
-\r
- memcached_return rv;\r
- string final_key;\r
- bool success;\r
-\r
- if (use_prefix) {\r
- final_key = m_prefix + key;\r
- } else {\r
- final_key = key;\r
- }\r
-\r
- m_lock->lock();\r
- rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
- m_lock->unlock();\r
-\r
- if (rv == MEMCACHED_SUCCESS) {\r
- success = true;\r
- } else if (rv == MEMCACHED_NOTSTORED) {\r
- // already there\r
- success = false;\r
- } else if (rv == MEMCACHED_ERRNO) {\r
- // System error\r
- log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
- success = false;\r
- } else {\r
- // shouldn't be here\r
- log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv));\r
- success = false;\r
- }\r
-\r
- return success;\r
-}\r
-\r
-bool MemcacheBase::setMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix) {\r
-\r
- memcached_return rv;\r
- string final_key;\r
- bool success;\r
-\r
- if (use_prefix) {\r
- final_key = m_prefix + key;\r
- } else {\r
- final_key = key;\r
- }\r
-\r
- m_lock->lock();\r
- rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
- m_lock->unlock();\r
-\r
- if (rv == MEMCACHED_SUCCESS) {\r
- success = true;\r
- } else if (rv == MEMCACHED_ERRNO) {\r
- // System error\r
- log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
- success = false;\r
- } else {\r
- // shouldn't be here\r
- log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv));\r
- success = false;\r
- }\r
-\r
- return success;\r
-}\r
-\r
-bool MemcacheBase::replaceMemcache(const char *key,\r
- string &value,\r
- time_t timeout,\r
- uint32_t flags,\r
- bool use_prefix) {\r
- \r
- memcached_return rv;\r
- string final_key;\r
- bool success;\r
-\r
- if (use_prefix) {\r
- final_key = m_prefix + key;\r
- } else {\r
- final_key = key;\r
- }\r
-\r
- m_lock->lock();\r
- rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
- m_lock->unlock();\r
-\r
- if (rv == MEMCACHED_SUCCESS) {\r
- success = true;\r
- } else if (rv == MEMCACHED_NOTSTORED) {\r
- // not there\r
- success = false;\r
- } else if (rv == MEMCACHED_ERRNO) {\r
- // System error\r
- log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
- success = false;\r
- } else {\r
- // shouldn't be here\r
- log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv));\r
- success = false;\r
- }\r
-\r
- return success;\r
-}\r
-\r
-MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_memcacheHosts(""), m_prefix("") {\r
-\r
- auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);\r
- if (p.get() && *p.get()) {\r
- log.debug("INIT: GOT key prefix: %s", p.get());\r
- m_prefix = p.get();\r
- }\r
-\r
- // Grab hosts from the configuration.\r
- e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;\r
- if (!e || !e->hasChildNodes()) {\r
- throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");\r
- }\r
- auto_ptr_char h(e->getFirstChild()->getNodeValue());\r
- log.debug("INIT: GOT Hosts: %s", h.get());\r
- m_memcacheHosts = h.get();\r
-\r
- m_lock = Mutex::create();\r
- log.debug("Lock created");\r
-\r
- memc = memcached_create(NULL);\r
- if (memc == NULL) {\r
- throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");\r
- }\r
-\r
- log.debug("Memcache created");\r
-\r
- unsigned int hash = MEMCACHED_HASH_CRC;\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);\r
- log.debug("CRC hash set");\r
-\r
- int32_t timeout = 1000000;\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout);\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout);\r
-\r
- int32_t poll_timeout = 1000;\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);\r
-\r
- int32_t fail_limit = 5;\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);\r
-\r
- int32_t retry_timeout = 30;\r
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);\r
-\r
- memcached_server_st *servers;\r
- servers = memcached_servers_parse((char *)m_memcacheHosts.c_str());\r
- log.debug("Got %u hosts.", memcached_server_list_count(servers));\r
- if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {\r
- throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed"); \r
- }\r
- memcached_server_list_free(servers);\r
-\r
- log.debug("Memcache object initialized");\r
-}\r
-\r
-MemcacheBase::~MemcacheBase() {\r
- memcached_free(memc);\r
- delete m_lock;\r
- log.debug("Base object destroyed");\r
-}\r
-\r
-MemcacheStorageService::MemcacheStorageService(const DOMElement* e)\r
- : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {\r
-\r
- const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;\r
- if (tag && *tag && XMLString::parseInt(tag) != 0) {\r
- m_buildMap = true;\r
- m_log.debug("Cache built with buildMap ON");\r
- }\r
-\r
-}\r
-\r
-MemcacheStorageService::~MemcacheStorageService() {\r
-\r
- \r
-}\r
-\r
-bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {\r
-\r
- log.debug("createString ctx: %s - key: %s", context, key);\r
-\r
- string final_key = string(context) + ":" + string(key);\r
-\r
- mc_record rec(value, expiration);\r
- string final_value;\r
- serialize(rec, final_value);\r
-\r
- bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version\r
-\r
- if (result && m_buildMap) {\r
- log.debug("Got result, updating map");\r
-\r
- string map_name = context;\r
- // we need to update the context map\r
- if (! addLock(map_name)) {\r
- log.error("Unable to get lock for context %s!", context);\r
- deleteMemcache(final_key.c_str(), 0);\r
- return false;\r
- }\r
-\r
- string ser_arr;\r
- uint32_t flags;\r
- bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
- \r
- list<string> contents;\r
- if (result) {\r
- log.debug("Match found. Parsing...");\r
-\r
- deserialize(ser_arr, contents);\r
- \r
- log.debug("Iterating retrieved session map...");\r
- list<string>::iterator iter;\r
- for(iter = contents.begin(); \r
- iter != contents.end();\r
- iter++) {\r
- log.debug("value = " + *iter);\r
- }\r
-\r
- } else {\r
- log.debug("New context: %s", map_name.c_str());\r
-\r
- }\r
-\r
- contents.push_back(key);\r
- serialize(contents, ser_arr); \r
- setMemcache(map_name.c_str(), ser_arr, expiration, 0); \r
- \r
- deleteLock(map_name);\r
- }\r
-\r
- return result; \r
-\r
-}\r
-\r
-int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) {\r
-\r
- log.debug("readString ctx: %s - key: %s", context, key);\r
-\r
- string final_key = string(context) + ":" + string(key);\r
- uint32_t rec_version;\r
- string value;\r
-\r
- if (m_buildMap) {\r
- log.debug("Checking context");\r
-\r
- string map_name = context;\r
- string ser_arr;\r
- uint32_t flags;\r
- bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-\r
- if (!ctx_found) {\r
- return 0;\r
- }\r
- }\r
-\r
- bool found = getMemcache(final_key.c_str(), value, &rec_version);\r
- if (!found) {\r
- return 0;\r
- }\r
-\r
- if (version && rec_version <= (uint32_t)version) {\r
- return version;\r
- }\r
-\r
- if (pexpiration || pvalue) {\r
- mc_record rec;\r
- deserialize(value, rec);\r
- \r
- if (pexpiration) {\r
- *pexpiration = rec.expiration;\r
- }\r
- \r
- if (pvalue) {\r
- *pvalue = rec.value;\r
- }\r
- }\r
- \r
- return rec_version;\r
-\r
-}\r
-\r
-int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) {\r
-\r
- log.debug("updateString ctx: %s - key: %s", context, key);\r
-\r
- time_t final_exp = expiration;\r
- time_t *want_expiration = NULL;\r
- if (! final_exp) {\r
- want_expiration = &final_exp;\r
- }\r
-\r
- int read_res = readString(context, key, NULL, want_expiration, version);\r
-\r
- if (!read_res) {\r
- // not found\r
- return read_res;\r
- }\r
-\r
- if (version && version != read_res) {\r
- // version incorrect\r
- return -1;\r
- }\r
-\r
- // Proceding with update\r
- string final_key = string(context) + ":" + string(key);\r
- mc_record rec(value, final_exp);\r
- string final_value;\r
- serialize(rec, final_value);\r
-\r
- replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);\r
- return version;\r
-\r
-}\r
-\r
-bool MemcacheStorageService::deleteString(const char* context, const char* key) {\r
-\r
- log.debug("deleteString ctx: %s - key: %s", context, key);\r
- \r
- string final_key = string(context) + ":" + string(key);\r
-\r
- // Not updating context map, if there is one. There is no need.\r
-\r
- return deleteMemcache(final_key.c_str(), 0);\r
-\r
-}\r
-\r
-void MemcacheStorageService::updateContext(const char* context, time_t expiration) {\r
-\r
- log.debug("updateContext ctx: %s", context);\r
-\r
- if (!m_buildMap) {\r
- log.error("updateContext invoked on a Storage with no context map built!");\r
- return;\r
- }\r
-\r
- string map_name = context;\r
- string ser_arr;\r
- uint32_t flags;\r
- bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
- \r
- list<string> contents;\r
- if (result) {\r
- log.debug("Match found. Parsing...");\r
- \r
- deserialize(ser_arr, contents);\r
- \r
- log.debug("Iterating retrieved session map...");\r
- list<string>::iterator iter;\r
- for(iter = contents.begin(); \r
- iter != contents.end();\r
- iter++) {\r
-\r
- // Update expiration times\r
- string value; \r
- int read_res = readString(context, iter->c_str(), &value, NULL, 0);\r
- \r
- if (!read_res) {\r
- // not found\r
- continue;\r
- }\r
-\r
- updateString(context, iter->c_str(), value.c_str(), expiration, read_res);\r
- }\r
- replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);\r
- }\r
- \r
-}\r
-\r
-void MemcacheStorageService::deleteContext(const char* context) {\r
-\r
- log.debug("deleteContext ctx: %s", context);\r
-\r
- if (!m_buildMap) {\r
- log.error("deleteContext invoked on a Storage with no context map built!");\r
- return;\r
- }\r
-\r
- string map_name = context;\r
- string ser_arr;\r
- uint32_t flags;\r
- bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
- \r
- list<string> contents;\r
- if (result) {\r
- log.debug("Match found. Parsing...");\r
- \r
- deserialize(ser_arr, contents);\r
- \r
- log.debug("Iterating retrieved session map...");\r
- list<string>::iterator iter;\r
- for(iter = contents.begin(); \r
- iter != contents.end();\r
- iter++) {\r
- string final_key = map_name + *iter;\r
- deleteMemcache(final_key.c_str(), 0);\r
- }\r
- \r
- deleteMemcache(map_name.c_str(), 0);\r
- }\r
- \r
-}\r
-\r
-extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {\r
- // Register this SS type\r
- XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);\r
- return 0;\r
-}\r
-\r
-extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {\r
- XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * memcache-store.cpp
+ *
+ * Storage Service using memcache (pre memcache tags)
+ */
+
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+# define MCEXT_EXPORTS __declspec(dllexport)
+#else
+# define MCEXT_EXPORTS
+#endif
+
+#include <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 std;
+
+namespace xmltooling {
+ static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);
+ static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);
+ static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);
+ static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t);
+ static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t);
+ static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t);
+ static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t);
+ static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t);
+
+ class mc_record {
+ public:
+ string value;
+ time_t expiration;
+ mc_record(){};
+ mc_record(string _v, time_t _e) :
+ value(_v), expiration(_e)
+ {}
+ };
+
+ class MemcacheBase {
+ public:
+ MemcacheBase(const DOMElement* e);
+ ~MemcacheBase();
+
+ bool addMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix = true);
+ bool setMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix = true);
+ bool replaceMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix = true);
+ bool getMemcache(const char *key,
+ string &dest,
+ uint32_t *flags,
+ bool use_prefix = true);
+ bool deleteMemcache(const char *key,
+ time_t timeout,
+ bool use_prefix = true);
+
+ void serialize(mc_record &source, string &dest);
+ void serialize(list<string> &source, string &dest);
+ void deserialize(string &source, mc_record &dest);
+ void deserialize(string &source, list<string> &dest);
+
+ bool addSessionToUser(string &key, string &user);
+ bool addLock(string what, bool use_prefix = true);
+ void deleteLock(string what, bool use_prefix = true);
+
+ protected:
+ const DOMElement* m_root; // can only use this during initialization
+ Category& log;
+ memcached_st *memc;
+ string m_prefix;
+ Mutex* m_lock;
+ };
+
+ class MemcacheStorageService : public StorageService, public MemcacheBase {
+
+ public:
+ MemcacheStorageService(const DOMElement* e);
+ ~MemcacheStorageService();
+
+ bool createString(const char* context, const char* key, const char* value, time_t expiration);
+ int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);
+ int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0);
+ bool deleteString(const char* context, const char* key);
+
+ bool createText(const char* context, const char* key, const char* value, time_t expiration) {
+ return createString(context, key, value, expiration);
+ }
+ int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) {
+ return readString(context, key, pvalue, pexpiration, version);
+ }
+ int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) {
+ return updateString(context, key, value, expiration, version);
+ }
+ bool deleteText(const char* context, const char* key) {
+ return deleteString(context, key);
+ }
+
+ void reap(const char* context) {}
+
+ void updateContext(const char* context, time_t expiration);
+ void deleteContext(const char* context);
+
+ private:
+
+ Category& m_log;
+ bool m_buildMap;
+
+
+ };
+
+ StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {
+ return new MemcacheStorageService(e);
+ }
+
+};
+
+bool MemcacheBase::addLock(string what, bool use_prefix) {
+ string lock_name = what + ":LOCK";
+ string set_val = "1";
+ unsigned tries = 5;
+ while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {
+ if (tries-- == 0) {
+ log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
+ return false;
+ }
+ log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());
+
+ // sleep 100ms
+#ifdef WIN32
+ Sleep(100);
+#else
+ struct timeval tv = { 0, 100000 };
+ select(0, 0, 0, 0, &tv);
+#endif
+ }
+ return true;
+}
+
+void MemcacheBase::deleteLock(string what, bool use_prefix) {
+
+ string lock_name = what + ":LOCK";
+ deleteMemcache(lock_name.c_str(), 0, use_prefix);
+ return;
+
+}
+
+void MemcacheBase::deserialize(string &source, mc_record &dest) {
+ istringstream is(source, stringstream::in | stringstream::out);
+ is >> dest.expiration;
+ is.ignore(1); // ignore delimiter
+ dest.value = is.str().c_str() + is.tellg();
+}
+
+void MemcacheBase::deserialize(string &source, list<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::addSessionToUser(string &key, string &user) {
+
+ if (! addLock(user, false)) {
+ return false;
+ }
+
+ // Aquired lock
+
+ string sessid = m_prefix + key; // add specific prefix to session
+ string delimiter = ";";
+ string user_key = "UDATA:";
+ user_key += user;
+ string user_val;
+ uint32_t flags;
+ bool result = getMemcache(user_key.c_str(), user_val, &flags, false);
+
+ if (result) {
+ bool already_there = false;
+ // skip delimiters at beginning.
+ string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);
+
+ // find first "non-delimiter".
+ string::size_type pos = user_val.find_first_of(delimiter, lastPos);
+
+ while (string::npos != pos || string::npos != lastPos) {
+ // found a token, add it to the vector.
+ string session = user_val.substr(lastPos, pos - lastPos);
+ if (strcmp(session.c_str(), sessid.c_str()) == 0) {
+ already_there = true;
+ break;
+ }
+
+ // skip delimiters. Note the "not_of"
+ lastPos = user_val.find_first_not_of(delimiter, pos);
+
+ // find next "non-delimiter"
+ pos = user_val.find_first_of(delimiter, lastPos);
+ }
+
+ if (!already_there) {
+ user_val += delimiter + sessid;
+ replaceMemcache(user_key.c_str(), user_val, 0, 0, false);
+ }
+ } else {
+ addMemcache(user_key.c_str(), sessid, 0, 0, false);
+ }
+
+ deleteLock(user, false);
+ return true;
+
+}
+
+bool MemcacheBase::deleteMemcache(const char *key,
+ time_t timeout,
+ bool use_prefix) {
+ memcached_return rv;
+ string final_key;
+ bool success;
+
+ if (use_prefix) {
+ final_key = m_prefix + key;
+ } else {
+ final_key = key;
+ }
+
+ m_lock->lock();
+ rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);
+ m_lock->unlock();
+
+ if (rv == MEMCACHED_SUCCESS) {
+ success = true;
+ } else if (rv == MEMCACHED_NOTFOUND) {
+ // Key wasn't there... No biggie.
+ success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+ log.error(error);
+ throw IOException(error);
+ } else {
+ string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv);
+ log.error(error);
+ throw IOException(error);
+ }
+
+ return success;
+}
+
+bool MemcacheBase::getMemcache(const char *key,
+ string &dest,
+ uint32_t *flags,
+ bool use_prefix) {
+ memcached_return rv;
+ size_t len;
+ char *result;
+ string final_key;
+ bool success;
+
+ if (use_prefix) {
+ final_key = m_prefix + key;
+ } else {
+ final_key = key;
+ }
+
+ m_lock->lock();
+ result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);
+ m_lock->unlock();
+
+ if (rv == MEMCACHED_SUCCESS) {
+ dest = result;
+ free(result);
+ success = true;
+ } else if (rv == MEMCACHED_NOTFOUND) {
+ log.debug("Key %s not found in memcache...", key);
+ success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+ log.error(error);
+ throw IOException(error);
+ } else {
+ string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv);
+ log.error(error);
+ throw IOException(error);
+ }
+
+ return success;
+}
+
+bool MemcacheBase::addMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix) {
+
+ memcached_return rv;
+ string final_key;
+ bool success;
+
+ if (use_prefix) {
+ final_key = m_prefix + key;
+ } else {
+ final_key = key;
+ }
+
+ m_lock->lock();
+ rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
+
+ if (rv == MEMCACHED_SUCCESS) {
+ success = true;
+ } else if (rv == MEMCACHED_NOTSTORED) {
+ // already there
+ success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+ log.error(error);
+ throw IOException(error);
+ } else {
+ string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv);
+ log.error(error);
+ throw IOException(error);
+ }
+
+ return success;
+}
+
+bool MemcacheBase::setMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix) {
+
+ memcached_return rv;
+ string final_key;
+ bool success;
+
+ if (use_prefix) {
+ final_key = m_prefix + key;
+ } else {
+ final_key = key;
+ }
+
+ m_lock->lock();
+ rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
+
+ if (rv == MEMCACHED_SUCCESS) {
+ success = true;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+ log.error(error);
+ throw IOException(error);
+ } else {
+ string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv);
+ log.error(error);
+ throw IOException(error);
+ }
+
+ return success;
+}
+
+bool MemcacheBase::replaceMemcache(const char *key,
+ string &value,
+ time_t timeout,
+ uint32_t flags,
+ bool use_prefix) {
+
+ memcached_return rv;
+ string final_key;
+ bool success;
+
+ if (use_prefix) {
+ final_key = m_prefix + key;
+ } else {
+ final_key = key;
+ }
+
+ m_lock->lock();
+ rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
+
+ if (rv == MEMCACHED_SUCCESS) {
+ success = true;
+ } else if (rv == MEMCACHED_NOTSTORED) {
+ // not there
+ success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+ log.error(error);
+ throw IOException(error);
+ } else {
+ string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv);
+ log.error(error);
+ throw IOException(error);
+ }
+
+ return success;
+}
+
+MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") {
+
+ auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);
+ if (p.get() && *p.get()) {
+ log.debug("INIT: GOT key prefix: %s", p.get());
+ m_prefix = p.get();
+ }
+
+ m_lock = Mutex::create();
+ log.debug("Lock created");
+
+ memc = memcached_create(NULL);
+ if (memc == NULL) {
+ throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
+ }
+
+ log.debug("Memcache created");
+
+ unsigned int hash = MEMCACHED_HASH_CRC;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);
+ log.debug("CRC hash set");
+
+ int32_t send_timeout = 1000000;
+ const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+ if (tag && *tag) {
+ send_timeout = XMLString::parseInt(tag);
+ }
+ log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout);
+
+ int32_t recv_timeout = 1000000;
+ tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+ if (tag && *tag) {
+ recv_timeout = XMLString::parseInt(tag);
+ }
+ log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout);
+
+ int32_t poll_timeout = 1000;
+ tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL;
+ if (tag && *tag) {
+ poll_timeout = XMLString::parseInt(tag);
+ }
+ log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);
+
+ int32_t fail_limit = 5;
+ tag = e ? e->getAttributeNS(NULL, failLimit) : NULL;
+ if (tag && *tag) {
+ fail_limit = XMLString::parseInt(tag);
+ }
+ log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);
+
+ int32_t retry_timeout = 30;
+ tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL;
+ if (tag && *tag) {
+ retry_timeout = XMLString::parseInt(tag);
+ }
+ log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);
+
+ // Grab hosts from the configuration.
+ e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;
+ if (!e || !e->hasChildNodes()) {
+ throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");
+ }
+ auto_ptr_char h(e->getFirstChild()->getNodeValue());
+ log.debug("INIT: GOT Hosts: %s", h.get());
+ memcached_server_st *servers;
+ servers = memcached_servers_parse(const_cast<char*>(h.get()));
+ log.debug("Got %u hosts.", memcached_server_list_count(servers));
+ if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {
+ throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed");
+ }
+ memcached_server_list_free(servers);
+
+ log.debug("Memcache object initialized");
+}
+
+MemcacheBase::~MemcacheBase() {
+ memcached_free(memc);
+ delete m_lock;
+ log.debug("Base object destroyed");
+}
+
+MemcacheStorageService::MemcacheStorageService(const DOMElement* e)
+ : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {
+
+ const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;
+ if (tag && *tag && XMLString::parseInt(tag) != 0) {
+ m_buildMap = true;
+ m_log.debug("Cache built with buildMap ON");
+ }
+
+}
+
+MemcacheStorageService::~MemcacheStorageService() {
+
+
+}
+
+bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {
+
+ log.debug("createString ctx: %s - key: %s", context, key);
+
+ string final_key = string(context) + ":" + string(key);
+
+ mc_record rec(value, expiration);
+ string final_value;
+ serialize(rec, final_value);
+
+ bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version
+
+ if (result && m_buildMap) {
+ log.debug("Got result, updating map");
+
+ string map_name = context;
+ // we need to update the context map
+ if (! addLock(map_name)) {
+ log.error("Unable to get lock for context %s!", context);
+ deleteMemcache(final_key.c_str(), 0);
+ return false;
+ }
+
+ string ser_arr;
+ uint32_t flags;
+ bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+ list<string> contents;
+ if (result) {
+ log.debug("Match found. Parsing...");
+
+ deserialize(ser_arr, contents);
+
+ log.debug("Iterating retrieved session map...");
+ list<string>::iterator iter;
+ for(iter = contents.begin();
+ iter != contents.end();
+ iter++) {
+ log.debug("value = " + *iter);
+ }
+
+ } else {
+ log.debug("New context: %s", map_name.c_str());
+
+ }
+
+ contents.push_back(key);
+ serialize(contents, ser_arr);
+ setMemcache(map_name.c_str(), ser_arr, expiration, 0);
+
+ deleteLock(map_name);
+ }
+
+ return result;
+
+}
+
+int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) {
+
+ log.debug("readString ctx: %s - key: %s", context, key);
+
+ string final_key = string(context) + ":" + string(key);
+ uint32_t rec_version;
+ string value;
+
+ if (m_buildMap) {
+ log.debug("Checking context");
+
+ string map_name = context;
+ string ser_arr;
+ uint32_t flags;
+ bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+ if (!ctx_found) {
+ return 0;
+ }
+ }
+
+ bool found = getMemcache(final_key.c_str(), value, &rec_version);
+ if (!found) {
+ return 0;
+ }
+
+ if (version && rec_version <= (uint32_t)version) {
+ return version;
+ }
+
+ if (pexpiration || pvalue) {
+ mc_record rec;
+ deserialize(value, rec);
+
+ if (pexpiration) {
+ *pexpiration = rec.expiration;
+ }
+
+ if (pvalue) {
+ *pvalue = rec.value;
+ }
+ }
+
+ return rec_version;
+
+}
+
+int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) {
+
+ log.debug("updateString ctx: %s - key: %s", context, key);
+
+ time_t final_exp = expiration;
+ time_t *want_expiration = NULL;
+ if (! final_exp) {
+ want_expiration = &final_exp;
+ }
+
+ int read_res = readString(context, key, NULL, want_expiration, version);
+
+ if (!read_res) {
+ // not found
+ return read_res;
+ }
+
+ if (version && version != read_res) {
+ // version incorrect
+ return -1;
+ }
+
+ // Proceding with update
+ string final_key = string(context) + ":" + string(key);
+ mc_record rec(value, final_exp);
+ string final_value;
+ serialize(rec, final_value);
+
+ replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);
+ return version;
+
+}
+
+bool MemcacheStorageService::deleteString(const char* context, const char* key) {
+
+ log.debug("deleteString ctx: %s - key: %s", context, key);
+
+ string final_key = string(context) + ":" + string(key);
+
+ // Not updating context map, if there is one. There is no need.
+
+ return deleteMemcache(final_key.c_str(), 0);
+
+}
+
+void MemcacheStorageService::updateContext(const char* context, time_t expiration) {
+
+ log.debug("updateContext ctx: %s", context);
+
+ if (!m_buildMap) {
+ log.error("updateContext invoked on a Storage with no context map built!");
+ return;
+ }
+
+ string map_name = context;
+ string ser_arr;
+ uint32_t flags;
+ bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+ list<string> contents;
+ if (result) {
+ log.debug("Match found. Parsing...");
+
+ deserialize(ser_arr, contents);
+
+ log.debug("Iterating retrieved session map...");
+ list<string>::iterator iter;
+ for(iter = contents.begin();
+ iter != contents.end();
+ iter++) {
+
+ // Update expiration times
+ string value;
+ int read_res = readString(context, iter->c_str(), &value, NULL, 0);
+
+ if (!read_res) {
+ // not found
+ continue;
+ }
+
+ updateString(context, iter->c_str(), value.c_str(), expiration, read_res);
+ }
+ replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);
+ }
+
+}
+
+void MemcacheStorageService::deleteContext(const char* context) {
+
+ log.debug("deleteContext ctx: %s", context);
+
+ if (!m_buildMap) {
+ log.error("deleteContext invoked on a Storage with no context map built!");
+ return;
+ }
+
+ string map_name = context;
+ string ser_arr;
+ uint32_t flags;
+ bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+ list<string> contents;
+ if (result) {
+ log.debug("Match found. Parsing...");
+
+ deserialize(ser_arr, contents);
+
+ log.debug("Iterating retrieved session map...");
+ list<string>::iterator iter;
+ for(iter = contents.begin();
+ iter != contents.end();
+ iter++) {
+ string final_key = map_name + *iter;
+ deleteMemcache(final_key.c_str(), 0);
+ }
+
+ deleteMemcache(map_name.c_str(), 0);
+ }
+
+}
+
+extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {
+ // Register this SS type
+ XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);
+ return 0;
+}
+
+extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {
+ XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");
+}
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
BEGIN
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth Memcache Storage Service Plugin\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "memcache-store\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "OriginalFilename", "memcache-store.so\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
END
END
BLOCK "VarFileInfo"
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by memcache-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 101\r
-#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1001\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+//{{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
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
# 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 <sstream>
+#include <stdexcept>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
-#include <memory>
-#include <fstream>
-#include <sstream>
-#include <stdexcept>
-
#ifdef WIN32
# include <process.h>
# define XP_WIN32
setResponseHeader("Content-Type", type);
}
void setResponseHeader(const char* name, const char* value) {
+ HTTPResponse::setResponseHeader(name, value);
pblock_nvinsert(name, value, m_rq->srvhdrs);
}
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", "01-Jan-1997 12:00:00 GMT", m_rq->srvhdrs);
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth NSAPI Extension\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "nsapi_shib\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "nsapi_shib.dll\0"
VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* odbc-store.cpp
*
- * Storage Service using ODBC
+ * Storage Service using ODBC.
*/
#if defined (_MSC_VER) || defined(__BORLANDC__)
#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>
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
BEGIN
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth ODBC Storage Service Plugin\0"
- VALUE "FileVersion", "2, 2, 1, 0\0"
+ VALUE "FileVersion", "2, 3, 0, 0\0"
VALUE "InternalName", "odbc-store\0"
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"
VALUE "OriginalFilename", "odbc-store.so\0"
- VALUE "ProductName", "Shibboleth 2.2.1\0"
- VALUE "ProductVersion", "2, 2, 1, 0\0"
+ VALUE "ProductName", "Shibboleth 2.3\0"
+ VALUE "ProductVersion", "2, 3, 0, 0\0"
END
END
BLOCK "VarFileInfo"
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by odbc-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 101\r
-#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1001\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+//{{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
PKG=SHIBsp
-VERSION=2.2.1
+VERSION=2.3
BASEDIR=/
NAME=shibboleth-sp
CATEGORY=application,security
discoveryTemplate.html \
localLogout.html \
globalLogout.html \
+ partialLogout.html \
attribute-map.xml \
attribute-policy.xml \
example-metadata.xml \
-## $Id: Makefile.am 2566 2007-10-24 02:19:26Z cantor $
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $
AUTOMAKE_OPTIONS = foreign
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:afp="urn:mace:shibboleth:2.0:afp"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
- elementFormDefault="qualified">\r
-\r
- <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />\r
-\r
+ elementFormDefault="qualified">
+
+ <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />
+
<annotation>
<documentation>Schema for the attribute filter policies.</documentation>
</annotation>
Defines an attribute rule that may be reused across multiple filter policies.
</documentation>
</annotation>
- </element>\r
+ </element>
<element ref="afp:AttributeFilterPolicy" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
such as a federation site, should be signed.
</documentation>
</annotation>
- </element>\r
- </sequence>\r
+ </element>
+ </sequence>
</extension>
- </complexContent>\r
+ </complexContent>
</complexType>
<element name="AttributeFilterPolicy" type="afp:AttributeFilterPolicyType">
</sequence>
</extension>
</complexContent>
- </complexType>\r
-\r
+ </complexType>
+
<element name="AttributeRule" type="afp:AttributeRuleType">
<annotation>
<documentation>A rule that describes how values of an attribute will be filtered.</documentation>
</annotation>
- </element>\r
+ </element>
<complexType name="AttributeRuleType">
<complexContent>
<extension base="afp:IdentityType">
</annotation>
</attribute>
</extension>
- </complexContent>\r
+ </complexContent>
</complexType>
<element name="PolicyRequirementRule" type="afp:MatchFunctorType">
</attribute>
</complexType>
-</schema>
\ No newline at end of file
+</schema>
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:am="urn:mace:shibboleth:2.0:attribute-map"
elementFormDefault="qualified"
- version="2.2">
+ version="2.3">
<annotation>
<documentation>
<documentation>Flag controlling whether the resulting attribute should be exported for CGI use.</documentation>
</annotation>
</attribute>
+ <attribute name="hashAlg" type="am:string">
+ <annotation>
+ <documentation>
+ Crypto-provider-specific name of hash algorithm to use,
+ turning the decoded result into a simple string.
+ </documentation>
+ </annotation>
+ </attribute>
</complexType>
<complexType name="StringAttributeDecoder">
</complexContent>
</complexType>
-</schema>
\ No newline at end of file
+ <complexType name="KeyInfoAttributeDecoder">
+ <annotation>
+ <documentation>
+ Decoder for attributes with ds:KeyInfo values.
+ </documentation>
+ </annotation>
+ <complexContent>
+ <extension base="am:AttributeDecoderType">
+ <sequence>
+ <element name="KeyInfoResolver" type="am:PluggableType" minOccurs="0"/>
+ </sequence>
+ <attribute name="hash" type="boolean">
+ <annotation>
+ <documentation>
+ Flag controlling whether to hash keys before base64-encoding them.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="keyInfoHashAlg" type="am:string">
+ <annotation>
+ <documentation>
+ Crypto-provider-specific name of hash algorithm to use.
+ </documentation>
+ </annotation>
+ </attribute>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="XMLAttributeDecoder">
+ <annotation>
+ <documentation>
+ Decoder for directly serializing XML values.
+ </documentation>
+ </annotation>
+ <complexContent>
+ <extension base="am:AttributeDecoderType"/>
+ </complexContent>
+ </complexType>
+
+ <complexType name="DOMAttributeDecoder">
+ <annotation>
+ <documentation>
+ Decoder for extracting information from XML values.
+ </documentation>
+ </annotation>
+ <complexContent>
+ <extension base="am:AttributeDecoderType">
+ <sequence>
+ <element name="Mapping" minOccurs="0">
+ <annotation>
+ <documentation>Optional transform to turn qualified XML names into string names.</documentation>
+ </annotation>
+ <complexType>
+ <attribute name="from" type="QName" use="required"/>
+ <attribute name="to" type="am:string" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute name="formatter" type="am:string">
+ <annotation>
+ <documentation>
+ The pattern used to generate strings from the XML.
+ </documentation>
+ </annotation>
+ </attribute>
+ </extension>
+ </complexContent>
+ </complexType>
+
+</schema>
elementFormDefault="qualified"\r
attributeFormDefault="unqualified"\r
blockDefault="substitution"\r
- version="2.2">\r
+ version="2.3">\r
\r
<import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>\r
<import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>\r
\r
<complexType name="PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="type" type="conf:string" use="required"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</complexType>\r
\r
<element name="SPConfig">\r
<element name="RequestMapper" type="conf:PluggableType" minOccurs="0"/>\r
<element ref="conf:ApplicationDefaults"/>\r
<element ref="conf:SecurityPolicies"/>\r
- <element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>
+ <element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="logger" type="anyURI"/>\r
<attribute name="clockSkew" type="unsignedInt"/>\r
- <attribute name="unsafeChars" type="conf:string"/>
+ <attribute name="unsafeChars" type="conf:string"/>\r
+ <attribute name="allowedSchemes" type="conf:listOfStrings"/>\r
<anyAttribute namespace="##other" processContents="lax"/>\r
</complexType>\r
</element>\r
<element name="Library" minOccurs="0" maxOccurs="unbounded">\r
<complexType>\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="path" type="anyURI" use="required"/>\r
<attribute name="fatal" type="boolean"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</complexType>\r
</element>\r
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
<complexContent>\r
<restriction base="conf:PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="id" type="ID" use="required"/>\r
<attribute name="cleanupInterval" type="unsignedInt"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</restriction>\r
</complexContent>\r
</complexType>\r
<complexContent>\r
<restriction base="conf:PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="StorageService" type="IDREF"/>\r
<attribute name="cacheTimeout" type="unsignedInt"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</restriction>\r
</complexContent>\r
</complexType>\r
<attribute name="exportAssertion" type="boolean"/>\r
<attribute name="redirectToSSL" type="unsignedInt"/>\r
<attribute name="entityID" type="anyURI"/>\r
+ <attribute name="discoveryURL" type="anyURI"/>\r
<attribute name="isPassive" type="boolean"/>\r
<attribute name="forceAuthn" type="boolean"/>\r
<attribute name="authnContextClassRef" type="anyURI"/>\r
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
+ <attribute name="NameIDFormat" type="anyURI"/>\r
+ <attribute name="SPNameQualifier" type="conf:string"/>\r
<attribute name="redirectErrors" type="anyURI"/>\r
<attribute name="sessionError" type="anyURI"/>\r
<attribute name="metadataError" type="anyURI"/>\r
<complexContent>\r
<restriction base="conf:PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="Location" type="anyURI" use="required"/>\r
<attribute name="acl" type="conf:listOfStrings"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</restriction>\r
</complexContent>\r
</complexType>\r
<complexContent>\r
<restriction base="conf:PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="Location" type="anyURI"/>\r
<attribute name="id" type="conf:string"/>\r
<attribute name="template" type="anyURI"/>\r
<attribute name="postArtifact" type="boolean"/>\r
<attribute name="acsByIndex" type="boolean"/>\r
- <attribute name="defaultACSIndex" type="unsignedShort"/>\r
+ <attribute name="acsIndex" type="unsignedShort"/>\r
+ <attribute name="defaultACSIndex" type="unsignedShort"/> <!-- deprecated -->\r
<attribute name="isPassive" type="boolean"/>\r
<attribute name="forceAuthn" type="boolean"/>\r
<attribute name="authnContextClassRef" type="anyURI"/>\r
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
+ <attribute name="NameIDFormat" type="anyURI"/>\r
+ <attribute name="SPNameQualifier" type="conf:string"/>\r
<attribute name="requestDelegation" type="boolean"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</restriction>\r
</complexContent>\r
</complexType>\r
<complexContent>\r
<restriction base="conf:PluggableType">\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="Location" type="anyURI"/>\r
<attribute name="relayState" type="conf:string"/>\r
<attribute name="outgoingBindings" type="conf:listOfURIs"/>\r
<attribute name="template" type="anyURI"/>\r
<attribute name="postArtifact" type="boolean"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</restriction>\r
</complexContent>\r
</complexType>\r
</annotation>\r
<complexType>\r
<sequence>\r
- <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+ <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
</sequence>\r
<attribute name="redirectErrors" type="anyURI"/>\r
<attribute name="session" type="anyURI"/>\r
<attribute name="ssl" type="anyURI"/>\r
<attribute name="localLogout" type="anyURI"/>\r
<attribute name="globalLogout" type="anyURI"/>\r
+ <attribute name="partialLogout" type="anyURI"/>\r
<attribute name="supportContact" type="conf:string"/>\r
<attribute name="logoLocation" type="anyURI"/>\r
<attribute name="styleSheet" type="anyURI"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</complexType>\r
</element>\r
\r
</simpleType>\r
</attribute>\r
<attribute name="Location" type="anyURI" use="required"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</complexType>\r
</element>\r
\r
</choice>\r
<attribute name="id" type="conf:string" use="required"/>\r
<attribute name="validate" type="boolean"/>\r
- <anyAttribute namespace="##any" processContents="lax"/>\r
+ <anyAttribute namespace="##any" processContents="skip"/>\r
</complexType>\r
</element>\r
</sequence>\r
-## $Id: Makefile.am 2308 2007-06-12 04:56:15Z cantor $
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $
AUTOMAKE_OPTIONS = foreign
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
Name: shibboleth
-Version: 2.2.1
-Release: 1
+Version: 2.3
+Release: 2
Summary: Open source system for attribute-based Web SSO
Group: System Environment/Libraries
Vendor: Internet2
URL: http://shibboleth.internet2.edu/
Source: %{name}-sp-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
+PreReq: openssl
%if 0%{?suse_version} > 1030
+PreReq: %{insserv_prereq}
BuildRequires: libXerces-c-devel >= 2.8.0
BuildRequires: libxml-security-c-devel >= 1.4.0
-BuildRequires: libxmltooling-devel >= 1.2
-BuildRequires: libsaml-devel >= 2.2
+BuildRequires: libxmltooling-devel >= 1.3
+BuildRequires: libsaml-devel >= 2.3
%{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
%{!?_with_log4cpp:BuildRequires: liblog4shib-devel}
%else
BuildRequires: xerces%{?xercesver}-c-devel >= 2.8.0
BuildRequires: xml-security-c-devel >= 1.4.0
-BuildRequires: xmltooling-devel >= 1.2
-BuildRequires: opensaml-devel >= 2.2
+BuildRequires: xmltooling-devel >= 1.3
+BuildRequires: opensaml-devel >= 2.3
%{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
%{!?_with_log4cpp:BuildRequires: log4shib-devel}
%endif
%{?_with_fastcgi:BuildRequires: fcgi-devel}
%if "%{_vendor}" == "redhat"
%{!?_without_builtinapache:BuildRequires: httpd-devel}
+BuildRequires: redhat-rpm-config
%endif
%if "%{_vendor}" == "suse"
%{!?_without_builtinapache:BuildRequires: apache2-devel}
%if 0%{?suse_version} > 1030
Requires: libXerces-c-devel >= 2.8.0
Requires: libxml-security-c-devel >= 1.4.0
-Requires: libxmltooling-devel >= 1.2
-Requires: libsaml-devel >= 2.2
+Requires: libxmltooling-devel >= 1.3
+Requires: libsaml-devel >= 2.3
%{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
%{!?_with_log4cpp:Requires: liblog4shib-devel}
%else
Requires: xerces%{?xercesver}-c-devel >= 2.8.0
Requires: xml-security-c-devel >= 1.4.0
-Requires: xmltooling-devel >= 1.2
-Requires: opensaml-devel >= 2.2
+Requires: xmltooling-devel >= 1.3
+Requires: opensaml-devel >= 2.3
%{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
%{!?_with_log4cpp:Requires: log4shib-devel}
%endif
%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
# %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
- mkdir -p $RPM_BUILD_ROOT%{_initrddir}
- %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
- %{__chmod} 755 $RPM_BUILD_ROOT%{_initrddir}/shibd
+ install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
+ install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/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
%endif
%check
if [ "$1" -gt "1" ] ; then
/etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
%{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+ exit 0
fi
%endif
%if "%{_vendor}" == "suse"
# This adds the proper /etc/rc*.d links for the script
- /sbin/chkconfig --add shibd
- cd /usr/sbin && ln -s /etc/init.d/shibd rcshibd
- # On upgrade, restart components if they're already running.
- if [ "$1" -gt "1" ] ; then
- /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
- %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
- fi
+ cd /
+ %insserv_force_if_yast shibd
%endif
%preun
if [ "$1" = 0 ] ; then
/sbin/service shibd stop >/dev/null 2>&1
/sbin/chkconfig --del shibd
+ %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
fi
%endif
%if "%{_vendor}" == "suse"
+ %stop_on_removal shibd
if [ "$1" = 0 ] ; then
- /sbin/service shibd stop >/dev/null 2>&1
- /sbin/chkconfig --del shibd
- cd /usr/sbin && %{__rm} -f rcshibd
+ %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
fi
%endif
+exit 0
+%postun
%ifnos solaris2.8 solaris2.9 solaris2.10
-%postun -p /sbin/ldconfig
+/sbin/ldconfig
+%endif
+%if "%{_vendor}" == "suse"
+cd /
+%restart_on_update shibd
+%{!?_without_builtinapache:%restart_on_update apache2}
+%{insserv_cleanup}
%endif
%posttrans
%config(noreplace) %{_sysconfdir}/%{name}/*.html
%config(noreplace) %{_sysconfdir}/%{name}/*.logger
%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
-%attr(755, root, root) %{_initrddir}/shibd
+%config %{_initrddir}/shibd
+%endif
+%if "%{_vendor}" == "suse"
+%{_sbindir}/rcshibd
%endif
%{_sysconfdir}/%{name}/*.dist
%{_sysconfdir}/%{name}/apache*.config
%doc %{pkgdocdir}/api
%changelog
+* Wed Aug 19 2009 Scott Cantor <cantor.2@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@osu.edu> - 2.2.1-1
- Doc handling changes
- SuSE init script
Name: @PACKAGE@
Version: @PACKAGE_VERSION@
-Release: 1
+Release: 2
Summary: Open source system for attribute-based Web SSO
Group: System Environment/Libraries
Vendor: Internet2
URL: http://shibboleth.internet2.edu/
Source: %{name}-sp-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
+PreReq: openssl
%if 0%{?suse_version} > 1030
+PreReq: %{insserv_prereq}
BuildRequires: libXerces-c-devel >= 2.8.0
BuildRequires: libxml-security-c-devel >= 1.4.0
-BuildRequires: libxmltooling-devel >= 1.2
-BuildRequires: libsaml-devel >= 2.2
+BuildRequires: libxmltooling-devel >= 1.3
+BuildRequires: libsaml-devel >= 2.3
%{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
%{!?_with_log4cpp:BuildRequires: liblog4shib-devel}
%else
BuildRequires: xerces%{?xercesver}-c-devel >= 2.8.0
BuildRequires: xml-security-c-devel >= 1.4.0
-BuildRequires: xmltooling-devel >= 1.2
-BuildRequires: opensaml-devel >= 2.2
+BuildRequires: xmltooling-devel >= 1.3
+BuildRequires: opensaml-devel >= 2.3
%{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
%{!?_with_log4cpp:BuildRequires: log4shib-devel}
%endif
%{?_with_fastcgi:BuildRequires: fcgi-devel}
%if "%{_vendor}" == "redhat"
%{!?_without_builtinapache:BuildRequires: httpd-devel}
+BuildRequires: redhat-rpm-config
%endif
%if "%{_vendor}" == "suse"
%{!?_without_builtinapache:BuildRequires: apache2-devel}
%if 0%{?suse_version} > 1030
Requires: libXerces-c-devel >= 2.8.0
Requires: libxml-security-c-devel >= 1.4.0
-Requires: libxmltooling-devel >= 1.2
-Requires: libsaml-devel >= 2.2
+Requires: libxmltooling-devel >= 1.3
+Requires: libsaml-devel >= 2.3
%{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
%{!?_with_log4cpp:Requires: liblog4shib-devel}
%else
Requires: xerces%{?xercesver}-c-devel >= 2.8.0
Requires: xml-security-c-devel >= 1.4.0
-Requires: xmltooling-devel >= 1.2
-Requires: opensaml-devel >= 2.2
+Requires: xmltooling-devel >= 1.3
+Requires: opensaml-devel >= 2.3
%{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
%{!?_with_log4cpp:Requires: log4shib-devel}
%endif
%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
# %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
- mkdir -p $RPM_BUILD_ROOT%{_initrddir}
- %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
- %{__chmod} 755 $RPM_BUILD_ROOT%{_initrddir}/shibd
+ install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
+ install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/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
%endif
%check
if [ "$1" -gt "1" ] ; then
/etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
%{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+ exit 0
fi
%endif
%if "%{_vendor}" == "suse"
# This adds the proper /etc/rc*.d links for the script
- /sbin/chkconfig --add shibd
- cd /usr/sbin && ln -s /etc/init.d/shibd rcshibd
- # On upgrade, restart components if they're already running.
- if [ "$1" -gt "1" ] ; then
- /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
- %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
- fi
+ cd /
+ %insserv_force_if_yast shibd
%endif
%preun
if [ "$1" = 0 ] ; then
/sbin/service shibd stop >/dev/null 2>&1
/sbin/chkconfig --del shibd
+ %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
fi
%endif
%if "%{_vendor}" == "suse"
+ %stop_on_removal shibd
if [ "$1" = 0 ] ; then
- /sbin/service shibd stop >/dev/null 2>&1
- /sbin/chkconfig --del shibd
- cd /usr/sbin && %{__rm} -f rcshibd
+ %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
fi
%endif
+exit 0
+%postun
%ifnos solaris2.8 solaris2.9 solaris2.10
-%postun -p /sbin/ldconfig
+/sbin/ldconfig
+%endif
+%if "%{_vendor}" == "suse"
+cd /
+%restart_on_update shibd
+%{!?_without_builtinapache:%restart_on_update apache2}
+%{insserv_cleanup}
%endif
%posttrans
%config(noreplace) %{_sysconfdir}/%{name}/*.html
%config(noreplace) %{_sysconfdir}/%{name}/*.logger
%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
-%attr(755, root, root) %{_initrddir}/shibd
+%config %{_initrddir}/shibd
+%endif
+%if "%{_vendor}" == "suse"
+%{_sbindir}/rcshibd
%endif
%{_sysconfdir}/%{name}/*.dist
%{_sysconfdir}/%{name}/apache*.config
%doc %{pkgdocdir}/api
%changelog
+* Wed Aug 19 2009 Scott Cantor <cantor.2@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@osu.edu> - 2.2.1-1
- Doc handling changes
- SuSE init script
-## $Id: Makefile.am 2283 2007-06-01 17:35:42Z cantor $
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $
AUTOMAKE_OPTIONS = foreign
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
-/*\r
- * Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/*\r
- * shar.cpp -- the shibd "main" code. All the functionality is elsewhere\r
- *\r
- * Created By: Derek Atkins <derek@ihtfp.com>\r
- *\r
- * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $\r
- */\r
-\r
-\r
-// eventually we might be able to support autoconf via cygwin...\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/SPConfig.h>\r
-\r
-#ifdef HAVE_UNISTD_H\r
-#include <unistd.h>\r
-#include <sys/select.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <signal.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/remoting/ListenerService.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-bool shibd_shutdown = false;\r
-const char* shar_config = NULL;\r
-const char* shar_schemadir = NULL;\r
-const char* shar_prefix = NULL;\r
-bool shar_checkonly = false;\r
-bool shar_version = false;\r
-static bool unlink_socket = false;\r
-const char* pidfile = NULL;\r
-\r
-#ifdef WIN32\r
-\r
-//#include <CRTDBG.H>\r
-\r
-#define nNoMansLandSize 4\r
-typedef struct _CrtMemBlockHeader\r
-{\r
- struct _CrtMemBlockHeader * pBlockHeaderNext;\r
- struct _CrtMemBlockHeader * pBlockHeaderPrev;\r
- char * szFileName;\r
- int nLine;\r
- size_t nDataSize;\r
- int nBlockUse;\r
- long lRequest;\r
- unsigned char gap[nNoMansLandSize];\r
- /* followed by:\r
- * unsigned char data[nDataSize];\r
- * unsigned char anotherGap[nNoMansLandSize];\r
- */\r
-} _CrtMemBlockHeader;\r
-\r
-/*\r
-int MyAllocHook(int nAllocType, void *pvData,\r
- size_t nSize, int nBlockUse, long lRequest,\r
- const unsigned char * szFileName, int nLine)\r
-{\r
- if ( nBlockUse == _CRT_BLOCK )\r
- return( TRUE );\r
- if (nAllocType == _HOOK_FREE) {\r
- _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);\r
- if (ptr->nDataSize == 8192)\r
- fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);\r
- }\r
- else if (nAllocType == _HOOK_ALLOC && nSize == 8192)\r
- fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);\r
- return (TRUE);\r
-}\r
-*/\r
-\r
-int real_main(int preinit)\r
-{\r
- SPConfig& conf=SPConfig::getConfig();\r
- if (preinit) {\r
-\r
- // Initialize the SP library.\r
- conf.setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::Metadata |\r
- SPConfig::Trust |\r
- SPConfig::Credentials |\r
- SPConfig::AttributeResolution |\r
- SPConfig::Handlers |\r
- SPConfig::OutOfProcess |\r
- (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
- );\r
- if (!conf.init(shar_schemadir, shar_prefix)) {\r
- fprintf(stderr, "configuration is invalid, see console for specific problems\n");\r
- return -1;\r
- }\r
-\r
- if (!conf.instantiate(shar_config)) {\r
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
- conf.term();\r
- return -2;\r
- }\r
-\r
- // If just a test run, bail.\r
- if (shar_checkonly) {\r
- fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");\r
- return 0;\r
- }\r
- }\r
- else {\r
-\r
- //_CrtSetAllocHook(MyAllocHook);\r
-\r
- if (!shar_checkonly) {\r
- // Run the listener.\r
- ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
- if (!listener->init(unlink_socket)) {\r
- fprintf(stderr, "listener failed to initialize\n");\r
- conf.term();\r
- return -3;\r
- }\r
- else if (!listener->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failed during service\n");\r
- listener->term();\r
- conf.term();\r
- return -3;\r
- }\r
- listener->term();\r
- }\r
-\r
- conf.term();\r
- }\r
- return 0;\r
-}\r
-\r
-#else\r
-\r
-int daemon_wait = 3;\r
-bool shibd_running = false;\r
-bool daemonize = true;\r
-\r
-static void term_handler(int arg)\r
-{\r
- shibd_shutdown = true;\r
-}\r
-\r
-static void run_handler(int arg)\r
-{\r
- shibd_running = true;\r
-}\r
-\r
-static void child_handler(int arg)\r
-{\r
- // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
-}\r
-\r
-static int setup_signals(void)\r
-{\r
- struct sigaction sa;\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = SIG_IGN;\r
- sa.sa_flags = SA_RESTART;\r
-\r
- if (sigaction(SIGPIPE, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
-\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = term_handler;\r
- sa.sa_flags = SA_RESTART;\r
-\r
- if (sigaction(SIGHUP, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGINT, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGQUIT, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
-\r
- if (daemonize) {\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = run_handler;\r
-\r
- if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
-\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = child_handler;\r
-\r
- if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static void usage(char* whoami)\r
-{\r
- fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);\r
- fprintf(stderr, " -d\tinstallation prefix to use.\n");\r
- fprintf(stderr, " -c\tconfig file to use.\n");\r
- fprintf(stderr, " -x\tXML schema catalogs to use.\n");\r
- fprintf(stderr, " -t\ttest configuration file for problems.\n");\r
- fprintf(stderr, " -f\tforce removal of listener socket.\n");\r
- fprintf(stderr, " -F\tstay in the foreground.\n");\r
- fprintf(stderr, " -p\tpid file to use.\n");\r
- fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");\r
- fprintf(stderr, " -v\tprint software version.\n");\r
- fprintf(stderr, " -h\tprint this help message.\n");\r
- exit(1);\r
-}\r
-\r
-static int parse_args(int argc, char* argv[])\r
-{\r
- int opt;\r
-\r
- while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {\r
- switch (opt) {\r
- case 'd':\r
- shar_prefix=optarg;\r
- break;\r
- case 'c':\r
- shar_config=optarg;\r
- break;\r
- case 'x':\r
- shar_schemadir=optarg;\r
- break;\r
- case 'f':\r
- unlink_socket = true;\r
- break;\r
- case 'F':\r
- daemonize = false;\r
- break;\r
- case 't':\r
- shar_checkonly=true;\r
- daemonize=false;\r
- break;\r
- case 'v':\r
- shar_version=true;\r
- break;\r
- case 'p':\r
- pidfile=optarg;\r
- break;\r
- case 'w':\r
- if (optarg)\r
- daemon_wait = atoi(optarg);\r
- if (daemon_wait <= 0)\r
- daemon_wait = 3;\r
- break;\r
- default:\r
- return -1;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
- if (parse_args(argc, argv) != 0)\r
- usage(argv[0]);\r
- else if (shar_version) {\r
- fprintf(stdout, PACKAGE_STRING"\n");\r
- return 0;\r
- }\r
-\r
- if (setup_signals() != 0)\r
- return -1;\r
-\r
- // initialize the shib-target library\r
- SPConfig& conf=SPConfig::getConfig();\r
- conf.setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::Metadata |\r
- SPConfig::Trust |\r
- SPConfig::Credentials |\r
- SPConfig::AttributeResolution |\r
- SPConfig::Handlers |\r
- SPConfig::OutOfProcess |\r
- (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
- );\r
- if (!conf.init(shar_schemadir, shar_prefix)) {\r
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
- return -1;\r
- }\r
-\r
- if (daemonize) {\r
- // We must fork() early, while we're single threaded.\r
- // StorageService cleanup thread is about to start.\r
- switch (fork()) {\r
- case 0:\r
- break;\r
- case -1:\r
- perror("forking");\r
- exit(EXIT_FAILURE);\r
- default:\r
- sleep(daemon_wait);\r
- exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
- }\r
- }\r
-\r
- if (!conf.instantiate(shar_config)) {\r
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
- conf.term();\r
- return -2;\r
- }\r
-\r
- if (shar_checkonly)\r
- fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
- else {\r
- // Init the listener.\r
- ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
- if (!listener->init(unlink_socket)) {\r
- fprintf(stderr, "listener failed to initialize\n");\r
- conf.term();\r
- return -3;\r
- }\r
-\r
- if (daemonize) {\r
- if (setsid() == -1) {\r
- perror("setsid");\r
- exit(EXIT_FAILURE);\r
- }\r
- if (chdir("/") == -1) {\r
- perror("chdir to root");\r
- exit(EXIT_FAILURE);\r
- }\r
-\r
- if (pidfile) {\r
- FILE* pidf = fopen(pidfile, "w");\r
- if (pidf) {\r
- fprintf(pidf, "%d\n", getpid());\r
- fclose(pidf);\r
- }\r
- else {\r
- perror(pidfile);\r
- }\r
- }\r
-\r
- freopen("/dev/null", "r", stdin);\r
- freopen("/dev/null", "w", stdout);\r
- freopen("/dev/null", "w", stderr);\r
-\r
- // Signal our parent that we are A-OK.\r
- kill(getppid(), SIGUSR1);\r
- }\r
-\r
- // Run the listener.\r
- if (!listener->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failure during service\n");\r
- listener->term();\r
- conf.term();\r
- if (pidfile)\r
- unlink(pidfile);\r
- return -3;\r
- }\r
- listener->term();\r
- }\r
-\r
- conf.term();\r
- if (pidfile)\r
- unlink(pidfile);\r
- return 0;\r
-}\r
-\r
-#endif\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * shar.cpp -- the shibd "main" code. All the functionality is elsewhere
+ *
+ * Created By: Derek Atkins <derek@ihtfp.com>
+ *
+ * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $
+ */
+
+
+// eventually we might be able to support autoconf via cygwin...
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <shibsp/SPConfig.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#include <sys/select.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>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+bool shibd_shutdown = false;
+const char* shar_config = NULL;
+const char* shar_schemadir = NULL;
+const char* shar_prefix = NULL;
+bool shar_checkonly = false;
+bool shar_version = false;
+static bool unlink_socket = false;
+const char* pidfile = NULL;
+
+#ifdef WIN32
+
+//#include <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)
+{
+ SPConfig& conf=SPConfig::getConfig();
+ if (preinit) {
+
+ // Initialize the SP library.
+ conf.setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::Metadata |
+ SPConfig::Trust |
+ SPConfig::Credentials |
+ SPConfig::AttributeResolution |
+ SPConfig::Handlers |
+ SPConfig::OutOfProcess |
+ (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+ );
+ if (!conf.init(shar_schemadir, shar_prefix)) {
+ fprintf(stderr, "configuration is invalid, see console for specific problems\n");
+ return -1;
+ }
+
+ if (!conf.instantiate(shar_config)) {
+ fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ conf.term();
+ return -2;
+ }
+
+ // If just a test run, bail.
+ if (shar_checkonly) {
+ fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
+ return 0;
+ }
+ }
+ else {
+
+ //_CrtSetAllocHook(MyAllocHook);
+
+ if (!shar_checkonly) {
+ // Run the listener.
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
+ else if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, "listener failed during service\n");
+ listener->term();
+ conf.term();
+ return -3;
+ }
+ listener->term();
+ }
+
+ conf.term();
+ }
+ return 0;
+}
+
+#else
+
+int daemon_wait = 3;
+bool shibd_running = false;
+bool daemonize = true;
+
+static void term_handler(int arg)
+{
+ shibd_shutdown = true;
+}
+
+static void run_handler(int arg)
+{
+ shibd_running = true;
+}
+
+static void child_handler(int arg)
+{
+ // Terminate the parent's wait/sleep if the newly born daemon dies early.
+}
+
+static int setup_signals(void)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGPIPE, &sa, NULL) < 0) {
+ return -1;
+ }
+
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = term_handler;
+ sa.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGHUP, &sa, NULL) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGINT, &sa, NULL) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGQUIT, &sa, NULL) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGTERM, &sa, NULL) < 0) {
+ return -1;
+ }
+
+ if (daemonize) {
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = run_handler;
+
+ if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+ return -1;
+ }
+
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = child_handler;
+
+ if (sigaction(SIGCHLD, &sa, NULL) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void usage(char* whoami)
+{
+ fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);
+ fprintf(stderr, " -d\tinstallation prefix to use.\n");
+ fprintf(stderr, " -c\tconfig file to use.\n");
+ fprintf(stderr, " -x\tXML schema catalogs to use.\n");
+ fprintf(stderr, " -t\ttest configuration file for problems.\n");
+ fprintf(stderr, " -f\tforce removal of listener socket.\n");
+ fprintf(stderr, " -F\tstay in the foreground.\n");
+ fprintf(stderr, " -p\tpid file to use.\n");
+ fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");
+ fprintf(stderr, " -v\tprint software version.\n");
+ fprintf(stderr, " -h\tprint this help message.\n");
+ exit(1);
+}
+
+static int parse_args(int argc, char* argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {
+ switch (opt) {
+ case 'd':
+ shar_prefix=optarg;
+ break;
+ case 'c':
+ shar_config=optarg;
+ break;
+ case 'x':
+ shar_schemadir=optarg;
+ break;
+ case 'f':
+ unlink_socket = true;
+ break;
+ case 'F':
+ daemonize = false;
+ break;
+ case 't':
+ shar_checkonly=true;
+ daemonize=false;
+ break;
+ case 'v':
+ shar_version=true;
+ break;
+ case 'p':
+ pidfile=optarg;
+ break;
+ case 'w':
+ if (optarg)
+ daemon_wait = atoi(optarg);
+ if (daemon_wait <= 0)
+ daemon_wait = 3;
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (parse_args(argc, argv) != 0)
+ usage(argv[0]);
+ else if (shar_version) {
+ fprintf(stdout, PACKAGE_STRING"\n");
+ return 0;
+ }
+
+ if (setup_signals() != 0)
+ return -1;
+
+ // initialize the shib-target library
+ SPConfig& conf=SPConfig::getConfig();
+ conf.setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::Metadata |
+ SPConfig::Trust |
+ SPConfig::Credentials |
+ SPConfig::AttributeResolution |
+ SPConfig::Handlers |
+ SPConfig::OutOfProcess |
+ (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+ );
+ if (!conf.init(shar_schemadir, shar_prefix)) {
+ fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ return -1;
+ }
+
+ if (daemonize) {
+ // We must fork() early, while we're single threaded.
+ // StorageService cleanup thread is about to start.
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ perror("forking");
+ exit(EXIT_FAILURE);
+ default:
+ sleep(daemon_wait);
+ exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+ }
+
+ if (!conf.instantiate(shar_config)) {
+ fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ conf.term();
+ return -2;
+ }
+
+ if (shar_checkonly)
+ fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
+ else {
+ // Init the listener.
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
+
+ if (daemonize) {
+ if (setsid() == -1) {
+ perror("setsid");
+ exit(EXIT_FAILURE);
+ }
+ if (chdir("/") == -1) {
+ perror("chdir to root");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pidfile) {
+ FILE* pidf = fopen(pidfile, "w");
+ if (pidf) {
+ fprintf(pidf, "%d\n", getpid());
+ fclose(pidf);
+ }
+ else {
+ perror(pidfile);
+ }
+ }
+
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+
+ // Signal our parent that we are A-OK.
+ kill(getppid(), SIGUSR1);
+ }
+
+ // Run the listener.
+ if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, "listener failure during service\n");
+ listener->term();
+ conf.term();
+ if (pidfile)
+ unlink(pidfile);
+ return -3;
+ }
+ listener->term();
+ }
+
+ conf.term();
+ if (pidfile)
+ unlink(pidfile);
+ return 0;
+}
+
+#endif
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
FILEFLAGSMASK 0x3fL\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
VALUE "Comments", "\0"\r
VALUE "CompanyName", "Internet2\0"\r
VALUE "FileDescription", "Shibboleth Daemon Service\0"\r
- VALUE "FileVersion", "2, 2, 1, 0\0"\r
+ VALUE "FileVersion", "2, 3, 0, 0\0"\r
VALUE "InternalName", "shibd\0"\r
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"\r
VALUE "LegalTrademarks", "\0"\r
VALUE "OriginalFilename", "shibd.exe\0"\r
VALUE "PrivateBuild", "\0"\r
- VALUE "ProductName", "Shibboleth 2.2.1\0"\r
- VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+ VALUE "ProductName", "Shibboleth 2.3\0"\r
+ VALUE "ProductVersion", "2, 3, 0, 0\0"\r
VALUE "SpecialBuild", "\0"\r
END\r
END\r
-/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/*\r
- * shar_win32.cpp -- the SHAR "main" code on Win32\r
- *\r
- * Created By: Scott Cantor (cantor.2@osu.edu)\r
- *\r
- * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $\r
- */\r
-\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-\r
-#include <shibsp/base.h>\r
-#include <string>\r
-#include <windows.h>\r
-\r
-using namespace std;\r
-\r
-extern bool shibd_shutdown; // signals shutdown to Unix side\r
-extern const char* shar_schemadir;\r
-extern const char* shar_config;\r
-extern const char* shar_prefix;\r
-extern bool shar_checkonly;\r
-\r
-// internal variables\r
-SERVICE_STATUS ssStatus; // current status of the service\r
-SERVICE_STATUS_HANDLE sshStatusHandle;\r
-DWORD dwErr = 0;\r
-BOOL bConsole = FALSE;\r
-char szErr[256];\r
-LPCSTR lpszInstall = NULL;\r
-LPCSTR lpszRemove = NULL;\r
-\r
-// internal function prototypes\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode);\r
-VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID CmdInstallService(LPCSTR);\r
-VOID CmdRemoveService(LPCSTR);\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );\r
-\r
-BOOL LogEvent(\r
- LPCTSTR lpUNCServerName,\r
- WORD wType,\r
- DWORD dwEventID,\r
- PSID lpUserSid,\r
- LPCTSTR message);\r
-\r
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID ServiceStop();\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);\r
-void AddToMessageLog(LPSTR lpszMsg);\r
-\r
-BOOL WINAPI BreakHandler(DWORD dwCtrlType)\r
-{\r
- switch(dwCtrlType)\r
- {\r
- case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate\r
- case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode\r
- ServiceStop();\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-int real_main(int); // The revised two-phase main() in shar.cpp\r
-\r
-int main(int argc, char *argv[])\r
-{\r
- int i=1;\r
- while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))\r
- {\r
- if (_stricmp("install", argv[i]+1) == 0)\r
- {\r
- if (argc > ++i)\r
- lpszInstall = argv[i++];\r
- }\r
- else if (_stricmp("remove", argv[i]+1) == 0)\r
- {\r
- if (argc > ++i)\r
- lpszRemove = argv[i++];\r
- }\r
- else if (_stricmp( "console", argv[i]+1) == 0)\r
- {\r
- i++;\r
- bConsole = TRUE;\r
- }\r
- else if (_stricmp( "check", argv[i]+1) == 0)\r
- {\r
- i++;\r
- bConsole = TRUE;\r
- shar_checkonly=true;\r
- }\r
- else if (_stricmp( "config", argv[i]+1) == 0)\r
- {\r
- if (argc > ++i)\r
- shar_config = argv[i++];\r
- }\r
- else if (_stricmp( "prefix", argv[i]+1) == 0)\r
- {\r
- if (argc > ++i)\r
- shar_prefix = argv[i++];\r
- }\r
- else if (_stricmp( "catalogs", argv[i]+1) == 0)\r
- {\r
- if (argc > ++i)\r
- shar_schemadir = argv[i++];\r
- }\r
- else\r
- {\r
- goto dispatch;\r
- }\r
- }\r
- \r
- if (bConsole)\r
- {\r
- // Install break handler, then run the C routine twice, once to setup, once to start running.\r
- SetConsoleCtrlHandler(&BreakHandler,TRUE);\r
- if ((i=real_main(1))!=0)\r
- {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
- return i;\r
- }\r
- return real_main(0);\r
- }\r
- else if (lpszInstall)\r
- {\r
- CmdInstallService(lpszInstall);\r
- return 0;\r
- }\r
- else if (lpszRemove)\r
- {\r
- CmdRemoveService(lpszRemove);\r
- return 0;\r
- }\r
- \r
-\r
- // if it doesn't match any of the above parameters\r
- // the service control manager may be starting the service\r
- // so we must call StartServiceCtrlDispatcher\r
- dispatch:\r
- // this is just to be friendly\r
- printf("%s -install <name> to install the named service\n", argv[0]);\r
- printf("%s -remove <name> to remove the named service\n", argv[0]);\r
- printf("%s -console to run as a console app for debugging\n", argv[0]);\r
- printf("%s -check to run as a console app and check configuration\n", argv[0]);\r
- printf("\t-prefix <dir> to specify the installation directory\n");\r
- printf("\t-config <file> to specify the config file to use\n");\r
- printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");\r
- printf("\nService starting.\nThis may take several seconds. Please wait.\n" );\r
-\r
- SERVICE_TABLE_ENTRY dispatchTable[] =\r
- {\r
- { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },\r
- { NULL, NULL }\r
- };\r
-\r
- if (!StartServiceCtrlDispatcher(dispatchTable))\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");\r
- return 0;\r
-}\r
-\r
-//\r
-// FUNCTION: ServiceStart\r
-//\r
-// PURPOSE: Actual code of the service\r
-// that does the work.\r
-//\r
-VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
- if (real_main(1)!=0)\r
- {\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
- return;\r
- }\r
-\r
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");\r
-\r
- if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))\r
- return;\r
-\r
- real_main(0);\r
-}\r
-\r
-\r
-//\r
-// FUNCTION: ServiceStop\r
-//\r
-// PURPOSE: Stops the service\r
-//\r
-VOID ServiceStop()\r
-{\r
- if (!bConsole)\r
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");\r
- shibd_shutdown=true;\r
-}\r
-\r
-\r
-void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
- // register our service control handler:\r
- sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);\r
- if (!sshStatusHandle)\r
- goto cleanup;\r
-\r
- // SERVICE_STATUS members that don't change in example\r
- ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
- ssStatus.dwServiceSpecificExitCode = 0;\r
-\r
-\r
- // report the status to the service control manager.\r
- if (!ReportStatusToSCMgr(\r
- SERVICE_START_PENDING, // service state\r
- NO_ERROR, // exit code\r
- 3000)) // wait hint\r
- goto cleanup;\r
-\r
-\r
- ServiceStart(dwArgc, lpszArgv);\r
-\r
-cleanup:\r
-\r
- // try to report the stopped status to the service control manager.\r
- //\r
- if (sshStatusHandle)\r
- (VOID)ReportStatusToSCMgr(\r
- SERVICE_STOPPED,\r
- dwErr,\r
- 0);\r
-\r
- return;\r
-}\r
-\r
-\r
-//\r
-// FUNCTION: service_ctrl\r
-//\r
-// PURPOSE: This function is called by the SCM whenever\r
-// ControlService() is called on this service.\r
-//\r
-// PARAMETERS:\r
-// dwCtrlCode - type of control requested\r
-//\r
-// RETURN VALUE:\r
-// none\r
-//\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode)\r
-{\r
- // Handle the requested control code.\r
- //\r
- switch(dwCtrlCode)\r
- {\r
- // Stop the service.\r
- //\r
- case SERVICE_CONTROL_STOP:\r
- ssStatus.dwCurrentState = SERVICE_STOP_PENDING;\r
- ServiceStop();\r
- break;\r
-\r
- // Update the service status.\r
- //\r
- case SERVICE_CONTROL_INTERROGATE:\r
- break;\r
-\r
- // invalid control code\r
- //\r
- default:\r
- break;\r
-\r
- }\r
-\r
- ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);\r
-}\r
-\r
-\r
-//\r
-// FUNCTION: ReportStatusToSCMgr()\r
-//\r
-// PURPOSE: Sets the current status of the service and\r
-// reports it to the Service Control Manager\r
-//\r
-// PARAMETERS:\r
-// dwCurrentState - the state of the service\r
-// dwWin32ExitCode - error code to report\r
-// dwWaitHint - worst case estimate to next checkpoint\r
-//\r
-// RETURN VALUE:\r
-// TRUE - success\r
-// FALSE - failure\r
-//\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,\r
- DWORD dwWin32ExitCode,\r
- DWORD dwWaitHint)\r
-{\r
- static DWORD dwCheckPoint = 1;\r
- BOOL fResult = TRUE;\r
-\r
-\r
- if (!bConsole) // when console we don't report to the SCM\r
- {\r
- if (dwCurrentState == SERVICE_START_PENDING)\r
- ssStatus.dwControlsAccepted = 0;\r
- else\r
- ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;\r
-\r
- ssStatus.dwCurrentState = dwCurrentState;\r
- ssStatus.dwWin32ExitCode = dwWin32ExitCode;\r
- ssStatus.dwWaitHint = dwWaitHint;\r
-\r
- if ( ( dwCurrentState == SERVICE_RUNNING ) ||\r
- ( dwCurrentState == SERVICE_STOPPED ) )\r
- ssStatus.dwCheckPoint = 0;\r
- else\r
- ssStatus.dwCheckPoint = dwCheckPoint++;\r
-\r
-\r
- // Report the status of the service to the service control manager.\r
- //\r
- if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))\r
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");\r
- }\r
- return fResult;\r
-}\r
-\r
-\r
-///////////////////////////////////////////////////////////////////\r
-//\r
-// The following code handles service installation and removal\r
-//\r
-//\r
-void CmdInstallService(LPCSTR name)\r
-{\r
- SC_HANDLE schService;\r
- SC_HANDLE schSCManager;\r
-\r
- char szPath[256];\r
-\r
- if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )\r
- {\r
- printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));\r
- return;\r
- }\r
- \r
- string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")";\r
- string realName = string("shibd_") + name;\r
- string cmd(szPath);\r
- if (shar_prefix)\r
- cmd = cmd + " -prefix " + shar_prefix;\r
- if (shar_config)\r
- cmd = cmd + " -config " + shar_config;\r
- if (shar_schemadir)\r
- cmd = cmd + " -schemadir " + shar_schemadir;\r
-\r
- schSCManager = OpenSCManager(\r
- NULL, // machine (NULL == local)\r
- NULL, // database (NULL == default)\r
- SC_MANAGER_ALL_ACCESS // access required\r
- );\r
- \r
- \r
- if ( schSCManager )\r
- {\r
- schService = CreateService(\r
- schSCManager, // SCManager database\r
- realName.c_str(), // name of service\r
- dispName.c_str(), // name to display\r
- SERVICE_ALL_ACCESS, // desired access\r
- SERVICE_WIN32_OWN_PROCESS, // service type\r
- SERVICE_AUTO_START, // start type\r
- SERVICE_ERROR_NORMAL, // error control type\r
- cmd.c_str(), // service's command line\r
- NULL, // no load ordering group\r
- NULL, // no tag identifier\r
- NULL, // dependencies\r
- NULL, // LocalSystem account\r
- NULL); // no password\r
-\r
- if ( schService )\r
- {\r
- printf("%s installed.\n", realName.c_str());\r
- CloseServiceHandle(schService);\r
- }\r
- else\r
- {\r
- printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));\r
- }\r
-\r
- CloseServiceHandle(schSCManager);\r
- }\r
- else\r
- printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-void CmdRemoveService(LPCSTR name)\r
-{\r
- SC_HANDLE schService;\r
- SC_HANDLE schSCManager;\r
- char realName[512];\r
-\r
- _snprintf(realName,sizeof(realName),"shibd_%s",name);\r
-\r
- schSCManager = OpenSCManager(\r
- NULL, // machine (NULL == local)\r
- NULL, // database (NULL == default)\r
- SC_MANAGER_ALL_ACCESS // access required\r
- );\r
- if ( schSCManager )\r
- {\r
- schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);\r
-\r
- if (schService)\r
- {\r
- // try to stop the service\r
- if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )\r
- {\r
- printf("Stopping shibd (%s).", name);\r
- Sleep( 1000 );\r
-\r
- while( QueryServiceStatus( schService, &ssStatus ) )\r
- {\r
- if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )\r
- {\r
- printf(".");\r
- Sleep( 1000 );\r
- }\r
- else\r
- break;\r
- }\r
-\r
- if ( ssStatus.dwCurrentState == SERVICE_STOPPED )\r
- printf("\n%s stopped.\n", realName);\r
- else\r
- printf("\n%s failed to stop.\n", realName);\r
-\r
- }\r
-\r
- // now remove the service\r
- if( DeleteService(schService) )\r
- printf("%s removed.\n", realName);\r
- else\r
- printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
-\r
- CloseServiceHandle(schService);\r
- }\r
- else\r
- printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
- CloseServiceHandle(schSCManager);\r
- }\r
- else\r
- printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-\r
-//\r
-// FUNCTION: GetLastErrorText\r
-//\r
-// PURPOSE: copies error message text to string\r
-//\r
-// PARAMETERS:\r
-// lpszBuf - destination buffer\r
-// dwSize - size of buffer\r
-//\r
-// RETURN VALUE:\r
-// destination buffer\r
-//\r
-// COMMENTS:\r
-//\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )\r
-{\r
- DWORD dwRet;\r
- LPSTR lpszTemp = NULL;\r
-\r
- dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,\r
- NULL,\r
- GetLastError(),\r
- LANG_NEUTRAL,\r
- (LPSTR)&lpszTemp,\r
- 0,\r
- NULL );\r
-\r
- // supplied buffer is not long enough\r
- if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )\r
- lpszBuf[0] = '\0';\r
- else\r
- {\r
- lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character\r
- sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );\r
- }\r
-\r
- if ( lpszTemp )\r
- LocalFree((HLOCAL) lpszTemp );\r
-\r
- return lpszBuf;\r
-}\r
-\r
-BOOL LogEvent(\r
- LPCSTR lpUNCServerName,\r
- WORD wType,\r
- DWORD dwEventID,\r
- PSID lpUserSid,\r
- LPCSTR message)\r
-{\r
- LPCSTR messages[] = {message, NULL};\r
- \r
- HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");\r
- BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
- return (DeregisterEventSource(hElog) && res);\r
-}\r
+/*
+ * Copyright 2001-2007 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * shar_win32.cpp -- the SHAR "main" code on Win32
+ *
+ * Created By: Scott Cantor (cantor.2@osu.edu)
+ *
+ * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $
+ */
+
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <shibsp/base.h>
+#include <string>
+#include <windows.h>
+
+using namespace std;
+
+extern bool shibd_shutdown; // signals shutdown to Unix side
+extern const char* shar_schemadir;
+extern const char* shar_config;
+extern const char* shar_prefix;
+extern bool shar_checkonly;
+
+// internal variables
+SERVICE_STATUS ssStatus; // current status of the service
+SERVICE_STATUS_HANDLE sshStatusHandle;
+DWORD dwErr = 0;
+BOOL bConsole = FALSE;
+char szErr[256];
+LPCSTR lpszInstall = NULL;
+LPCSTR lpszRemove = NULL;
+
+// internal function prototypes
+VOID WINAPI service_ctrl(DWORD dwCtrlCode);
+VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);
+VOID CmdInstallService(LPCSTR);
+VOID CmdRemoveService(LPCSTR);
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );
+
+BOOL LogEvent(
+ LPCTSTR lpUNCServerName,
+ WORD wType,
+ DWORD dwEventID,
+ PSID lpUserSid,
+ LPCTSTR message);
+
+VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
+VOID ServiceStop();
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
+void AddToMessageLog(LPSTR lpszMsg);
+
+BOOL WINAPI BreakHandler(DWORD dwCtrlType)
+{
+ switch(dwCtrlType)
+ {
+ case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
+ case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode
+ ServiceStop();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+int real_main(int); // The revised two-phase main() in shar.cpp
+
+int main(int argc, char *argv[])
+{
+ int i=1;
+ while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))
+ {
+ if (_stricmp("install", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ lpszInstall = argv[i++];
+ }
+ else if (_stricmp("remove", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ lpszRemove = argv[i++];
+ }
+ else if (_stricmp( "console", argv[i]+1) == 0)
+ {
+ i++;
+ bConsole = TRUE;
+ }
+ else if (_stricmp( "check", argv[i]+1) == 0)
+ {
+ i++;
+ bConsole = TRUE;
+ shar_checkonly=true;
+ }
+ else if (_stricmp( "config", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ shar_config = argv[i++];
+ }
+ else if (_stricmp( "prefix", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ shar_prefix = argv[i++];
+ }
+ else if (_stricmp( "catalogs", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ shar_schemadir = argv[i++];
+ }
+ else
+ {
+ goto dispatch;
+ }
+ }
+
+ if (bConsole)
+ {
+ // Install break handler, then run the C routine twice, once to setup, once to start running.
+ SetConsoleCtrlHandler(&BreakHandler,TRUE);
+ if ((i=real_main(1))!=0)
+ {
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
+ return i;
+ }
+ return real_main(0);
+ }
+ else if (lpszInstall)
+ {
+ CmdInstallService(lpszInstall);
+ return 0;
+ }
+ else if (lpszRemove)
+ {
+ CmdRemoveService(lpszRemove);
+ return 0;
+ }
+
+
+ // if it doesn't match any of the above parameters
+ // the service control manager may be starting the service
+ // so we must call StartServiceCtrlDispatcher
+ dispatch:
+ // this is just to be friendly
+ printf("%s -install <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("\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" );
+
+ SERVICE_TABLE_ENTRY dispatchTable[] =
+ {
+ { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },
+ { NULL, NULL }
+ };
+
+ if (!StartServiceCtrlDispatcher(dispatchTable))
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");
+ return 0;
+}
+
+//
+// FUNCTION: ServiceStart
+//
+// PURPOSE: Actual code of the service
+// that does the work.
+//
+VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)
+{
+
+ if (real_main(1)!=0)
+ {
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
+ return;
+ }
+
+ LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");
+
+ if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
+ return;
+
+ real_main(0);
+}
+
+
+//
+// FUNCTION: ServiceStop
+//
+// PURPOSE: Stops the service
+//
+VOID ServiceStop()
+{
+ if (!bConsole)
+ LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");
+ shibd_shutdown=true;
+}
+
+
+void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)
+{
+
+ // register our service control handler:
+ sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
+ if (!sshStatusHandle)
+ goto cleanup;
+
+ // SERVICE_STATUS members that don't change in example
+ ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ssStatus.dwServiceSpecificExitCode = 0;
+
+
+ // report the status to the service control manager.
+ if (!ReportStatusToSCMgr(
+ SERVICE_START_PENDING, // service state
+ NO_ERROR, // exit code
+ 3000)) // wait hint
+ goto cleanup;
+
+
+ ServiceStart(dwArgc, lpszArgv);
+
+cleanup:
+
+ // try to report the stopped status to the service control manager.
+ //
+ if (sshStatusHandle)
+ (VOID)ReportStatusToSCMgr(
+ SERVICE_STOPPED,
+ dwErr,
+ 0);
+
+ return;
+}
+
+
+//
+// FUNCTION: service_ctrl
+//
+// PURPOSE: This function is called by the SCM whenever
+// ControlService() is called on this service.
+//
+// PARAMETERS:
+// dwCtrlCode - type of control requested
+//
+// RETURN VALUE:
+// none
+//
+VOID WINAPI service_ctrl(DWORD dwCtrlCode)
+{
+ // Handle the requested control code.
+ //
+ switch(dwCtrlCode)
+ {
+ // Stop the service.
+ //
+ case SERVICE_CONTROL_STOP:
+ ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ ServiceStop();
+ break;
+
+ // Update the service status.
+ //
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+
+ // invalid control code
+ //
+ default:
+ break;
+
+ }
+
+ ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
+}
+
+
+//
+// FUNCTION: ReportStatusToSCMgr()
+//
+// PURPOSE: Sets the current status of the service and
+// reports it to the Service Control Manager
+//
+// PARAMETERS:
+// dwCurrentState - the state of the service
+// dwWin32ExitCode - error code to report
+// dwWaitHint - worst case estimate to next checkpoint
+//
+// RETURN VALUE:
+// TRUE - success
+// FALSE - failure
+//
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
+ DWORD dwWin32ExitCode,
+ DWORD dwWaitHint)
+{
+ static DWORD dwCheckPoint = 1;
+ BOOL fResult = TRUE;
+
+
+ if (!bConsole) // when console we don't report to the SCM
+ {
+ if (dwCurrentState == SERVICE_START_PENDING)
+ ssStatus.dwControlsAccepted = 0;
+ else
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+ ssStatus.dwCurrentState = dwCurrentState;
+ ssStatus.dwWin32ExitCode = dwWin32ExitCode;
+ ssStatus.dwWaitHint = dwWaitHint;
+
+ if ( ( dwCurrentState == SERVICE_RUNNING ) ||
+ ( dwCurrentState == SERVICE_STOPPED ) )
+ ssStatus.dwCheckPoint = 0;
+ else
+ ssStatus.dwCheckPoint = dwCheckPoint++;
+
+
+ // Report the status of the service to the service control manager.
+ //
+ if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");
+ }
+ return fResult;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+// The following code handles service installation and removal
+//
+//
+void CmdInstallService(LPCSTR name)
+{
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+ char szPath[256];
+
+ if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )
+ {
+ printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
+ return;
+ }
+
+ string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")";
+ string realName = string("shibd_") + name;
+ string cmd(szPath);
+ if (shar_prefix)
+ cmd = cmd + " -prefix " + shar_prefix;
+ if (shar_config)
+ cmd = cmd + " -config " + shar_config;
+ if (shar_schemadir)
+ cmd = cmd + " -schemadir " + shar_schemadir;
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+
+
+ if ( schSCManager )
+ {
+ schService = CreateService(
+ schSCManager, // SCManager database
+ realName.c_str(), // name of service
+ dispName.c_str(), // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ cmd.c_str(), // service's command line
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ NULL, // dependencies
+ NULL, // LocalSystem account
+ NULL); // no password
+
+ if ( schService )
+ {
+ printf("%s installed.\n", realName.c_str());
+ CloseServiceHandle(schService);
+ }
+ else
+ {
+ printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));
+ }
+
+ CloseServiceHandle(schSCManager);
+ }
+ else
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
+}
+
+void CmdRemoveService(LPCSTR name)
+{
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+ char realName[512];
+
+ _snprintf(realName,sizeof(realName),"shibd_%s",name);
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if ( schSCManager )
+ {
+ schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);
+
+ if (schService)
+ {
+ // try to stop the service
+ if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
+ {
+ printf("Stopping shibd (%s).", name);
+ Sleep( 1000 );
+
+ while( QueryServiceStatus( schService, &ssStatus ) )
+ {
+ if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
+ {
+ printf(".");
+ Sleep( 1000 );
+ }
+ else
+ break;
+ }
+
+ if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
+ printf("\n%s stopped.\n", realName);
+ else
+ printf("\n%s failed to stop.\n", realName);
+
+ }
+
+ // now remove the service
+ if( DeleteService(schService) )
+ printf("%s removed.\n", realName);
+ else
+ printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));
+
+
+ CloseServiceHandle(schService);
+ }
+ else
+ printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));
+
+ CloseServiceHandle(schSCManager);
+ }
+ else
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
+}
+
+
+//
+// FUNCTION: GetLastErrorText
+//
+// PURPOSE: copies error message text to string
+//
+// PARAMETERS:
+// lpszBuf - destination buffer
+// dwSize - size of buffer
+//
+// RETURN VALUE:
+// destination buffer
+//
+// COMMENTS:
+//
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )
+{
+ DWORD dwRet;
+ LPSTR lpszTemp = NULL;
+
+ dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ NULL,
+ GetLastError(),
+ LANG_NEUTRAL,
+ (LPSTR)&lpszTemp,
+ 0,
+ NULL );
+
+ // supplied buffer is not long enough
+ if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
+ lpszBuf[0] = '\0';
+ else
+ {
+ lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character
+ sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );
+ }
+
+ if ( lpszTemp )
+ LocalFree((HLOCAL) lpszTemp );
+
+ return lpszBuf;
+}
+
+BOOL LogEvent(
+ LPCSTR lpUNCServerName,
+ WORD wType,
+ DWORD dwEventID,
+ PSID lpUserSid,
+ LPCSTR message)
+{
+ LPCSTR messages[] = {message, NULL};
+
+ HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");
+ BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
+ return (DeregisterEventSource(hElog) && res);
+}
/**
* AbstractSPRequest.cpp
*
- * Abstract base for SPRequest implementations
+ * Abstract base for SPRequest implementations.
*/
#include "internal.h"
+#include "exceptions.h"
#include "AbstractSPRequest.h"
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
+#include "util/CGIParser.h"
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling;
using namespace std;
+SPRequest::SPRequest()
+{
+}
+
+SPRequest::~SPRequest()
+{
+}
+
+string SPRequest::getSecureHeader(const char* name) const
+{
+ return getHeader(name);
+}
+
+void SPRequest::setAuthType(const char* authtype)
+{
+}
+
AbstractSPRequest::AbstractSPRequest(const char* category)
: m_sp(NULL), m_mapper(NULL), m_app(NULL), m_sessionTried(false), m_session(NULL),
m_log(&Category::getInstance(category)), m_parser(NULL)
delete m_parser;
}
+const ServiceProvider& AbstractSPRequest::getServiceProvider() const
+{
+ return *m_sp;
+}
+
RequestMapper::Settings AbstractSPRequest::getRequestSettings() const
{
if (!m_mapper) {
}
}
+const char* AbstractSPRequest::getRequestURI() const
+{
+ return m_uri.c_str();
+}
+
const char* AbstractSPRequest::getRequestURL() const
{
if (m_url.empty()) {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/AbstractSPRequest.h
*
- * Abstract base for SPRequest implementations
+ * Abstract base for SPRequest implementations.
*/
#ifndef __shibsp_abstreq_h__
#define __shibsp_abstreq_h__
-#include <shibsp/exceptions.h>
#include <shibsp/SPRequest.h>
-#include <shibsp/util/CGIParser.h>
namespace shibsp {
+ class SHIBSP_API CGIParser;
+
#if defined (_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4251 )
/**
* Stores a normalized request URI to ensure it contains no %-encoded characters
- * or other undesirable artifacts, such as ;jsessionid appendage.
+ * or other undesirable artifacts.
*
* @param uri the request URI as obtained from the client
*/
public:
virtual ~AbstractSPRequest();
- const ServiceProvider& getServiceProvider() const {
- return *m_sp;
- }
-
+ // Virtual function overrides.
+ const ServiceProvider& getServiceProvider() const;
RequestMapper::Settings getRequestSettings() const;
-
const Application& getApplication() const;
-
Session* getSession(bool checkTimeout=true, bool ignoreAddress=false, bool cache=true);
-
- const char* getRequestURI() const {
- return m_uri.c_str();
- }
-
+ const char* getRequestURI() const;
const char* getRequestURL() const;
-
std::string getRemoteAddr() const;
-
const char* getParameter(const char* name) const;
-
std::vector<const char*>::size_type getParameters(const char* name, std::vector<const char*>& values) const;
-
const char* getHandlerURL(const char* resource=NULL) const;
-
void log(SPLogLevel level, const std::string& msg) const;
-
bool isPriorityEnabled(SPLogLevel level) const;
private:
{
MAKE_NONCOPYABLE(AccessControl);
protected:
- AccessControl() {}
+ AccessControl();
public:
- virtual ~AccessControl() {}
+ virtual ~AccessControl();
/**
* Possible results from an access control decision.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "remoting/ListenerService.h"
#include <algorithm>
+#include <xmltooling/util/Threads.h>
using namespace shibsp;
using namespace xmltooling;
delete m_lock;
}
+const ServiceProvider& Application::getServiceProvider() const
+{
+ return *m_sp;
+}
+
+const char* Application::getId() const
+{
+ return getString("id").second;
+}
+
pair<string,const char*> Application::getCookieNameProps(const char* prefix, time_t* lifetime) const
{
static const char* defProps="; path=/";
#include <shibsp/util/PropertySet.h>
-#include <set>
+#include <string>
+#include <vector>
#ifndef SHIBSP_LITE
# include <saml/binding/MessageEncoder.h>
-# include <saml/saml2/metadata/MetadataProvider.h>
-# include <xmltooling/security/CredentialResolver.h>
-# include <xmltooling/security/TrustEngine.h>
#endif
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/util/Threads.h>
+
+namespace xmltooling {
+ class XMLTOOL_API CredentialResolver;
+ class XMLTOOL_API RWLock;
+ class XMLTOOL_API SOAPTransport;
+ class XMLTOOL_API StorageService;
+ class XMLTOOL_API TrustEngine;
+};
+
+#ifndef SHIBSP_LITE
+namespace opensaml {
+ class SAML_API SecurityPolicyRule;
+ namespace saml2md {
+ class SAML_API MetadataProvider;
+ };
+};
+#endif
namespace shibsp {
*
* @return a locked ServiceProvider
*/
- const ServiceProvider& getServiceProvider() const {
- return *m_sp;
- }
+ const ServiceProvider& getServiceProvider() const;
/**
* Returns the Application's ID.
*
* @return the ID
*/
- virtual const char* getId() const {
- return getString("id").second;
- }
+ virtual const char* getId() const;
/**
* Returns a unique hash for the Application.
SPConfig.cpp \
attribute/Attribute.cpp \
attribute/ExtensibleAttribute.cpp \
+ attribute/NameIDAttribute.cpp \
+ attribute/SimpleAttribute.cpp \
+ attribute/ScopedAttribute.cpp \
+ attribute/XMLAttribute.cpp \
handler/impl/AbstractHandler.cpp \
handler/impl/AssertionConsumerService.cpp \
handler/impl/AssertionLookup.cpp \
attribute/filtering/impl/AttributeFilter.cpp \
attribute/filtering/impl/ChainingAttributeFilter.cpp \
attribute/filtering/impl/XMLAttributeFilter.cpp \
+ attribute/filtering/impl/BasicFilteringContext.cpp \
attribute/filtering/impl/MatchFunctor.cpp \
attribute/filtering/impl/AndMatchFunctor.cpp \
attribute/filtering/impl/AnyMatchFunctor.cpp \
metadata/DynamicMetadataProvider.cpp \
metadata/MetadataExtImpl.cpp \
metadata/MetadataExtSchemaValidators.cpp \
+ metadata/MetadataProviderCriteria.cpp \
security/PKIXTrustEngine.cpp \
security/SecurityPolicy.cpp
# this is different from the project version
# http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 4:0:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 4:0:0
libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
pkgsysconfdir = $(sysconfdir)/@PACKAGE@
libshibsp_lite_la-ServiceProvider.lo \
libshibsp_lite_la-SPConfig.lo libshibsp_lite_la-Attribute.lo \
libshibsp_lite_la-ExtensibleAttribute.lo \
+ libshibsp_lite_la-NameIDAttribute.lo \
+ libshibsp_lite_la-SimpleAttribute.lo \
+ libshibsp_lite_la-ScopedAttribute.lo \
+ libshibsp_lite_la-XMLAttribute.lo \
libshibsp_lite_la-AbstractHandler.lo \
libshibsp_lite_la-AssertionConsumerService.lo \
libshibsp_lite_la-AssertionLookup.lo \
libshibsp_la_LIBADD =
am__objects_2 = AbstractSPRequest.lo Application.lo ServiceProvider.lo \
SPConfig.lo Attribute.lo ExtensibleAttribute.lo \
- AbstractHandler.lo AssertionConsumerService.lo \
+ NameIDAttribute.lo SimpleAttribute.lo ScopedAttribute.lo \
+ XMLAttribute.lo AbstractHandler.lo AssertionConsumerService.lo \
AssertionLookup.lo ChainingLogoutInitiator.lo \
ChainingSessionInitiator.lo CookieSessionInitiator.lo \
FormSessionInitiator.lo LocalLogoutInitiator.lo \
NameIDFromScopedAttributeDecoder.lo ScopedAttributeDecoder.lo \
StringAttributeDecoder.lo XMLAttributeDecoder.lo \
AttributeFilter.lo ChainingAttributeFilter.lo \
- XMLAttributeFilter.lo MatchFunctor.lo AndMatchFunctor.lo \
- AnyMatchFunctor.lo NotMatchFunctor.lo OrMatchFunctor.lo \
- AttributeIssuerStringFunctor.lo \
+ XMLAttributeFilter.lo BasicFilteringContext.lo MatchFunctor.lo \
+ AndMatchFunctor.lo AnyMatchFunctor.lo NotMatchFunctor.lo \
+ OrMatchFunctor.lo AttributeIssuerStringFunctor.lo \
AttributeRequesterStringFunctor.lo \
AttributeScopeStringFunctor.lo AttributeValueStringFunctor.lo \
AuthenticationMethodStringFunctor.lo \
KeyDescriptorAttributeExtractor.lo XMLAttributeExtractor.lo \
ArtifactResolver.lo SOAPClient.lo DynamicMetadataProvider.lo \
MetadataExtImpl.lo MetadataExtSchemaValidators.lo \
- PKIXTrustEngine.lo SecurityPolicy.lo
+ MetadataProviderCriteria.lo PKIXTrustEngine.lo \
+ SecurityPolicy.lo
libshibsp_la_OBJECTS = $(am_libshibsp_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
SPConfig.cpp \
attribute/Attribute.cpp \
attribute/ExtensibleAttribute.cpp \
+ attribute/NameIDAttribute.cpp \
+ attribute/SimpleAttribute.cpp \
+ attribute/ScopedAttribute.cpp \
+ attribute/XMLAttribute.cpp \
handler/impl/AbstractHandler.cpp \
handler/impl/AssertionConsumerService.cpp \
handler/impl/AssertionLookup.cpp \
attribute/filtering/impl/AttributeFilter.cpp \
attribute/filtering/impl/ChainingAttributeFilter.cpp \
attribute/filtering/impl/XMLAttributeFilter.cpp \
+ attribute/filtering/impl/BasicFilteringContext.cpp \
attribute/filtering/impl/MatchFunctor.cpp \
attribute/filtering/impl/AndMatchFunctor.cpp \
attribute/filtering/impl/AnyMatchFunctor.cpp \
metadata/DynamicMetadataProvider.cpp \
metadata/MetadataExtImpl.cpp \
metadata/MetadataExtSchemaValidators.cpp \
+ metadata/MetadataProviderCriteria.cpp \
security/PKIXTrustEngine.cpp \
security/SecurityPolicy.cpp
# this is different from the project version
# http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 4:0:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 4:0:0
libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
pkgsysconfdir = $(sysconfdir)/@PACKAGE@
pkgxmldir = $(datadir)/xml/@PACKAGE@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AttributeValueStringFunctor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthenticationMethodRegexFunctor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthenticationMethodStringFunctor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BasicFilteringContext.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CGIParser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAccessControl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAttributeExtractor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataExtImpl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataExtSchemaValidators.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataGenerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataProviderCriteria.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDAttributeDecoder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDFromScopedAttributeDecoder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NotMatchFunctor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SOAPClient.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SPConfig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SPConstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScopedAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScopedAttributeDecoder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SecurityPolicy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServiceProvider.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Shib1SessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleAggregationAttributeResolver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketListener.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StatusHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StorageServiceSessionCache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnixListener.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WAYFSessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAccessControl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeDecoder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeExtractor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeFilter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-LocalLogoutInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-LogoutHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-MetadataGenerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-RemotedHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAML1Consumer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAML2ArtifactResolution.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAMLDSSessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SPConfig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SPConstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ServiceProvider.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SessionHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-Shib1SessionInitiator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SocketListener.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-StatusHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-UnixListener.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-WAYFSessionInitiator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLAccessControl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLRequestMapper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLServiceProvider.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ddf.Plo@am__quote@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp
+libshibsp_lite_la-NameIDAttribute.lo: attribute/NameIDAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-NameIDAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo" -c -o libshibsp_lite_la-NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/NameIDAttribute.cpp' object='libshibsp_lite_la-NameIDAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp
+
+libshibsp_lite_la-SimpleAttribute.lo: attribute/SimpleAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-SimpleAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo" -c -o libshibsp_lite_la-SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/SimpleAttribute.cpp' object='libshibsp_lite_la-SimpleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp
+
+libshibsp_lite_la-ScopedAttribute.lo: attribute/ScopedAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-ScopedAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo" -c -o libshibsp_lite_la-ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/ScopedAttribute.cpp' object='libshibsp_lite_la-ScopedAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp
+
+libshibsp_lite_la-XMLAttribute.lo: attribute/XMLAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-XMLAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo" -c -o libshibsp_lite_la-XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/XMLAttribute.cpp' object='libshibsp_lite_la-XMLAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp
+
libshibsp_lite_la-AbstractHandler.lo: handler/impl/AbstractHandler.cpp
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-AbstractHandler.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo" -c -o libshibsp_lite_la-AbstractHandler.lo `test -f 'handler/impl/AbstractHandler.cpp' || echo '$(srcdir)/'`handler/impl/AbstractHandler.cpp; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo" "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp
+NameIDAttribute.lo: attribute/NameIDAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT NameIDAttribute.lo -MD -MP -MF "$(DEPDIR)/NameIDAttribute.Tpo" -c -o NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/NameIDAttribute.Tpo" "$(DEPDIR)/NameIDAttribute.Plo"; else rm -f "$(DEPDIR)/NameIDAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/NameIDAttribute.cpp' object='NameIDAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp
+
+SimpleAttribute.lo: attribute/SimpleAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SimpleAttribute.lo -MD -MP -MF "$(DEPDIR)/SimpleAttribute.Tpo" -c -o SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/SimpleAttribute.Tpo" "$(DEPDIR)/SimpleAttribute.Plo"; else rm -f "$(DEPDIR)/SimpleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/SimpleAttribute.cpp' object='SimpleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp
+
+ScopedAttribute.lo: attribute/ScopedAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ScopedAttribute.lo -MD -MP -MF "$(DEPDIR)/ScopedAttribute.Tpo" -c -o ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/ScopedAttribute.Tpo" "$(DEPDIR)/ScopedAttribute.Plo"; else rm -f "$(DEPDIR)/ScopedAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/ScopedAttribute.cpp' object='ScopedAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp
+
+XMLAttribute.lo: attribute/XMLAttribute.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT XMLAttribute.lo -MD -MP -MF "$(DEPDIR)/XMLAttribute.Tpo" -c -o XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/XMLAttribute.Tpo" "$(DEPDIR)/XMLAttribute.Plo"; else rm -f "$(DEPDIR)/XMLAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/XMLAttribute.cpp' object='XMLAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp
+
AbstractHandler.lo: handler/impl/AbstractHandler.cpp
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT AbstractHandler.lo -MD -MP -MF "$(DEPDIR)/AbstractHandler.Tpo" -c -o AbstractHandler.lo `test -f 'handler/impl/AbstractHandler.cpp' || echo '$(srcdir)/'`handler/impl/AbstractHandler.cpp; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/AbstractHandler.Tpo" "$(DEPDIR)/AbstractHandler.Plo"; else rm -f "$(DEPDIR)/AbstractHandler.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o XMLAttributeFilter.lo `test -f 'attribute/filtering/impl/XMLAttributeFilter.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/XMLAttributeFilter.cpp
+BasicFilteringContext.lo: attribute/filtering/impl/BasicFilteringContext.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT BasicFilteringContext.lo -MD -MP -MF "$(DEPDIR)/BasicFilteringContext.Tpo" -c -o BasicFilteringContext.lo `test -f 'attribute/filtering/impl/BasicFilteringContext.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/BasicFilteringContext.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/BasicFilteringContext.Tpo" "$(DEPDIR)/BasicFilteringContext.Plo"; else rm -f "$(DEPDIR)/BasicFilteringContext.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/filtering/impl/BasicFilteringContext.cpp' object='BasicFilteringContext.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o BasicFilteringContext.lo `test -f 'attribute/filtering/impl/BasicFilteringContext.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/BasicFilteringContext.cpp
+
MatchFunctor.lo: attribute/filtering/impl/MatchFunctor.cpp
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT MatchFunctor.lo -MD -MP -MF "$(DEPDIR)/MatchFunctor.Tpo" -c -o MatchFunctor.lo `test -f 'attribute/filtering/impl/MatchFunctor.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/MatchFunctor.cpp; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/MatchFunctor.Tpo" "$(DEPDIR)/MatchFunctor.Plo"; else rm -f "$(DEPDIR)/MatchFunctor.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o MetadataExtSchemaValidators.lo `test -f 'metadata/MetadataExtSchemaValidators.cpp' || echo '$(srcdir)/'`metadata/MetadataExtSchemaValidators.cpp
+MetadataProviderCriteria.lo: metadata/MetadataProviderCriteria.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT MetadataProviderCriteria.lo -MD -MP -MF "$(DEPDIR)/MetadataProviderCriteria.Tpo" -c -o MetadataProviderCriteria.lo `test -f 'metadata/MetadataProviderCriteria.cpp' || echo '$(srcdir)/'`metadata/MetadataProviderCriteria.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/MetadataProviderCriteria.Tpo" "$(DEPDIR)/MetadataProviderCriteria.Plo"; else rm -f "$(DEPDIR)/MetadataProviderCriteria.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metadata/MetadataProviderCriteria.cpp' object='MetadataProviderCriteria.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o MetadataProviderCriteria.lo `test -f 'metadata/MetadataProviderCriteria.cpp' || echo '$(srcdir)/'`metadata/MetadataProviderCriteria.cpp
+
PKIXTrustEngine.lo: security/PKIXTrustEngine.cpp
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT PKIXTrustEngine.lo -MD -MP -MF "$(DEPDIR)/PKIXTrustEngine.Tpo" -c -o PKIXTrustEngine.lo `test -f 'security/PKIXTrustEngine.cpp' || echo '$(srcdir)/'`security/PKIXTrustEngine.cpp; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/PKIXTrustEngine.Tpo" "$(DEPDIR)/PKIXTrustEngine.Plo"; else rm -f "$(DEPDIR)/PKIXTrustEngine.Tpo"; exit 1; fi
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <shibsp/base.h>
#include <xmltooling/Lockable.h>
-#include <xmltooling/io/HTTPRequest.h>
+
+namespace xmltooling {
+ class XMLTOOL_API HTTPRequest;
+};
namespace shibsp {
{
MAKE_NONCOPYABLE(RequestMapper);
protected:
- RequestMapper() {}
+ RequestMapper();
public:
- virtual ~RequestMapper() {}
+ virtual ~RequestMapper();
/** Combination of configuration settings and effective access control. */
typedef std::pair<const PropertySet*,AccessControl*> Settings;
/**
* SPConfig.cpp
*
- * Library configuration
+ * Library configuration.
*/
#include "internal.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
#include "SPConfig.h"
+#include "TransactionLog.h"
#include "attribute/Attribute.h"
#include "handler/SessionInitiator.h"
#include "remoting/ListenerService.h"
# include "metadata/MetadataExt.h"
# include "security/PKIXTrustEngine.h"
# include <saml/SAMLConfig.h>
-#else
-# include <xmltooling/XMLToolingConfig.h>
#endif
#include <ctime>
#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
#include <xmltooling/util/PathResolver.h>
#include <xmltooling/util/TemplateEngine.h>
+#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
return g_config;
}
+SPConfig::SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL),
+#ifndef SHIBSP_LITE
+ m_artifactResolver(NULL),
+#endif
+ m_features(0), m_configDoc(NULL)
+{
+}
+
+SPConfig::~SPConfig()
+{
+}
+
+void SPConfig::setFeatures(unsigned long enabled)
+{
+ m_features = enabled;
+}
+
+bool SPConfig::isEnabled(components_t feature)
+{
+ return (m_features & feature)>0;
+}
+
+ServiceProvider* SPConfig::getServiceProvider() const
+{
+ return m_serviceProvider;
+}
+
void SPConfig::setServiceProvider(ServiceProvider* serviceProvider)
{
delete m_serviceProvider;
m_serviceProvider = serviceProvider;
}
+#ifndef SHIBSP_LITE
+void SPConfig::setArtifactResolver(MessageDecoder::ArtifactResolver* artifactResolver)
+{
+ delete m_artifactResolver;
+ m_artifactResolver = artifactResolver;
+}
+
+const MessageDecoder::ArtifactResolver* SPConfig::getArtifactResolver() const
+{
+ return m_artifactResolver;
+}
+#endif
+
bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
{
#ifdef _DEBUG
}
return false;
}
+
+TransactionLog::TransactionLog() : log(logging::Category::getInstance(SHIBSP_TX_LOGCAT)), m_lock(Mutex::create())
+{
+}
+
+TransactionLog::~TransactionLog()
+{
+ delete m_lock;
+}
+
+Lockable* TransactionLog::lock()
+{
+ m_lock->lock();
+ return this;
+}
+
+void TransactionLog::unlock()
+{
+ m_lock->unlock();
+}
#define __shibsp_config_h__
#include <shibsp/base.h>
+
+#include <string>
#ifndef SHIBSP_LITE
# include <saml/binding/MessageDecoder.h>
+# include <saml/binding/MessageEncoder.h>
#endif
#include <xmltooling/PluginManager.h>
+#include <xmltooling/QName.h>
#include <xercesc/dom/DOM.hpp>
/**
{
MAKE_NONCOPYABLE(SPConfig);
public:
- SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL),
-#ifndef SHIBSP_LITE
- m_artifactResolver(NULL),
-#endif
- m_features(0), m_configDoc(NULL) {
- }
+ SPConfig();
- virtual ~SPConfig() {}
+ virtual ~SPConfig();
/**
* Returns the global configuration object for the library.
*
* @param enabled bitmask of component constants
*/
- void setFeatures(unsigned long enabled) {
- m_features = enabled;
- }
+ void setFeatures(unsigned long enabled);
/**
* Test whether a subsystem is enabled.
* @param feature subsystem/component to test
* @return true iff feature is enabled
*/
- bool isEnabled(components_t feature) {
- return (m_features & feature)>0;
- }
+ bool isEnabled(components_t feature);
/**
* Initializes library
*
* @return global ServiceProvider or NULL
*/
- ServiceProvider* getServiceProvider() const {
- return m_serviceProvider;
- }
+ ServiceProvider* getServiceProvider() const;
/**
* Instantiates and installs a ServiceProvider instance based on an XML configuration string
*
* @param artifactResolver new ArtifactResolver instance to store
*/
- void setArtifactResolver(opensaml::MessageDecoder::ArtifactResolver* artifactResolver) {
- delete m_artifactResolver;
- m_artifactResolver = artifactResolver;
- }
+ void setArtifactResolver(opensaml::MessageDecoder::ArtifactResolver* artifactResolver);
/**
* Returns the global ArtifactResolver instance.
*
* @return global ArtifactResolver or NULL
*/
- const opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const {
- return m_artifactResolver;
- }
+ const opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const;
#endif
/** Separator for serialized values of multi-valued attributes. */
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/SPRequest.h
*
- * Interface to server request being processed
+ * Interface to server request being processed.
*/
#ifndef __shibsp_req_h__
class SHIBSP_API SPRequest : public virtual xmltooling::HTTPRequest, public virtual xmltooling::HTTPResponse
{
protected:
- SPRequest() {}
+ SPRequest();
public:
- virtual ~SPRequest() {}
+ virtual ~SPRequest();
/**
* Returns the locked ServiceProvider processing the request.
* @param name the name of the secure header to return
* @return the header's value, or an empty string
*/
- virtual std::string getSecureHeader(const char* name) const {
- return getHeader(name);
- }
+ virtual std::string getSecureHeader(const char* name) const;
/**
* Ensures no value exists for a request header.
*
* @param authtype AUTH_TYPE value to set or NULL to clear
*/
- virtual void setAuthType(const char* authtype) {
- }
+ virtual void setAuthType(const char* authtype);
/** Portable logging levels. */
enum SPLogLevel {
#include <fstream>
#include <sstream>
+#ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
+#endif
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/PathResolver.h>
if (!pathname.first)
pathname=props->getString(page);
}
- if (pathname.first) {
- string fname(pathname.second);
- ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
- if (infile) {
- tp.setPropertySet(props);
- stringstream str;
- XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException());
- return request.sendError(str);
- }
+
+ string fname;
+ if (!pathname.first) {
+ fname = string(page) + "Error.html";
+ pathname.second = fname.c_str();
+ }
+ else {
+ fname = pathname.second;
+ }
+
+ ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
+ if (infile) {
+ tp.setPropertySet(props);
+ stringstream str;
+ XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException());
+ return request.sendError(str);
}
- if (!strcmp(page,"access")) {
+ if (!strcmp(page, "access")) {
istringstream msg("Access Denied");
return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN);
}
- log.error("sendError could not process error template (%s)", page);
+ log.error("sendError could not process error template (%s)", pathname.second);
istringstream msg("Internal Server Error. Please contact the site administrator.");
return request.sendError(msg);
}
SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory);
}
+ServiceProvider::ServiceProvider()
+{
+}
+
+ServiceProvider::~ServiceProvider()
+{
+}
+
pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
{
#ifdef _DEBUG
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define __shibsp_sp_h__
#include <shibsp/util/PropertySet.h>
+
+#include <xmltooling/Lockable.h>
+
+namespace xmltooling {
+ class XMLTOOL_API SOAPTransport;
+ class XMLTOOL_API StorageService;
+};
+
#ifndef SHIBSP_LITE
-# include <saml/binding/SecurityPolicyRule.h>
-# include <xmltooling/soap/SOAPTransport.h>
-# include <xmltooling/util/StorageService.h>
+namespace opensaml {
+ class SAML_API SecurityPolicyRule;
+};
#endif
-#include <xmltooling/Lockable.h>
namespace shibsp {
{
MAKE_NONCOPYABLE(ServiceProvider);
protected:
- ServiceProvider() {}
+ ServiceProvider();
public:
- virtual ~ServiceProvider() {}
+ virtual ~ServiceProvider();
/**
* Loads a configuration and prepares the instance for use.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/SessionCache.h
*
- * Caches and manages user sessions
+ * Caches and manages user sessions.
*/
#ifndef __shibsp_sessioncache_h__
#define __shibsp_sessioncache_h__
#include <shibsp/base.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <ctime>
+#include <xmltooling/Lockable.h>
+
+namespace xmltooling {
+ class XMLTOOL_API HTTPRequest;
+ class XMLTOOL_API HTTPResponse;
+};
+
#ifndef SHIBSP_LITE
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
+# include <set>
+namespace opensaml {
+ class SAML_API Assertion;
+ namespace saml2 {
+ class SAML_API NameID;
+ };
+};
#endif
-#include <xmltooling/Lockable.h>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
namespace shibsp {
{
MAKE_NONCOPYABLE(Session);
protected:
- Session() {}
- virtual ~Session() {}
+ Session();
+ virtual ~Session();
public:
/**
* Returns the session key.
{
MAKE_NONCOPYABLE(SessionCache);
protected:
- SessionCache() {}
+ SessionCache();
public:
- virtual ~SessionCache() {}
+ virtual ~SessionCache();
#ifndef SHIBSP_LITE
/**
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
class SHIBSP_API SessionCacheEx : public SessionCache
{
protected:
- SessionCacheEx() {}
+ SessionCacheEx();
public:
- virtual ~SessionCacheEx() {}
+ virtual ~SessionCacheEx();
#ifndef SHIBSP_LITE
/**
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <shibsp/base.h>
#include <xmltooling/logging.h>
#include <xmltooling/Lockable.h>
-#include <xmltooling/util/Threads.h>
-namespace shibsp {
+namespace xmltooling {
+ class XMLTOOL_API Mutex;
+};
+namespace shibsp {
/**
* Interface to a synchronized logging object.
*
{
MAKE_NONCOPYABLE(TransactionLog);
public:
- TransactionLog()
- : log(xmltooling::logging::Category::getInstance(SHIBSP_TX_LOGCAT)), m_lock(xmltooling::Mutex::create()) {
- }
+ TransactionLog();
- virtual ~TransactionLog() {
- delete m_lock;
- }
+ virtual ~TransactionLog();
- xmltooling::Lockable* lock() {
- m_lock->lock();
- return this;
- }
+ xmltooling::Lockable* lock();
- void unlock() {
- m_lock->unlock();
- }
+ void unlock();
/** Logging object. */
xmltooling::logging::Category& log;
*/
#include "internal.h"
+#include "exceptions.h"
#include "SPConfig.h"
#ifndef SHIBSP_LITE
# include "attribute/AttributeDecoder.h"
#include "attribute/XMLAttribute.h"
#include "util/SPConstants.h"
-#include <xercesc/util/Base64.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/security/SecurityHelper.h>
using namespace shibsp;
using namespace xmltooling;
using namespace std;
namespace shibsp {
-
- SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in) {
- return new SimpleAttribute(in);
- }
-
- SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in) {
- return new ScopedAttribute(in);
- }
-
- SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in) {
- return new NameIDAttribute(in);
- }
-
- SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
- return new ExtensibleAttribute(in);
- }
-
- SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
- return new XMLAttribute(in);
- }
+ SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in);
+ SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in);
+ SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in);
+ SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in);
+ SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in);
#ifndef SHIBSP_LITE
SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
static const XMLCh _XMLAttributeDecoder[] = UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
static const XMLCh caseSensitive[] = UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
+ static const XMLCh hashAlg[] = UNICODE_LITERAL_7(h,a,s,h,A,l,g);
static const XMLCh internal[] = UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
#endif
};
conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
}
-AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), m_internal(false)
+AttributeDecoder::AttributeDecoder(const DOMElement *e)
+ : m_caseSensitive(true), m_internal(false), m_hashAlg(e ? e->getAttributeNS(NULL, hashAlg) : NULL)
{
if (e) {
const XMLCh* flag = e->getAttributeNS(NULL, caseSensitive);
m_internal = true;
}
}
+
+AttributeDecoder::~AttributeDecoder()
+{
+}
+
+Attribute* AttributeDecoder::_decode(Attribute* attr) const
+{
+ if (attr) {
+ attr->setCaseSensitive(m_caseSensitive);
+ attr->setInternal(m_internal);
+
+ if (m_hashAlg.get() && *m_hashAlg.get()) {
+ // We turn the values into strings using the supplied hash algorithm and return a SimpleAttribute instead.
+ auto_ptr<SimpleAttribute> simple(new SimpleAttribute(attr->getAliases()));
+ simple->setCaseSensitive(false);
+ simple->setInternal(m_internal);
+ vector<string>& newdest = simple->getValues();
+ const vector<string>& serialized = attr->getSerializedValues();
+ for (vector<string>::const_iterator ser = serialized.begin(); ser != serialized.end(); ++ser) {
+ newdest.push_back(SecurityHelper::doHash(m_hashAlg.get(), ser->data(), ser->length()));
+ if (newdest.back().empty())
+ newdest.pop_back();
+ }
+ delete attr;
+ return newdest.empty() ? NULL : simple.release();
+ }
+
+ }
+ return attr;
+}
#endif
void shibsp::registerAttributeFactories()
map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
+void Attribute::registerFactory(const char* type, AttributeFactory* factory)
+{
+ m_factoryMap[type] = factory;
+}
+
+void Attribute::deregisterFactory(const char* type)
+{
+ m_factoryMap.erase(type);
+}
+
+void Attribute::deregisterFactories()
+{
+ m_factoryMap.clear();
+}
+
+Attribute::Attribute(const vector<string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false)
+{
+}
+
Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()), m_internal(!in["internal"].isnull())
{
const char* id = in.first().name();
}
}
+Attribute::~Attribute()
+{
+}
+
+const char* Attribute::getId() const
+{
+ return m_id.front().c_str();
+}
+
+const vector<string>& Attribute::getAliases() const
+{
+ return m_id;
+}
+
+vector<string>& Attribute::getAliases()
+{
+ return m_id;
+}
+
+void Attribute::setCaseSensitive(bool caseSensitive)
+{
+ m_caseSensitive = caseSensitive;
+}
+
+void Attribute::setInternal(bool internal)
+{
+ m_internal = internal;
+}
+
+bool Attribute::isCaseSensitive() const
+{
+ return m_caseSensitive;
+}
+
+bool Attribute::isInternal() const
+{
+ return m_internal;
+}
+
+size_t Attribute::valueCount() const
+{
+ return m_serialized.size();
+}
+
+const vector<string>& Attribute::getSerializedValues() const
+{
+ return m_serialized;
+}
+
+const char* Attribute::getString(size_t index) const
+{
+ return m_serialized[index].c_str();
+}
+
+const char* Attribute::getScope(size_t index) const
+{
+ return NULL;
+}
+
+void Attribute::removeValue(size_t index)
+{
+ if (index < m_serialized.size())
+ m_serialized.erase(m_serialized.begin() + index);
+}
+
DDF Attribute::marshall() const
{
DDF ddf(NULL);
throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
return (i->second)(in);
}
-
-const vector<string>& XMLAttribute::getSerializedValues() const
-{
- xsecsize_t len;
- XMLByte *pos, *pos2;\r
- if (m_serialized.empty()) {
- for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
- XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
- if (enc) {
- for (pos=enc, pos2=enc; *pos2; pos2++)\r
- if (isgraph(*pos2))\r
- *pos++=*pos2;\r
- *pos=0;\r
- m_serialized.push_back(reinterpret_cast<char*>(enc));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
- XMLString::release(&enc);
-#else
- XMLString::release((char**)&enc);
-#endif
- }
- }
- }
- return Attribute::getSerializedValues();
-}
#ifndef __shibsp_attribute_h__
#define __shibsp_attribute_h__
-#include <shibsp/exceptions.h>
#include <shibsp/remoting/ddf.h>
#include <map>
*
* @param ids array with primary identifier in first position, followed by any aliases
*/
- Attribute(const std::vector<std::string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false) {
- }
+ Attribute(const std::vector<std::string>& ids);
/**
* Constructs based on a remoted Attribute.
mutable std::vector<std::string> m_serialized;
public:
- virtual ~Attribute() {}
+ virtual ~Attribute();
/**
* Returns the Attribute identifier.
*
* @return the Attribute identifier
*/
- const char* getId() const {
- return m_id.front().c_str();
- }
+ const char* getId() const;
/**
* Returns all of the effective names for the Attribute.
*
* @return immutable array of identifiers, with the primary ID in the first position
*/
- const std::vector<std::string>& getAliases() const {
- return m_id;
- }
+ const std::vector<std::string>& getAliases() const;
/**
* Returns all of the effective names for the Attribute.
*
* @return mutable array of identifiers, with the primary ID in the first position
*/
- std::vector<std::string>& getAliases() {
- return m_id;
- }
+ std::vector<std::string>& getAliases();
/**
* Sets whether case sensitivity should apply to basic value comparisons.
*
* @param caseSensitive true iff value comparisons should be case sensitive
*/
- void setCaseSensitive(bool caseSensitive) {
- m_caseSensitive = caseSensitive;
- }
+ void setCaseSensitive(bool caseSensitive);
/**
* Sets whether the attribute should be exported for CGI use.
*
* @param export true iff the attribute should <strong>NOT</strong> be exported
*/
- void setInternal(bool internal) {
- m_internal = internal;
- }
+ void setInternal(bool internal);
/**
* Indicates whether case sensitivity should apply to basic value comparisons.
*
* @return true iff value comparisons should be case sensitive
*/
- bool isCaseSensitive() const {
- return m_caseSensitive;
- }
+ bool isCaseSensitive() const;
/**
* Indicates whether the attribute should be exported for CGI use.
*
* @return true iff the attribute should <strong>NOT</strong> be exported
*/
- bool isInternal() const {
- return m_internal;
- }
+ bool isInternal() const;
/**
* Returns the number of values.
*
* @return number of values
*/
- virtual size_t valueCount() const {
- return m_serialized.size();
- }
+ virtual size_t valueCount() const;
/**
* Returns serialized Attribute values encoded as UTF-8 strings.
*
* @return an immutable vector of values
*/
- virtual const std::vector<std::string>& getSerializedValues() const {
- return m_serialized;
- }
+ virtual const std::vector<std::string>& getSerializedValues() const;
/**
* Informs the Attribute that values have changed and any serializations
* @param index position of value
* @return the specified value in its "string" form, or NULL if undefined
*/
- virtual const char* getString(size_t index) const {
- return m_serialized[index].c_str();
- }
+ virtual const char* getString(size_t index) const;
/**
* Gets the "scope" of the value at the specified position (starting from zero).
* @param index position of value
* @return the specified value's "scope", or NULL if attribute is unscoped
*/
- virtual const char* getScope(size_t index) const {
- return NULL;
- }
+ virtual const char* getScope(size_t index) const;
/**
* Removes the value at the specified position (starting from zero).
*
* @param index position of value to remove
*/
- virtual void removeValue(size_t index) {
- if (index < m_serialized.size())
- m_serialized.erase(m_serialized.begin() + index);
- }
+ virtual void removeValue(size_t index);
/**
* Marshalls an Attribute for remoting.
* @param type string used at the root of remoted Attribute structures
* @param factory factory function
*/
- static void registerFactory(const char* type, AttributeFactory* factory) {
- m_factoryMap[type] = factory;
- }
+ static void registerFactory(const char* type, AttributeFactory* factory);
/**
* Deregisters an AttributeFactory function for a given attribute "type".
*
* @param type string used at the root of remoted Attribute structures
*/
- static void deregisterFactory(const char* type) {
- m_factoryMap.erase(type);
- }
+ static void deregisterFactory(const char* type);
/**
* Clears the map of factories.
*/
- static void deregisterFactories() {
- m_factoryMap.clear();
- }
+ static void deregisterFactories();
private:
static std::map<std::string,AttributeFactory*> m_factoryMap;
#ifndef __shibsp_attrdecoder_h__
#define __shibsp_attrdecoder_h__
-#include <shibsp/attribute/Attribute.h>
-#include <xmltooling/XMLObject.h>
+#include <shibsp/base.h>
+
+#include <string>
+#include <vector>
+
+namespace xmltooling {
+ class XMLTOOL_API QName;
+ class XMLTOOL_API XMLObject;
+};
namespace shibsp {
+ class SHIBSP_API Attribute;
+
/**
* Decodes XML objects into resolved Attributes.
*/
/** Flag for hiding attributes from CGI export. */
bool m_internal;
+ /** Hash algorithm to apply to decoded values. */
+ xmltooling::auto_ptr_char m_hashAlg;
+
/**
* Helper method to handle base class decoding housekeeping.
*
* @param attr the new Attribute object being created
* @return the attr parameter
*/
- virtual Attribute* _decode(Attribute* attr) const {
- attr->setCaseSensitive(m_caseSensitive);
- attr->setInternal(m_internal);
- return attr;
- }
+ virtual Attribute* _decode(Attribute* attr) const;
public:
- virtual ~AttributeDecoder() {}
+ virtual ~AttributeDecoder();
/**
* Decodes an XMLObject into a resolved Attribute.
-/*\r
- * Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * DOMAttributeDecoder.cpp\r
- *\r
- * Decodes a DOM into an ExtensibleAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/ExtensibleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
- class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder\r
- {\r
- public:\r
- DOMAttributeDecoder(const DOMElement* e);\r
- ~DOMAttributeDecoder() {}\r
-\r
- Attribute* decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
- ) const;\r
-\r
- private:\r
- DDF convert(DOMElement* e, bool nameit=true) const;\r
- auto_ptr_char m_formatter;\r
- map<pair<xstring,xstring>,string> m_tagMap;\r
- };\r
-\r
- AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)\r
- {\r
- return new DOMAttributeDecoder(e);\r
- }\r
-\r
- static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g);\r
- static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m);\r
- static const XMLCh _to[] = UNICODE_LITERAL_2(t,o);\r
- static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
-};\r
-\r
-DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)\r
- : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)\r
-{\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
-\r
- e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;\r
- while (e) {\r
- if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {\r
- auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));\r
- auto_ptr_char t(e->getAttributeNS(NULL, _to));\r
- if (f.get() && t.get() && *t.get()) {\r
- if (log.isDebugEnabled())\r
- log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());\r
- m_tagMap.insert(\r
- pair< const pair<xstring,xstring>,string>(\r
- pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),\r
- t.get()\r
- )\r
- );\r
- }\r
- }\r
- e = XMLHelper::getNextSiblingElement(e, Mapping);\r
- }\r
-}\r
-\r
-Attribute* DOMAttributeDecoder::decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
-\r
- if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
- log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
-\r
- auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));\r
- DDF dest = attr->getValues();\r
- vector<XMLObject*>::const_iterator v,stop;\r
-\r
- const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
- if (saml2attr) {\r
- const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml2attr->getName());\r
- log.debug(\r
- "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
- if (saml1attr) {\r
- const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml1attr->getAttributeName());\r
- log.debug(\r
- "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- for (; v!=stop; ++v) {\r
- DOMElement* e = (*v)->getDOM();\r
- if (e) {\r
- DDF converted = convert(e, false);\r
- if (!converted.isnull())\r
- dest.add(converted);\r
- }\r
- else\r
- log.warn("skipping AttributeValue without a backing DOM");\r
- }\r
-\r
- return dest.integer() ? _decode(attr.release()) : NULL;\r
-}\r
-\r
-DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const\r
-{\r
- const XMLCh* nsURI;\r
- const XMLCh* local;\r
- map<pair<xstring,xstring>,string>::const_iterator mapping;\r
- DDF obj = DDF(NULL).structure();\r
-\r
- if (nameit) {\r
- // Name this structure.\r
- nsURI = e->getNamespaceURI();\r
- local = e->getLocalName();\r
- mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));\r
- if (mapping == m_tagMap.end()) {\r
- auto_ptr_char temp(local);\r
- obj.name(temp.get());\r
- }\r
- else {\r
- obj.name(mapping->second.c_str());\r
- }\r
- }\r
-\r
- // Process non-xmlns attributes.\r
- DOMNamedNodeMap* attrs = e->getAttributes();\r
- for (XMLSize_t a = attrs->getLength(); a > 0; --a) {\r
- DOMNode* attr = attrs->item(a-1);\r
- nsURI = attr->getNamespaceURI();\r
- if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))\r
- continue;\r
- local = attr->getLocalName();\r
- mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));\r
- if (mapping == m_tagMap.end()) {\r
- auto_ptr_char temp(local);\r
- obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);\r
- }\r
- else {\r
- obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);\r
- }\r
- }\r
-\r
- DOMElement* child = XMLHelper::getFirstChildElement(e);\r
- if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {\r
- // Attach a _text member if a text node is present.\r
- obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);\r
- }\r
- else {\r
- while (child) {\r
- // Convert the child element.\r
- DDF converted = convert(child);\r
- if (!converted.isnull()) {\r
- // Now identify it and attach it.\r
- if (obj[converted.name()].isnull()) {\r
- // We're a new child, so just attach as a structure member.\r
- obj.add(converted);\r
- }\r
- else if (obj[converted.name()].islist()) {\r
- // We're already a repeating child, so add it to the list.\r
- obj[converted.name()].add(converted);\r
- }\r
- else if (obj[converted.name()].isstruct()) {\r
- // This is the complex case where we see a child for the second\r
- // time and have to convert a structure member into a named list.\r
- DDF newlist = DDF(converted.name()).list();\r
- newlist.add(obj[converted.name()].remove());\r
- newlist.add(converted);\r
- obj.add(newlist);\r
- }\r
- }\r
- child = XMLHelper::getNextSiblingElement(child);\r
- }\r
- }\r
-\r
- // If we're empty, just delete.\r
- if (obj.integer() == 0)\r
- obj.destroy();\r
- return obj;\r
-}\r
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * DOMAttributeDecoder.cpp
+ *
+ * Decodes a DOM into an ExtensibleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/ExtensibleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ DOMAttributeDecoder(const DOMElement* e);
+ ~DOMAttributeDecoder() {}
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ DDF convert(DOMElement* e, bool nameit=true) const;
+ auto_ptr_char m_formatter;
+ map<pair<xstring,xstring>,string> m_tagMap;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new DOMAttributeDecoder(e);
+ }
+
+ static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+ static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m);
+ static const XMLCh _to[] = UNICODE_LITERAL_2(t,o);
+ static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)
+ : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+ e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;
+ while (e) {
+ if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {
+ auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));
+ auto_ptr_char t(e->getAttributeNS(NULL, _to));
+ if (f.get() && t.get() && *t.get()) {
+ if (log.isDebugEnabled())
+ log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());
+ m_tagMap.insert(
+ pair< const pair<xstring,xstring>,string>(
+ pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),
+ t.get()
+ )
+ );
+ }
+ }
+ e = XMLHelper::getNextSiblingElement(e, Mapping);
+ }
+}
+
+Attribute* DOMAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+ return NULL;
+ }
+
+ auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));
+ DDF dest = attr->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ DOMElement* e = (*v)->getDOM();
+ if (e) {
+ DDF converted = convert(e, false);
+ if (!converted.isnull())
+ dest.add(converted);
+ }
+ else
+ log.warn("skipping AttributeValue without a backing DOM");
+ }
+
+ return dest.integer() ? _decode(attr.release()) : NULL;
+}
+
+DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const
+{
+ const XMLCh* nsURI;
+ const XMLCh* local;
+ map<pair<xstring,xstring>,string>::const_iterator mapping;
+ DDF obj = DDF(NULL).structure();
+
+ if (nameit) {
+ // Name this structure.
+ nsURI = e->getNamespaceURI();
+ local = e->getLocalName();
+ mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));
+ if (mapping == m_tagMap.end()) {
+ auto_ptr_char temp(local);
+ obj.name(temp.get());
+ }
+ else {
+ obj.name(mapping->second.c_str());
+ }
+ }
+
+ // Process non-xmlns attributes.
+ DOMNamedNodeMap* attrs = e->getAttributes();
+ for (XMLSize_t a = attrs->getLength(); a > 0; --a) {
+ DOMNode* attr = attrs->item(a-1);
+ nsURI = attr->getNamespaceURI();
+ if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))
+ continue;
+ local = attr->getLocalName();
+ mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));
+ if (mapping == m_tagMap.end()) {
+ auto_ptr_char temp(local);
+ obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);
+ }
+ else {
+ obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);
+ }
+ }
+
+ DOMElement* child = XMLHelper::getFirstChildElement(e);
+ if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {
+ // Attach a _text member if a text node is present.
+ obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);
+ }
+ else {
+ while (child) {
+ // Convert the child element.
+ DDF converted = convert(child);
+ if (!converted.isnull()) {
+ // Now identify it and attach it.
+ if (obj[converted.name()].isnull()) {
+ // We're a new child, so just attach as a structure member.
+ obj.add(converted);
+ }
+ else if (obj[converted.name()].islist()) {
+ // We're already a repeating child, so add it to the list.
+ obj[converted.name()].add(converted);
+ }
+ else if (obj[converted.name()].isstruct()) {
+ // This is the complex case where we see a child for the second
+ // time and have to convert a structure member into a named list.
+ DDF newlist = DDF(converted.name()).list();
+ newlist.add(obj[converted.name()].remove());
+ newlist.add(converted);
+ obj.add(newlist);
+ }
+ }
+ child = XMLHelper::getNextSiblingElement(child);
+ }
+ }
+
+ // If we're empty, just delete.
+ if (obj.integer() == 0)
+ obj.destroy();
+ return obj;
+}
using namespace xmltooling;
using namespace std;
+namespace shibsp {
+ SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
+ return new ExtensibleAttribute(in);
+ }
+};
+
+ExtensibleAttribute::ExtensibleAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids)
+{
+ m_obj = Attribute::marshall();
+ m_obj.name("Extensible");
+ m_obj.addmember("_formatter").string(formatter);
+}
+
+ExtensibleAttribute::ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy())
+{
+}
+
+ExtensibleAttribute::~ExtensibleAttribute()
+{
+ m_obj.destroy();
+}
+
+DDF ExtensibleAttribute::getValues()
+{
+ return m_obj.first();
+}
+
+size_t ExtensibleAttribute::valueCount() const
+{
+ return m_obj.first().integer();
+}
+
+void ExtensibleAttribute::clearSerializedValues()
+{
+ m_serialized.clear();
+}
+
+const char* ExtensibleAttribute::getString(size_t index) const
+{
+ return m_obj.first()[static_cast<unsigned long>(index)].string();
+}
+
+const char* ExtensibleAttribute::getScope(size_t index) const
+{
+ return NULL;
+}
+
+void ExtensibleAttribute::removeValue(size_t index)
+{
+ Attribute::removeValue(index);
+ DDF vals = m_obj.first();
+ if (index < static_cast<size_t>(vals.integer()))
+ vals[static_cast<unsigned long>(index)].remove().destroy();
+}
+
const vector<string>& ExtensibleAttribute::getSerializedValues() const
{
if (m_serialized.empty()) {
}
return Attribute::getSerializedValues();
}
+
+DDF ExtensibleAttribute::marshall() const
+{
+ if (!isCaseSensitive())
+ m_obj.addmember("case_insensitive");
+ if (isInternal())
+ m_obj.addmember("internal");
+ return m_obj.copy();
+}
#define __shibsp_extattr_h__
#include <shibsp/attribute/Attribute.h>
-#include <xmltooling/exceptions.h>
namespace shibsp {
* @param ids array with primary identifier in first position, followed by any aliases
* @param formatter template for serialization of values
*/
- ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter) : Attribute(ids) {
- m_obj = Attribute::marshall();
- m_obj.name("Extensible");
- m_obj.addmember("_formatter").string(formatter);
- }
+ ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter);
/**
* Constructs based on a remoted ExtensibleAttribute.
*
* @param in input object containing marshalled ExtensibleAttribute
*/
- ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy()) {
- }
+ ExtensibleAttribute(DDF& in);
- virtual ~ExtensibleAttribute() {
- m_obj.destroy();
- }
+ virtual ~ExtensibleAttribute();
/**
* Returns the set of values in a DDF list.
*
* @return a mutable list object containing the values
*/
- DDF getValues() {
- return m_obj.first();
- }
-
- size_t valueCount() const {
- return m_obj.first().integer();
- }
-
- void clearSerializedValues() {
- m_serialized.clear();
- }
-
- const char* getString(size_t index) const {
- return m_obj.first()[static_cast<unsigned long>(index)].string();
- }
-
- const char* getScope(size_t index) const {
- return NULL;
- }
-
- void removeValue(size_t index) {
- Attribute::removeValue(index);
- DDF vals = m_obj.first();
- if (index < static_cast<size_t>(vals.integer()))
- vals[static_cast<unsigned long>(index)].remove().destroy();
- }
-
+ DDF getValues();
+
+ // Virtual function overrides.
+ size_t valueCount() const;
+ void clearSerializedValues();
+ const char* getString(size_t index) const;
+ const char* getScope(size_t index) const;
+ void removeValue(size_t index);
const std::vector<std::string>& getSerializedValues() const;
-
- DDF marshall() const {
- if (!isCaseSensitive())
- m_obj.addmember("case_insensitive");
- if (isInternal())
- m_obj.addmember("internal");
- return m_obj.copy();
- }
+ DDF marshall() const;
private:
mutable DDF m_obj;
-/*\r
- * Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * KeyInfoAttributeDecoder.cpp\r
- *\r
- * Decodes KeyInfo information into a SimpleAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/SimpleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/security/SecurityHelper.h>\r
-#include <xmltooling/signature/KeyInfo.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmlsignature;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
- class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder\r
- {\r
- public:\r
- KeyInfoAttributeDecoder(const DOMElement* e);\r
- ~KeyInfoAttributeDecoder() {\r
- delete m_keyInfoResolver;\r
- }\r
-\r
- Attribute* decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
- ) const;\r
-\r
- private:\r
- void extract(const KeyInfo* k, vector<string>& dest) const {\r
- auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));\r
- if (cred.get()) {\r
- dest.push_back(string());\r
- dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash);\r
- if (dest.back().empty())\r
- dest.pop_back();\r
- }\r
- }\r
-\r
- const KeyInfoResolver* getKeyInfoResolver() const {\r
- return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();\r
- }\r
-\r
- bool m_hash;\r
- KeyInfoResolver* m_keyInfoResolver;\r
- };\r
-\r
- AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)\r
- {\r
- return new KeyInfoAttributeDecoder(e);\r
- }\r
-\r
- static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);\r
- static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h);\r
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);\r
-};\r
-\r
-KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {\r
- const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;\r
- m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
- e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;\r
- if (e) {\r
- auto_ptr_char t(e->getAttributeNS(NULL, _type));\r
- if (t.get() && *t.get())\r
- m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);\r
- else\r
- throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");\r
- }\r
-}\r
-\r
-Attribute* KeyInfoAttributeDecoder::decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");\r
-\r
- if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
- log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
-\r
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));\r
- vector<string>& dest = attr->getValues();\r
- vector<XMLObject*>::const_iterator v,stop;\r
-\r
- const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
- if (saml2attr) {\r
- const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml2attr->getName());\r
- log.debug(\r
- "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
- if (saml1attr) {\r
- const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml1attr->getAttributeName());\r
- log.debug(\r
- "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- for (; v!=stop; ++v) {\r
- const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);\r
- if (k)\r
- extract(k, dest);\r
- else if ((*v)->hasChildren()) {\r
- const list<XMLObject*>& children = (*v)->getOrderedChildren();\r
- for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {\r
- if (k=dynamic_cast<const KeyInfo*>(*vv))\r
- extract(k, dest);\r
- else\r
- log.warn("skipping AttributeValue without a recognizable KeyInfo");\r
- }\r
- }\r
- }\r
-\r
- return dest.empty() ? NULL : _decode(attr.release());\r
-}\r
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * KeyInfoAttributeDecoder.cpp
+ *
+ * Decodes KeyInfo information into a SimpleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/Credential.h>
+#include <xmltooling/security/KeyInfoResolver.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/signature/KeyInfo.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ KeyInfoAttributeDecoder(const DOMElement* e);
+ ~KeyInfoAttributeDecoder() {
+ delete m_keyInfoResolver;
+ }
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ void extract(const KeyInfo* k, vector<string>& dest) const {
+ auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+ if (cred.get()) {
+ const char* alg = m_keyInfoHashAlg.get();
+ if (!alg || !*alg)
+ alg = "SHA1";
+ dest.push_back(string());
+ dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash ? alg : NULL);
+ if (dest.back().empty())
+ dest.pop_back();
+ }
+ }
+
+ const KeyInfoResolver* getKeyInfoResolver() const {
+ return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+ }
+
+ bool m_hash;
+ auto_ptr_char m_keyInfoHashAlg;
+ KeyInfoResolver* m_keyInfoResolver;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new KeyInfoAttributeDecoder(e);
+ }
+
+ static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);
+ static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h);
+ static const XMLCh keyInfoHashAlg[] = UNICODE_LITERAL_14(k,e,y,I,n,f,o,H,a,s,h,A,l,g);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+};
+
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e)
+ : AttributeDecoder(e),
+ m_hash(false),
+ m_keyInfoHashAlg(e ? e->getAttributeNS(NULL, keyInfoHashAlg) : NULL),
+ m_keyInfoResolver(NULL) {
+ const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;
+ m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+ e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;
+ if (e) {
+ auto_ptr_char t(e->getAttributeNS(NULL, _type));
+ if (t.get() && *t.get())
+ m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);
+ else
+ throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
+ }
+}
+
+Attribute* KeyInfoAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");
+
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+ return NULL;
+ }
+
+ auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));
+ vector<string>& dest = attr->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);
+ if (k)
+ extract(k, dest);
+ else if ((*v)->hasChildren()) {
+ const list<XMLObject*>& children = (*v)->getOrderedChildren();
+ for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+ if (k=dynamic_cast<const KeyInfo*>(*vv))
+ extract(k, dest);
+ else
+ log.warn("skipping AttributeValue without a recognizable KeyInfo");
+ }
+ }
+ }
+
+ return dest.empty() ? NULL : _decode(attr.release());
+}
--- /dev/null
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * NameIDAttribute.cpp
+ *
+ * An Attribute whose values are derived from or mappable to a SAML NameID.
+ */
+
+#include "internal.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <xmltooling/exceptions.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in) {
+ return new NameIDAttribute(in);
+ }
+};
+
+NameIDAttribute::NameIDAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids), m_formatter(formatter)
+{
+}
+
+NameIDAttribute::NameIDAttribute(DDF& in) : Attribute(in)
+{
+ DDF val = in["_formatter"];
+ if (val.isstring())
+ m_formatter = val.string();
+ else
+ m_formatter = DEFAULT_NAMEID_FORMATTER;
+ const char* pch;
+ val = in.first().first();
+ while (val.name()) {
+ m_values.push_back(Value());
+ Value& v = m_values.back();
+ v.m_Name = val.name();
+ pch = val["Format"].string();
+ if (pch)
+ v.m_Format = pch;
+ pch = val["NameQualifier"].string();
+ if (pch)
+ v.m_NameQualifier = pch;
+ pch = val["SPNameQualifier"].string();
+ if (pch)
+ v.m_SPNameQualifier = pch;
+ pch = val["SPProvidedID"].string();
+ if (pch)
+ v.m_SPProvidedID = pch;
+ val = in.first().next();
+ }
+}
+
+NameIDAttribute::~NameIDAttribute()
+{
+}
+
+vector<NameIDAttribute::Value>& NameIDAttribute::getValues()
+{
+ return m_values;
+}
+
+const vector<NameIDAttribute::Value>& NameIDAttribute::getValues() const
+{
+ return m_values;
+}
+
+size_t NameIDAttribute::valueCount() const
+{
+ return m_values.size();
+}
+
+void NameIDAttribute::clearSerializedValues()
+{
+ m_serialized.clear();
+}
+
+const char* NameIDAttribute::getString(size_t index) const
+{
+ return m_values[index].m_Name.c_str();
+}
+
+const char* NameIDAttribute::getScope(size_t index) const
+{
+ return m_values[index].m_NameQualifier.c_str();
+}
+
+void NameIDAttribute::removeValue(size_t index)
+{
+ Attribute::removeValue(index);
+ if (index < m_values.size())
+ m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& NameIDAttribute::getSerializedValues() const
+{
+ if (m_serialized.empty()) {
+ for (vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+ // This is kind of a hack, but it's a good way to reuse some code.
+ XMLToolingException e(
+ m_formatter,
+ namedparams(
+ 5,
+ "Name", i->m_Name.c_str(),
+ "Format", i->m_Format.c_str(),
+ "NameQualifier", i->m_NameQualifier.c_str(),
+ "SPNameQualifier", i->m_SPNameQualifier.c_str(),
+ "SPProvidedID", i->m_SPProvidedID.c_str()
+ )
+ );
+ m_serialized.push_back(e.what());
+ }
+ }
+ return Attribute::getSerializedValues();
+}
+
+DDF NameIDAttribute::marshall() const
+{
+ DDF ddf = Attribute::marshall();
+ ddf.name("NameID");
+ ddf.addmember("_formatter").string(m_formatter.c_str());
+ DDF vlist = ddf.first();
+ for (vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+ DDF val = DDF(i->m_Name.c_str()).structure();
+ if (!i->m_Format.empty())
+ val.addmember("Format").string(i->m_Format.c_str());
+ if (!i->m_NameQualifier.empty())
+ val.addmember("NameQualifier").string(i->m_NameQualifier.c_str());
+ if (!i->m_SPNameQualifier.empty())
+ val.addmember("SPNameQualifier").string(i->m_SPNameQualifier.c_str());
+ if (!i->m_SPProvidedID.empty())
+ val.addmember("SPProvidedID").string(i->m_SPProvidedID.c_str());
+ vlist.add(val);
+ }
+ return ddf;
+}
#define __shibsp_nameidattr_h__
#include <shibsp/attribute/Attribute.h>
-#include <xmltooling/exceptions.h>
namespace shibsp {
* @param ids array with primary identifier in first position, followed by any aliases
* @param formatter template for serialization of tuple
*/
- NameIDAttribute(const std::vector<std::string>& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER)
- : Attribute(ids), m_formatter(formatter) {
- }
+ NameIDAttribute(const std::vector<std::string>& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER);
/**
* Constructs based on a remoted NameIDAttribute.
*
* @param in input object containing marshalled NameIDAttribute
*/
- NameIDAttribute(DDF& in) : Attribute(in) {
- DDF val = in["_formatter"];
- if (val.isstring())
- m_formatter = val.string();
- else
- m_formatter = DEFAULT_NAMEID_FORMATTER;
- const char* pch;
- val = in.first().first();
- while (val.name()) {
- m_values.push_back(Value());
- Value& v = m_values.back();
- v.m_Name = val.name();
- pch = val["Format"].string();
- if (pch)
- v.m_Format = pch;
- pch = val["NameQualifier"].string();
- if (pch)
- v.m_NameQualifier = pch;
- pch = val["SPNameQualifier"].string();
- if (pch)
- v.m_SPNameQualifier = pch;
- pch = val["SPProvidedID"].string();
- if (pch)
- v.m_SPProvidedID = pch;
- val = in.first().next();
- }
- }
+ NameIDAttribute(DDF& in);
- virtual ~NameIDAttribute() {}
+ virtual ~NameIDAttribute();
/**
* Holds all the fields associated with a NameID.
*
* @return a mutable vector of the values
*/
- std::vector<Value>& getValues() {
- return m_values;
- }
+ std::vector<Value>& getValues();
/**
* Returns the set of values encoded as UTF-8 strings.
*
* @return an immutable vector of the values
*/
- const std::vector<Value>& getValues() const {
- return m_values;
- }
-
- size_t valueCount() const {
- return m_values.size();
- }
-
- void clearSerializedValues() {
- m_serialized.clear();
- }
-
- const char* getString(size_t index) const {
- return m_values[index].m_Name.c_str();
- }
-
- const char* getScope(size_t index) const {
- return m_values[index].m_NameQualifier.c_str();
- }
-
- void removeValue(size_t index) {
- Attribute::removeValue(index);
- if (index < m_values.size())
- m_values.erase(m_values.begin() + index);
- }
-
- const std::vector<std::string>& getSerializedValues() const {
- if (m_serialized.empty()) {
- for (std::vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
- // This is kind of a hack, but it's a good way to reuse some code.
- xmltooling::XMLToolingException e(
- m_formatter,
- xmltooling::namedparams(
- 5,
- "Name", i->m_Name.c_str(),
- "Format", i->m_Format.c_str(),
- "NameQualifier", i->m_NameQualifier.c_str(),
- "SPNameQualifier", i->m_SPNameQualifier.c_str(),
- "SPProvidedID", i->m_SPProvidedID.c_str()
- )
- );
- m_serialized.push_back(e.what());
- }
- }
- return Attribute::getSerializedValues();
- }
-
- DDF marshall() const {
- DDF ddf = Attribute::marshall();
- ddf.name("NameID");
- ddf.addmember("_formatter").string(m_formatter.c_str());
- DDF vlist = ddf.first();
- for (std::vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
- DDF val = DDF(i->m_Name.c_str()).structure();
- if (!i->m_Format.empty())
- val.addmember("Format").string(i->m_Format.c_str());
- if (!i->m_NameQualifier.empty())
- val.addmember("NameQualifier").string(i->m_NameQualifier.c_str());
- if (!i->m_SPNameQualifier.empty())
- val.addmember("SPNameQualifier").string(i->m_SPNameQualifier.c_str());
- if (!i->m_SPProvidedID.empty())
- val.addmember("SPProvidedID").string(i->m_SPProvidedID.c_str());
- vlist.add(val);
- }
- return ddf;
- }
+ const std::vector<Value>& getValues() const;
+
+ // Virtual function overrides.
+ size_t valueCount() const;
+ void clearSerializedValues();
+ const char* getString(size_t index) const;
+ const char* getScope(size_t index) const;
+ void removeValue(size_t index);
+ const std::vector<std::string>& getSerializedValues() const;
+ DDF marshall() const;
private:
std::vector<Value> m_values;
-/*\r
- * Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * NameIDAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into NameIDAttributes\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/NameIDAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
- static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
- static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);\r
-\r
- class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder\r
- {\r
- public:\r
- NameIDAttributeDecoder(const DOMElement* e)\r
- : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {\r
- const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;\r
- if (flag && (*flag == chLatin_t || *flag == chDigit_1))\r
- m_defaultQualifiers = true;\r
- }\r
- ~NameIDAttributeDecoder() {}\r
-\r
- shibsp::Attribute* decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
- ) const;\r
-\r
- private:\r
- void extract(\r
- const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
- ) const;\r
- void extract(\r
- const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
- ) const;\r
- auto_ptr_char m_formatter;\r
- bool m_defaultQualifiers;\r
- };\r
-\r
- AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)\r
- {\r
- return new NameIDAttributeDecoder(e);\r
- }\r
-};\r
-\r
-shibsp::Attribute* NameIDAttributeDecoder::decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- auto_ptr<NameIDAttribute> nameid(\r
- new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
- );\r
- vector<NameIDAttribute::Value>& dest = nameid->getValues();\r
- vector<XMLObject*>::const_iterator v,stop;\r
-\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");\r
-\r
- if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
- const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
- if (saml2attr) {\r
- const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml2attr->getName());\r
- log.debug(\r
- "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
- if (saml1attr) {\r
- const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml1attr->getAttributeName());\r
- log.debug(\r
- "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- for (; v!=stop; ++v) {\r
- const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);\r
- if (n2)\r
- extract(n2, dest, assertingParty, relyingParty);\r
- else {\r
- const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);\r
- if (n1)\r
- extract(n1, dest, assertingParty, relyingParty);\r
- else if ((*v)->hasChildren()) {\r
- const list<XMLObject*>& values = (*v)->getOrderedChildren();\r
- for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {\r
- if (n2=dynamic_cast<const NameIDType*>(*vv))\r
- extract(n2, dest, assertingParty, relyingParty);\r
- else if (n1=dynamic_cast<const NameIdentifier*>(*vv))\r
- extract(n1, dest, assertingParty, relyingParty);\r
- else\r
- log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");\r
- }\r
- }\r
- }\r
- }\r
-\r
- return dest.empty() ? NULL : _decode(nameid.release());\r
- }\r
-\r
- const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);\r
- if (saml2name) {\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char f(saml2name->getFormat());\r
- log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
- }\r
- extract(saml2name, dest, assertingParty, relyingParty);\r
- }\r
- else {\r
- const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
- if (saml1name) {\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char f(saml1name->getFormat());\r
- log.debug(\r
- "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
- ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
- );\r
- }\r
- extract(saml1name, dest, assertingParty, relyingParty);\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- return dest.empty() ? NULL : _decode(nameid.release());\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
- const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- auto_arrayptr<char> name(toUTF8(n->getName()));\r
- if (name.get() && *name.get()) {\r
- dest.push_back(NameIDAttribute::Value());\r
- NameIDAttribute::Value& val = dest.back();\r
- val.m_Name = name.get();\r
- char* str = toUTF8(n->getFormat());\r
- if (str) {\r
- val.m_Format = str;\r
- delete[] str;\r
- }\r
-\r
- str = toUTF8(n->getNameQualifier());\r
- if (str && *str)\r
- val.m_NameQualifier = str;\r
- else if (m_defaultQualifiers && assertingParty)\r
- val.m_NameQualifier = assertingParty;\r
- delete[] str;\r
-\r
- str = toUTF8(n->getSPNameQualifier());\r
- if (str && *str)\r
- val.m_SPNameQualifier = str;\r
- else if (m_defaultQualifiers && relyingParty)\r
- val.m_SPNameQualifier = relyingParty;\r
- delete[] str;\r
-\r
- str = toUTF8(n->getSPProvidedID());\r
- if (str) {\r
- val.m_SPProvidedID = str;\r
- delete[] str;\r
- }\r
- }\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
- const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- auto_arrayptr<char> name(toUTF8(n->getName()));\r
- if (name.get() && *name.get()) {\r
- dest.push_back(NameIDAttribute::Value());\r
- NameIDAttribute::Value& val = dest.back();\r
- val.m_Name = name.get();\r
- char* str = toUTF8(n->getFormat());\r
- if (str) {\r
- val.m_Format = str;\r
- delete[] str;\r
- }\r
-\r
- str = toUTF8(n->getNameQualifier());\r
- if (str && *str)\r
- val.m_NameQualifier = str;\r
- else if (m_defaultQualifiers && assertingParty)\r
- val.m_NameQualifier = assertingParty;\r
- delete[] str;\r
-\r
- if (m_defaultQualifiers && relyingParty)\r
- val.m_SPNameQualifier = relyingParty;\r
- }\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * NameIDAttributeDecoder.cpp
+ *
+ * Decodes SAML into NameIDAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+ static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);
+
+ class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ NameIDAttributeDecoder(const DOMElement* e)
+ : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {
+ const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;
+ if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+ m_defaultQualifiers = true;
+ }
+ ~NameIDAttributeDecoder() {}
+
+ shibsp::Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ void extract(
+ const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+ ) const;
+ void extract(
+ const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+ ) const;
+ auto_ptr_char m_formatter;
+ bool m_defaultQualifiers;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new NameIDAttributeDecoder(e);
+ }
+};
+
+shibsp::Attribute* NameIDAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ auto_ptr<NameIDAttribute> nameid(
+ new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
+ );
+ vector<NameIDAttribute::Value>& dest = nameid->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");
+
+ if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+ const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);
+ if (n2)
+ extract(n2, dest, assertingParty, relyingParty);
+ else {
+ const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);
+ if (n1)
+ extract(n1, dest, assertingParty, relyingParty);
+ else if ((*v)->hasChildren()) {
+ const list<XMLObject*>& values = (*v)->getOrderedChildren();
+ for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {
+ if (n2=dynamic_cast<const NameIDType*>(*vv))
+ extract(n2, dest, assertingParty, relyingParty);
+ else if (n1=dynamic_cast<const NameIdentifier*>(*vv))
+ extract(n1, dest, assertingParty, relyingParty);
+ else
+ log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");
+ }
+ }
+ }
+ }
+
+ return dest.empty() ? NULL : _decode(nameid.release());
+ }
+
+ const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);
+ if (saml2name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml2name->getFormat());
+ log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+ }
+ extract(saml2name, dest, assertingParty, relyingParty);
+ }
+ else {
+ const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+ if (saml1name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml1name->getFormat());
+ log.debug(
+ "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+ ids.front().c_str(), f.get() ? f.get() : "unspecified"
+ );
+ }
+ extract(saml1name, dest, assertingParty, relyingParty);
+ }
+ else {
+ log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ return dest.empty() ? NULL : _decode(nameid.release());
+}
+
+void NameIDAttributeDecoder::extract(
+ const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ auto_arrayptr<char> name(toUTF8(n->getName()));
+ if (name.get() && *name.get()) {
+ dest.push_back(NameIDAttribute::Value());
+ NameIDAttribute::Value& val = dest.back();
+ val.m_Name = name.get();
+ char* str = toUTF8(n->getFormat());
+ if (str) {
+ val.m_Format = str;
+ delete[] str;
+ }
+
+ str = toUTF8(n->getNameQualifier());
+ if (str && *str)
+ val.m_NameQualifier = str;
+ else if (m_defaultQualifiers && assertingParty)
+ val.m_NameQualifier = assertingParty;
+ delete[] str;
+
+ str = toUTF8(n->getSPNameQualifier());
+ if (str && *str)
+ val.m_SPNameQualifier = str;
+ else if (m_defaultQualifiers && relyingParty)
+ val.m_SPNameQualifier = relyingParty;
+ delete[] str;
+
+ str = toUTF8(n->getSPProvidedID());
+ if (str) {
+ val.m_SPProvidedID = str;
+ delete[] str;
+ }
+ }
+}
+
+void NameIDAttributeDecoder::extract(
+ const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ auto_arrayptr<char> name(toUTF8(n->getName()));
+ if (name.get() && *name.get()) {
+ dest.push_back(NameIDAttribute::Value());
+ NameIDAttribute::Value& val = dest.back();
+ val.m_Name = name.get();
+ char* str = toUTF8(n->getFormat());
+ if (str) {
+ val.m_Format = str;
+ delete[] str;
+ }
+
+ str = toUTF8(n->getNameQualifier());
+ if (str && *str)
+ val.m_NameQualifier = str;
+ else if (m_defaultQualifiers && assertingParty)
+ val.m_NameQualifier = assertingParty;
+ delete[] str;
+
+ if (m_defaultQualifiers && relyingParty)
+ val.m_SPNameQualifier = relyingParty;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ScopedAttribute.cpp
+ *
+ * An Attribute whose values are relations of a value and a scope.
+ */
+
+#include "internal.h"
+#include "attribute/ScopedAttribute.h"
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+ SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in) {
+ return new ScopedAttribute(in);
+ }
+};
+
+ScopedAttribute::ScopedAttribute(const vector<string>& ids, char delimeter) : Attribute(ids), m_delimeter(delimeter)
+{
+}
+
+ScopedAttribute::ScopedAttribute(DDF& in) : Attribute(in), m_delimeter('@')
+{
+ DDF val = in["_delimeter"];
+ if (val.isint())
+ m_delimeter = static_cast<char>(val.integer());
+ val = in.first().first();
+ while (val.name() && val.string()) {
+ m_values.push_back(make_pair(string(val.name()), string(val.string())));
+ val = in.first().next();
+ }
+}
+
+ScopedAttribute::~ScopedAttribute()
+{
+}
+
+vector< pair<string,string> >& ScopedAttribute::getValues()
+{
+ return m_values;
+}
+
+const vector< pair<string,string> >& ScopedAttribute::getValues() const
+{
+ return m_values;
+}
+
+size_t ScopedAttribute::valueCount() const
+{
+ return m_values.size();
+}
+
+void ScopedAttribute::clearSerializedValues()
+{
+ m_serialized.clear();
+}
+
+const char* ScopedAttribute::getString(size_t index) const
+{
+ return m_values[index].first.c_str();
+}
+
+const char* ScopedAttribute::getScope(size_t index) const
+{
+ return m_values[index].second.c_str();
+}
+
+void ScopedAttribute::removeValue(size_t index)
+{
+ Attribute::removeValue(index);
+ if (index < m_values.size())
+ m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& ScopedAttribute::getSerializedValues() const
+{
+ if (m_serialized.empty()) {
+ for (vector< pair<string,string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+ m_serialized.push_back(i->first + m_delimeter + i->second);
+ }
+ return Attribute::getSerializedValues();
+}
+
+DDF ScopedAttribute::marshall() const
+{
+ DDF ddf = Attribute::marshall();
+ ddf.name("Scoped");
+ if (m_delimeter != '@')
+ ddf.addmember("_delimeter").integer(m_delimeter);
+ DDF vlist = ddf.first();
+ for (vector< pair<string,string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+ DDF val = DDF(i->first.c_str()).string(i->second.c_str());
+ vlist.add(val);
+ }
+ return ddf;
+}
* @param ids array with primary identifier in first position, followed by any aliases
* @param delimeter value/scope delimeter when serializing
*/
- ScopedAttribute(const std::vector<std::string>& ids, char delimeter='@')
- : Attribute(ids), m_delimeter(delimeter) {
- }
+ ScopedAttribute(const std::vector<std::string>& ids, char delimeter='@');
/**
* Constructs based on a remoted ScopedAttribute.
*
* @param in input object containing marshalled ScopedAttribute
*/
- ScopedAttribute(DDF& in) : Attribute(in), m_delimeter('@') {
- DDF val = in["_delimeter"];
- if (val.isint())
- m_delimeter = static_cast<char>(val.integer());
- val = in.first().first();
- while (val.name() && val.string()) {
- m_values.push_back(std::make_pair(std::string(val.name()), std::string(val.string())));
- val = in.first().next();
- }
- }
+ ScopedAttribute(DDF& in);
- virtual ~ScopedAttribute() {}
+ virtual ~ScopedAttribute();
/**
* Returns the set of values encoded as UTF-8 strings.
*
* @return a mutable vector of the values
*/
- std::vector< std::pair<std::string,std::string> >& getValues() {
- return m_values;
- }
+ std::vector< std::pair<std::string,std::string> >& getValues();
/**
* Returns the set of values encoded as UTF-8 strings.
*
* @return an immutable vector of the values
*/
- const std::vector< std::pair<std::string,std::string> >& getValues() const {
- return m_values;
- }
-
- size_t valueCount() const {
- return m_values.size();
- }
-
- void clearSerializedValues() {
- m_serialized.clear();
- }
-
- const char* getString(size_t index) const {
- return m_values[index].first.c_str();
- }
-
- const char* getScope(size_t index) const {
- return m_values[index].second.c_str();
- }
-
- void removeValue(size_t index) {
- Attribute::removeValue(index);
- if (index < m_values.size())
- m_values.erase(m_values.begin() + index);
- }
-
- const std::vector<std::string>& getSerializedValues() const {
- if (m_serialized.empty()) {
- for (std::vector< std::pair<std::string,std::string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
- m_serialized.push_back(i->first + m_delimeter + i->second);
- }
- return Attribute::getSerializedValues();
- }
-
- DDF marshall() const {
- DDF ddf = Attribute::marshall();
- ddf.name("Scoped");
- if (m_delimeter != '@')
- ddf.addmember("_delimeter").integer(m_delimeter);
- DDF vlist = ddf.first();
- for (std::vector< std::pair<std::string,std::string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
- DDF val = DDF(i->first.c_str()).string(i->second.c_str());
- vlist.add(val);
- }
- return ddf;
- }
+ const std::vector< std::pair<std::string,std::string> >& getValues() const;
+
+ // Virtual function overrides.
+ size_t valueCount() const;
+ void clearSerializedValues();
+ const char* getString(size_t index) const;
+ const char* getScope(size_t index) const;
+ void removeValue(size_t index);
+ const std::vector<std::string>& getSerializedValues() const;
+ DDF marshall() const;
private:
char m_delimeter;
/**
* ScopedAttributeDecoder.cpp
*
- * Decodes SAML into ScopedAttributes
+ * Decodes SAML into ScopedAttributes.
*/
#include "internal.h"
namespace shibsp {
static const XMLCh Scope[] = UNICODE_LITERAL_5(S,c,o,p,e);
- static const XMLCh scopeDelimeter[] = UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);
+ static const XMLCh scopeDelimiter[] = UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,i,t,e,r);
class SHIBSP_DLLLOCAL ScopedAttributeDecoder : virtual public AttributeDecoder
{
public:
- ScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@') {
- if (e && e->hasAttributeNS(NULL,scopeDelimeter)) {
- auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));
- m_delimeter = *(d.get());
+ ScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimiter('@') {
+ if (e && e->hasAttributeNS(NULL,scopeDelimiter)) {
+ auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimiter));
+ m_delimiter = *(d.get());
}
}
~ScopedAttributeDecoder() {}
) const;
private:
- char m_delimeter;
+ char m_delimiter;
};
AttributeDecoder* SHIBSP_DLLLOCAL ScopedAttributeDecoderFactory(const DOMElement* const & e)
char* scope;
const XMLCh* xmlscope;
xmltooling::QName scopeqname(NULL,Scope);
- auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimeter));
+ auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimiter));
vector< pair<string,string> >& dest = scoped->getValues();
vector<XMLObject*>::const_iterator v,stop;
delete[] scope;
}
else {
- scope = strchr(val, m_delimeter);
+ scope = strchr(val, m_delimiter);
if (scope) {
*scope++ = 0;
if (*scope)
}
}
- if (val && *val && *val!=m_delimeter) {
- scope = strchr(val, m_delimeter);
+ if (val && *val && *val!=m_delimiter) {
+ scope = strchr(val, m_delimiter);
if (scope) {
*scope++ = 0;
if (*scope)
log.warn("ignoring NameID with no scope");
}
else {
- log.warn("ignoring NameID with no scope delimiter (%c)", m_delimeter);
+ log.warn("ignoring NameID with no scope delimiter (%c)", m_delimiter);
}
}
else {
--- /dev/null
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SimpleAttribute.cpp
+ *
+ * An Attribute whose values are simple strings.
+ */
+
+#include "internal.h"
+#include "attribute/SimpleAttribute.h"
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+ SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in) {
+ return new SimpleAttribute(in);
+ }
+};
+
+SimpleAttribute::SimpleAttribute(const vector<string>& ids) : Attribute(ids)
+{
+}
+
+SimpleAttribute::SimpleAttribute(DDF& in) : Attribute(in)
+{
+ DDF val = in.first().first();
+ while (val.string()) {
+ m_serialized.push_back(val.string());
+ val = in.first().next();
+ }
+}
+
+SimpleAttribute::~SimpleAttribute()
+{
+}
+
+vector<string>& SimpleAttribute::getValues()
+{
+ return m_serialized;
+}
+
+void SimpleAttribute::clearSerializedValues()
+{
+ // Do nothing, since our values are already serialized.
+}
+
+DDF SimpleAttribute::marshall() const
+{
+ DDF ddf = Attribute::marshall();
+ DDF vlist = ddf.first();
+ for (vector<string>::const_iterator i=m_serialized.begin(); i!=m_serialized.end(); ++i)
+ vlist.add(DDF(NULL).string(i->c_str()));
+ return ddf;
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* @param ids array with primary identifier in first position, followed by any aliases
*/
- SimpleAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
+ SimpleAttribute(const std::vector<std::string>& ids);
/**
* Constructs based on a remoted SimpleAttribute.
*
* @param in input object containing marshalled SimpleAttribute
*/
- SimpleAttribute(DDF& in) : Attribute(in) {
- DDF val = in.first().first();
- while (val.string()) {
- m_serialized.push_back(val.string());
- val = in.first().next();
- }
- }
+ SimpleAttribute(DDF& in);
- virtual ~SimpleAttribute() {}
+ virtual ~SimpleAttribute();
/**
* Returns the set of values encoded as UTF-8 strings.
*
* @return a mutable vector of the values
*/
- std::vector<std::string>& getValues() {
- return m_serialized;
- }
+ std::vector<std::string>& getValues();
- void clearSerializedValues() {
- // Do nothing, since our values are already serialized.
- }
-
- DDF marshall() const {
- DDF ddf = Attribute::marshall();
- DDF vlist = ddf.first();
- for (std::vector<std::string>::const_iterator i=m_serialized.begin(); i!=m_serialized.end(); ++i)
- vlist.add(DDF(NULL).string(i->c_str()));
- return ddf;
- }
+ // Virtual function overrides.
+ void clearSerializedValues();
+ DDF marshall() const;
};
};
-/*\r
- * Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * StringAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into SimpleAttributes\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/SimpleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
- class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder\r
- {\r
- public:\r
- StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
- ~StringAttributeDecoder() {}\r
-\r
- shibsp::Attribute* decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
- ) const;\r
- };\r
-\r
- AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)\r
- {\r
- return new StringAttributeDecoder(e);\r
- }\r
-};\r
-\r
-shibsp::Attribute* StringAttributeDecoder::decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- char* val;\r
- auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));\r
- vector<string>& dest = simple->getValues();\r
- vector<XMLObject*>::const_iterator v,stop;\r
-\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");\r
-\r
- if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
- const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
- if (saml2attr) {\r
- const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml2attr->getName());\r
- log.debug(\r
- "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
- if (saml1attr) {\r
- const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml1attr->getAttributeName());\r
- log.debug(\r
- "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- for (; v!=stop; ++v) {\r
- if (!(*v)->hasChildren()) {\r
- val = toUTF8((*v)->getTextContent());\r
- if (val && *val)\r
- dest.push_back(val);\r
- else\r
- log.warn("skipping empty AttributeValue");\r
- delete[] val;\r
- }\r
- else {\r
- log.warn("skipping complex AttributeValue");\r
- }\r
- }\r
-\r
- return dest.empty() ? NULL : _decode(simple.release());\r
- }\r
-\r
- const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
- if (saml2name) {\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char f(saml2name->getFormat());\r
- log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
- }\r
- val = toUTF8(saml2name->getName());\r
- }\r
- else {\r
- const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
- if (saml1name) {\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char f(saml1name->getFormat());\r
- log.debug(\r
- "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
- ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
- );\r
- }\r
- val = toUTF8(saml1name->getName());\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- if (val && *val)\r
- dest.push_back(val);\r
- else\r
- log.warn("ignoring empty NameID");\r
- delete[] val;\r
- return dest.empty() ? NULL : _decode(simple.release());\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * StringAttributeDecoder.cpp
+ *
+ * Decodes SAML into SimpleAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+ ~StringAttributeDecoder() {}
+
+ shibsp::Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new StringAttributeDecoder(e);
+ }
+};
+
+shibsp::Attribute* StringAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ char* val;
+ auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
+ vector<string>& dest = simple->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");
+
+ if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+ const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ if (!(*v)->hasChildren()) {
+ val = toUTF8((*v)->getTextContent());
+ if (val && *val)
+ dest.push_back(val);
+ else
+ log.warn("skipping empty AttributeValue");
+ delete[] val;
+ }
+ else {
+ log.warn("skipping complex AttributeValue");
+ }
+ }
+
+ return dest.empty() ? NULL : _decode(simple.release());
+ }
+
+ const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
+ if (saml2name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml2name->getFormat());
+ log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+ }
+ val = toUTF8(saml2name->getName());
+ }
+ else {
+ const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+ if (saml1name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml1name->getFormat());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+ ids.front().c_str(), f.get() ? f.get() : "unspecified"
+ );
+ }
+ val = toUTF8(saml1name->getName());
+ }
+ else {
+ log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ if (val && *val)
+ dest.push_back(val);
+ else
+ log.warn("ignoring empty NameID");
+ delete[] val;
+ return dest.empty() ? NULL : _decode(simple.release());
+}
--- /dev/null
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * XMLAttribute.cpp
+ *
+ * An Attribute whose values are serialized XML.
+ */
+
+#include "internal.h"
+#include "attribute/XMLAttribute.h"
+
+#include <xercesc/util/Base64.hpp>
+
+#ifndef SHIBSP_LITE
+# include <xsec/framework/XSECDefs.hpp>
+#endif
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+ SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
+ return new XMLAttribute(in);
+ }
+};
+
+XMLAttribute::XMLAttribute(const vector<string>& ids) : Attribute(ids)
+{
+}
+
+XMLAttribute::XMLAttribute(DDF& in) : Attribute(in)
+{
+ DDF val = in.first().first();
+ while (val.string()) {
+ m_values.push_back(val.string());
+ val = in.first().next();
+ }
+}
+
+XMLAttribute::~XMLAttribute()
+{
+}
+
+vector<string>& XMLAttribute::getValues()
+{
+ return m_values;
+}
+
+const vector<string>& XMLAttribute::getValues() const
+{
+ return m_values;
+}
+
+size_t XMLAttribute::valueCount() const
+{
+ return m_values.size();
+}
+
+void XMLAttribute::clearSerializedValues()
+{
+ m_serialized.clear();
+}
+
+const char* XMLAttribute::getString(size_t index) const
+{
+ return m_values[index].c_str();
+}
+
+void XMLAttribute::removeValue(size_t index)
+{
+ Attribute::removeValue(index);
+ if (index < m_values.size())
+ m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& XMLAttribute::getSerializedValues() const
+{
+ xsecsize_t len;
+ XMLByte *pos, *pos2;
+ if (m_serialized.empty()) {
+ for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+ XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
+ if (enc) {
+ for (pos=enc, pos2=enc; *pos2; pos2++)
+ if (isgraph(*pos2))
+ *pos++=*pos2;
+ *pos=0;
+ m_serialized.push_back(reinterpret_cast<char*>(enc));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&enc);
+#else
+ XMLString::release((char**)&enc);
+#endif
+ }
+ }
+ }
+ return Attribute::getSerializedValues();
+}
+
+DDF XMLAttribute::marshall() const
+{
+ DDF ddf = Attribute::marshall();
+ ddf.name("XML");
+ DDF vlist = ddf.first();
+ for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+ vlist.add(DDF(NULL).string(i->c_str()));
+ return ddf;
+}
*
* @param ids array with primary identifier in first position, followed by any aliases
*/
- XMLAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
+ XMLAttribute(const std::vector<std::string>& ids);
/**
* Constructs based on a remoted XMLAttribute.
*
* @param in input object containing marshalled XMLAttribute
*/
- XMLAttribute(DDF& in) : Attribute(in) {
- DDF val = in.first().first();
- while (val.string()) {
- m_values.push_back(val.string());
- val = in.first().next();
- }
- }
+ XMLAttribute(DDF& in);
- virtual ~XMLAttribute() {}
+ virtual ~XMLAttribute();
/**
* Returns the set of values encoded as XML.
*
* @return a mutable vector of the values
*/
- std::vector<std::string>& getValues() {
- return m_values;
- }
+ std::vector<std::string>& getValues();
/**
* Returns the set of values encoded as XML.
*
* @return an immutable vector of the values
*/
- const std::vector<std::string>& getValues() const {
- return m_values;
- }
-
- size_t valueCount() const {
- return m_values.size();
- }
-
- void clearSerializedValues() {
- m_serialized.clear();
- }
-
- const char* getString(size_t index) const {
- return m_values[index].c_str();
- }
-
- void removeValue(size_t index) {
- Attribute::removeValue(index);
- if (index < m_values.size())
- m_values.erase(m_values.begin() + index);
- }
+ const std::vector<std::string>& getValues() const;
+ // Virtual function overrides.
+ size_t valueCount() const;
+ void clearSerializedValues();
+ const char* getString(size_t index) const;
+ void removeValue(size_t index);
const std::vector<std::string>& getSerializedValues() const;
-
- DDF marshall() const {
- DDF ddf = Attribute::marshall();
- ddf.name("XML");
- DDF vlist = ddf.first();
- for (std::vector<std::string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
- vlist.add(DDF(NULL).string(i->c_str()));
- return ddf;
- }
+ DDF marshall() const;
private:
std::vector<std::string> m_values;
-/*\r
- * Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLAttributeDecoder.cpp\r
- *\r
- * Decodes arbitrary XML into an XMLAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/XMLAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
- class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
- {\r
- public:\r
- XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
- ~XMLAttributeDecoder() {}\r
-\r
- Attribute* decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
- ) const;\r
-\r
- private:\r
- DDF convert(DOMElement* e, bool nameit=true) const;\r
- auto_ptr_char m_formatter;\r
- map<pair<xstring,xstring>,string> m_tagMap;\r
- };\r
-\r
- AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
- {\r
- return new XMLAttributeDecoder(e);\r
- }\r
-};\r
-\r
-\r
-Attribute* XMLAttributeDecoder::decode(\r
- const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
- ) const\r
-{\r
- if (!xmlObject)\r
- return NULL;\r
-\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
-\r
- auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
- vector<string>& dest = attr->getValues();\r
-\r
- // Handle any non-Attribute object directly.\r
- if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
- DOMElement* e = xmlObject->getDOM();\r
- if (e) {\r
- if (log.isDebugEnabled()) {\r
- log.debug(\r
- "decoding XMLAttribute (%s) from XMLObject (%s)",\r
- ids.front().c_str(),\r
- (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
- );\r
- }\r
- dest.push_back(string());\r
- XMLHelper::serialize(e, dest.back());\r
- }\r
- else {\r
- log.warn("skipping XMLObject without a backing DOM");\r
- }\r
- return dest.empty() ? NULL : _decode(attr.release());\r
- }\r
-\r
- vector<XMLObject*>::const_iterator v,stop;\r
-\r
- const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
- if (saml2attr) {\r
- const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml2attr->getName());\r
- log.debug(\r
- "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
- if (saml1attr) {\r
- const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
- v = values.begin();\r
- stop = values.end();\r
- if (log.isDebugEnabled()) {\r
- auto_ptr_char n(saml1attr->getAttributeName());\r
- log.debug(\r
- "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
- ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
- );\r
- }\r
- }\r
- else {\r
- log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");\r
- return NULL;\r
- }\r
- }\r
-\r
- for (; v!=stop; ++v) {\r
- DOMElement* e = (*v)->getDOM();\r
- if (e) {\r
- dest.push_back(string());\r
- XMLHelper::serialize(e, dest.back());\r
- }\r
- else\r
- log.warn("skipping AttributeValue without a backing DOM");\r
- }\r
-\r
- return dest.empty() ? NULL : _decode(attr.release());\r
-}\r
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * XMLAttributeDecoder.cpp
+ *
+ * Decodes arbitrary XML into an XMLAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/XMLAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+ ~XMLAttributeDecoder() {}
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ DDF convert(DOMElement* e, bool nameit=true) const;
+ auto_ptr_char m_formatter;
+ map<pair<xstring,xstring>,string> m_tagMap;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new XMLAttributeDecoder(e);
+ }
+};
+
+
+Attribute* XMLAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ if (!xmlObject)
+ return NULL;
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");
+
+ auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));
+ vector<string>& dest = attr->getValues();
+
+ // Handle any non-Attribute object directly.
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ DOMElement* e = xmlObject->getDOM();
+ if (e) {
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "decoding XMLAttribute (%s) from XMLObject (%s)",
+ ids.front().c_str(),
+ (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()
+ );
+ }
+ dest.push_back(string());
+ XMLHelper::serialize(e, dest.back());
+ }
+ else {
+ log.warn("skipping XMLObject without a backing DOM");
+ }
+ return dest.empty() ? NULL : _decode(attr.release());
+ }
+
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ DOMElement* e = (*v)->getDOM();
+ if (e) {
+ dest.push_back(string());
+ XMLHelper::serialize(e, dest.back());
+ }
+ else
+ log.warn("skipping AttributeValue without a backing DOM");
+ }
+
+ return dest.empty() ? NULL : _decode(attr.release());
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_attrfilt_h__
#define __shibsp_attrfilt_h__
-#include <shibsp/attribute/filtering/FilteringContext.h>
+#include <shibsp/base.h>
+#include <vector>
#include <xmltooling/Lockable.h>
namespace shibsp {
+ class SHIBSP_API Attribute;
+ class SHIBSP_API FilteringContext;
+
/**
* Engine for filtering attribute values.
*/
{
MAKE_NONCOPYABLE(AttributeFilter);
protected:
- AttributeFilter() {}
+ AttributeFilter();
public:
- virtual ~AttributeFilter() {}
+ virtual ~AttributeFilter();
/**
* Filters values out of a set of attributes.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
namespace shibsp {
+ class SHIBSP_API Attribute;
+
class SHIBSP_API BasicFilteringContext : public FilteringContext
{
public:
const opensaml::saml2md::RoleDescriptor* role=NULL,
const XMLCh* authncontext_class=NULL,
const XMLCh* authncontext_decl=NULL
- ) : m_app(app), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl) {
- if (role)
- m_issuer = dynamic_cast<opensaml::saml2md::EntityDescriptor*>(role->getParent())->getEntityID();
- for (std::vector<Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a)
- m_attributes.insert(std::multimap<std::string,Attribute*>::value_type((*a)->getId(), *a));
- }
+ );
- virtual ~BasicFilteringContext() {}
+ virtual ~BasicFilteringContext();
- const Application& getApplication() const {
- return m_app;
- }
- const XMLCh* getAuthnContextClassRef() const {
- return m_class;
- }
- const XMLCh* getAuthnContextDeclRef() const {
- return m_decl;
- }
- const XMLCh* getAttributeRequester() const {
- return m_app.getXMLString("entityID").second;
- }
- const XMLCh* getAttributeIssuer() const {
- return m_issuer;
- }
- const opensaml::saml2md::RoleDescriptor* getAttributeRequesterMetadata() const {
- return NULL;
- }
- const opensaml::saml2md::RoleDescriptor* getAttributeIssuerMetadata() const {
- return m_role;
- }
- const std::multimap<std::string,Attribute*>& getAttributes() const {
- return m_attributes;
- }
+ // Virtual function overrides.
+ const Application& getApplication() const;
+ const XMLCh* getAuthnContextClassRef() const;
+ const XMLCh* getAuthnContextDeclRef() const;
+ const XMLCh* getAttributeRequester() const;
+ const XMLCh* getAttributeIssuer() const;
+ const opensaml::saml2md::RoleDescriptor* getAttributeRequesterMetadata() const;
+ const opensaml::saml2md::RoleDescriptor* getAttributeIssuerMetadata() const;
+ const std::multimap<std::string,Attribute*>& getAttributes() const;
private:
const Application& m_app;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_filtpolctx_h__
#define __shibsp_filtpolctx_h__
-#include <shibsp/attribute/filtering/MatchFunctor.h>
+#include <shibsp/base.h>
#include <map>
#include <string>
namespace shibsp {
+ class SHIBSP_API MatchFunctor;
+
/**
* Context for lookup of instantiated MatchFunctor objects.
*/
*
* @param functors reference to a map of id/functor pairs
*/
- FilterPolicyContext(std::multimap<std::string,MatchFunctor*>& functors) : m_functors(functors) {
- }
+ FilterPolicyContext(std::multimap<std::string,MatchFunctor*>& functors);
- virtual ~FilterPolicyContext() {}
+ virtual ~FilterPolicyContext();
/**
* Gets a mutable map to store id/functor pairs.
*
* @return reference to a mutable map containing available MatchFunctors
*/
- std::multimap<std::string,MatchFunctor*>& getMatchFunctors() const {
- return m_functors;
- }
+ std::multimap<std::string,MatchFunctor*>& getMatchFunctors() const;
private:
std::multimap<std::string,MatchFunctor*>& m_functors;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <shibsp/base.h>
-#include <saml/saml2/metadata/Metadata.h>
+#include <map>
+#include <string>
+
+namespace opensaml {
+ namespace saml2md {
+ class SAML_API RoleDescriptor;
+ };
+};
namespace shibsp {
{
MAKE_NONCOPYABLE(FilteringContext);
protected:
- FilteringContext() {}
+ FilteringContext();
public:
- virtual ~FilteringContext() {}
+ virtual ~FilteringContext();
/**
* Gets the Application doing the filtering.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
MAKE_NONCOPYABLE(MatchFunctor);
protected:
- MatchFunctor() {}
+ MatchFunctor();
public:
- virtual ~MatchFunctor() {}
+ virtual ~MatchFunctor();
/**
* Evaluates this matching criteria. This evaluation is used when a filtering engine determines policy
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "exceptions.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include "util/SPConstants.h"
#include <xercesc/util/XMLUniDefs.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
using namespace shibsp;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
conf.AttributeFilterManager.registerFactory(XML_ATTRIBUTE_FILTER, XMLAttributeFilterFactory);
conf.AttributeFilterManager.registerFactory(CHAINING_ATTRIBUTE_FILTER, ChainingAttributeFilterFactory);
}
+
+AttributeFilter::AttributeFilter()
+{
+}
+
+AttributeFilter::~AttributeFilter()
+{
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
using namespace opensaml::saml2md;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include <xercesc/util/regx/RegularExpression.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
namespace shibsp {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* AttributeRequesterInEntityGroupFunctor.cpp
*
- * A match function that evaluates to true if the attribute requester is found in metadata and is a member\r
+ * A match function that evaluates to true if the attribute requester is found in metadata and is a member
* of the given entity group.
*/
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
using namespace opensaml::saml2md;
static const XMLCh groupID[] = UNICODE_LITERAL_7(g,r,o,u,p,I,D);
/**
- * A match function that evaluates to true if the attribute requester is found in metadata and is a member\r
+ * A match function that evaluates to true if the attribute requester is found in metadata and is a member
* of the given entity group.
*/
class SHIBSP_DLLLOCAL AttributeRequesterInEntityGroupFunctor : public MatchFunctor
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include <xercesc/util/regx/RegularExpression.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
namespace shibsp {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include "metadata/MetadataExt.h"
+#include <saml/saml2/metadata/Metadata.h>
#include <xercesc/util/regx/RegularExpression.hpp>
using namespace opensaml::saml2md;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include <xercesc/util/regx/RegularExpression.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
using namespace shibsp;
using namespace std;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include <xercesc/util/regx/RegularExpression.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
using namespace shibsp;
using namespace std;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include <xercesc/util/regx/RegularExpression.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
namespace shibsp {
--- /dev/null
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * BasicFilteringContext.cpp
+ *
+ * A trivial FilteringContext implementation.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "attribute/Attribute.h"
+#include "attribute/filtering/BasicFilteringContext.h"
+
+#include <saml/saml2/metadata/Metadata.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace std;
+
+FilteringContext::FilteringContext()
+{
+}
+
+FilteringContext::~FilteringContext()
+{
+}
+
+BasicFilteringContext::BasicFilteringContext(
+ const Application& app,
+ const vector<Attribute*>& attributes,
+ const RoleDescriptor* role,
+ const XMLCh* authncontext_class,
+ const XMLCh* authncontext_decl
+ ) : m_app(app), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl)
+{
+ if (role)
+ m_issuer = dynamic_cast<EntityDescriptor*>(role->getParent())->getEntityID();
+ for (vector<Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a)
+ m_attributes.insert(multimap<string,Attribute*>::value_type((*a)->getId(), *a));
+}
+
+BasicFilteringContext::~BasicFilteringContext()
+{
+}
+
+const Application& BasicFilteringContext::getApplication() const
+{
+ return m_app;
+}
+
+const XMLCh* BasicFilteringContext::getAuthnContextClassRef() const
+{
+ return m_class;
+}
+
+const XMLCh* BasicFilteringContext::getAuthnContextDeclRef() const
+{
+ return m_decl;
+}
+
+const XMLCh* BasicFilteringContext::getAttributeRequester() const
+{
+ return m_app.getXMLString("entityID").second;
+}
+
+const XMLCh* BasicFilteringContext::getAttributeIssuer() const
+{
+ return m_issuer;
+}
+
+const RoleDescriptor* BasicFilteringContext::getAttributeRequesterMetadata() const
+{
+ return NULL;
+}
+
+const RoleDescriptor* BasicFilteringContext::getAttributeIssuerMetadata() const
+{
+ return m_role;
+}
+
+const multimap<string,Attribute*>& BasicFilteringContext::getAttributes() const
+{
+ return m_attributes;
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
+#include "attribute/filtering/FilterPolicyContext.h"
#include "attribute/filtering/MatchFunctor.h"
#include "util/SPConstants.h"
REGISTER_FACTORY(AttributeRequesterInEntityGroup);
REGISTER_FACTORY(AttributeScopeMatchesShibMDScope);
}
+
+MatchFunctor::MatchFunctor()
+{
+}
+
+MatchFunctor::~MatchFunctor()
+{
+}
+
+FilterPolicyContext::FilterPolicyContext(multimap<string,MatchFunctor*>& functors) : m_functors(functors)
+{
+}
+
+FilterPolicyContext::~FilterPolicyContext()
+{
+}
+
+multimap<string,MatchFunctor*>& FilterPolicyContext::getMatchFunctors() const
+{
+ return m_functors;
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "exceptions.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include "util/SPConstants.h"
#include <xercesc/util/XMLUniDefs.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "attribute/Attribute.h"
#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
using namespace shibsp;
using namespace std;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "exceptions.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include "util/SPConstants.h"
#include <xercesc/util/XMLUniDefs.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
+#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
#include "attribute/Attribute.h"
#include "attribute/filtering/AttributeFilter.h"
+#include "attribute/filtering/FilteringContext.h"
#include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
#include "util/SPConstants.h"
#include <xmltooling/util/NDC.h>
#define __shibsp_extractor_h__
#include <shibsp/base.h>
+
+#include <string>
+#include <vector>
#include <xmltooling/Lockable.h>
-#include <saml/saml2/metadata/Metadata.h>
+
+namespace xmltooling {
+ class XMLTOOL_API XMLObject;
+};
+
+namespace opensaml {
+ namespace saml2md {
+ class SAML_API RoleDescriptor;
+ };
+};
namespace shibsp {
{
MAKE_NONCOPYABLE(AttributeExtractor);
protected:
- AttributeExtractor() {}
+ AttributeExtractor();
public:
- virtual ~AttributeExtractor() {}
+ virtual ~AttributeExtractor();
/**
* Extracts the attributes found in an XMLObject.
#include <shibsp/base.h>
-#include <saml/Assertion.h>
-#include <saml/saml2/metadata/Metadata.h>
+#include <string>
+#include <vector>
#include <xmltooling/Lockable.h>
+namespace opensaml {
+ class SAML_API Assertion;
+ namespace saml2 {
+ class SAML_API NameID;
+ };
+ namespace saml2md {
+ class SAML_API EntityDescriptor;
+ };
+};
+
namespace shibsp {
class SHIBSP_API Application;
{
MAKE_NONCOPYABLE(AttributeResolver);
protected:
- AttributeResolver() {}
+ AttributeResolver();
public:
- virtual ~AttributeResolver() {}
+ virtual ~AttributeResolver();
/**
* Creates a ResolutionContext based on session bootstrap material.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <shibsp/base.h>
-#include <saml/Assertion.h>
+#include <vector>
+
+namespace opensaml {
+ class SAML_API Assertion;
+};
namespace shibsp {
{
MAKE_NONCOPYABLE(ResolutionContext);
protected:
- ResolutionContext() {}
+ ResolutionContext();
public:
- virtual ~ResolutionContext() {}
+ virtual ~ResolutionContext();
/**
* Returns the set of Attributes resolved and added to the context.
SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
}
+AttributeExtractor::AttributeExtractor()
+{
+}
+
+AttributeExtractor::~AttributeExtractor()
+{
+}
+
ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e)
{
SPConfig& conf = SPConfig::getConfig();
#include "attribute/resolver/AttributeResolver.h"
#include "attribute/resolver/ResolutionContext.h"
+#include <saml/Assertion.h>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/util/XMLHelper.h>
SPConfig::getConfig().AttributeResolverManager.registerFactory(CHAINING_ATTRIBUTE_RESOLVER, ChainingResolverFactory);
}
+ResolutionContext::ResolutionContext()
+{
+}
+
+ResolutionContext::~ResolutionContext()
+{
+}
+
+AttributeResolver::AttributeResolver()
+{
+}
+
+AttributeResolver::~AttributeResolver()
+{
+}
+
ChainingAttributeResolver::ChainingAttributeResolver(const DOMElement* e)
{
SPConfig& conf = SPConfig::getConfig();
#include "util/SPConstants.h"
#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/security/CredentialResolver.h>
+#include <xmltooling/util/DateTime.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
val.addmember("DelegationInstant").string(temp.get());
}
- auto_arrayptr<char> name(toUTF8(n->getName()));\r
- if (name.get() && *name.get()) {\r
- val.addmember("Name").string(name.get());\r
- char* str = toUTF8(n->getFormat());\r
- if (str && *str)\r
- val.addmember("Format").string(str);\r
- delete[] str;\r
-\r
- str = toUTF8(n->getNameQualifier());\r
- if (str && *str)\r
- val.addmember("NameQualifier").string(str);\r
- delete[] str;\r
-\r
- str = toUTF8(n->getSPNameQualifier());\r
- if (str && *str)\r
- val.addmember("SPNameQualifier").string(str);\r
- delete[] str;\r
-\r
- str = toUTF8(n->getSPProvidedID());\r
- if (str && *str)\r
- val.addmember("SPProvidedID").string(str);\r
- delete[] str;\r
- }\r
+ auto_arrayptr<char> name(toUTF8(n->getName()));
+ if (name.get() && *name.get()) {
+ val.addmember("Name").string(name.get());
+ char* str = toUTF8(n->getFormat());
+ if (str && *str)
+ val.addmember("Format").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getNameQualifier());
+ if (str && *str)
+ val.addmember("NameQualifier").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getSPNameQualifier());
+ if (str && *str)
+ val.addmember("SPNameQualifier").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getSPProvidedID());
+ if (str && *str)
+ val.addmember("SPProvidedID").string(str);
+ delete[] str;
+ }
if (n != (*d)->getNameID())
delete n;
*/
#include "internal.h"
+#include "exceptions.h"
#include "Application.h"
#include "attribute/AttributeDecoder.h"
#include "attribute/SimpleAttribute.h"
#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/security/Credential.h>
#include <xmltooling/security/SecurityHelper.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
}
private:
+ auto_ptr_char m_hashAlg;
vector<string> m_hashId;
vector<string> m_signingId;
vector<string> m_encryptionId;
static const XMLCh encryptionId[] = UNICODE_LITERAL_12(e,n,c,r,y,p,t,i,o,n,I,d);
static const XMLCh hashId[] = UNICODE_LITERAL_6(h,a,s,h,I,d);
+ static const XMLCh hashAlg[] = UNICODE_LITERAL_7(h,a,s,h,A,l,g);
static const XMLCh signingId[] = UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
};
-KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e)
+KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e) : m_hashAlg(e ? e->getAttributeNS(NULL, hashAlg) : NULL)
{
if (e) {
const XMLCh* a = e->getAttributeNS(NULL, hashId);
mcc.setUsage(Credential::SIGNING_CREDENTIAL);
if (application.getMetadataProvider()->resolve(creds, &mcc)) {
if (!m_hashId.empty()) {
+ const char* alg = m_hashAlg.get();
+ if (!alg || !*alg)
+ alg = "SHA1";
auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
vector<string>& vals = attr->getValues();
for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
if (vals.empty() || !vals.back().empty())
vals.push_back(string());
- vals.back() = SecurityHelper::getDEREncoding(*(*c), true);
+ vals.back() = SecurityHelper::getDEREncoding(*(*c), alg);
}
if (vals.back().empty())
vals.pop_back();
#include "attribute/resolver/ResolutionContext.h"
#include "binding/SOAPClient.h"
#include "metadata/MetadataProviderCriteria.h"
+#include "security/SecurityPolicy.h"
#include "util/SPConstants.h"
#include <saml/exceptions.h>
-#include <saml/binding/SecurityPolicy.h>
#include <saml/saml1/binding/SAML1SOAPClient.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml1/core/Protocols.h>
#include <saml/saml2/binding/SAML2SOAPClient.h>
#include <saml/saml2/core/Protocols.h>
#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/MetadataProvider.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/XMLHelper.h>
obj.release();
}
}
- else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1P_NS, AttributeDesignator::LOCAL_NAME)) {
+ else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1_NS, AttributeDesignator::LOCAL_NAME)) {
auto_ptr<XMLObject> obj(AttributeDesignatorBuilder::buildOneFromElement(child));
AttributeDesignator* down = dynamic_cast<AttributeDesignator*>(obj.get());
if (down) {
*/
#include "internal.h"
+#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
#include "attribute/resolver/ResolutionContext.h"
#include "binding/SOAPClient.h"
#include "metadata/MetadataProviderCriteria.h"
+#include "security/SecurityPolicy.h"
#include "util/SPConstants.h"
#include <saml/exceptions.h>
#include <saml/SAMLConfig.h>
-#include <saml/binding/SecurityPolicy.h>
#include <saml/saml2/binding/SAML2SOAPClient.h>
#include <saml/saml2/core/Protocols.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/TrustEngine.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
*/
#include "internal.h"
+#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
+#include "attribute/Attribute.h"
#include "attribute/AttributeDecoder.h"
#include "attribute/filtering/AttributeFilter.h"
#include "attribute/filtering/BasicFilteringContext.h"
#include "attribute/resolver/AttributeExtractor.h"
+#include "remoting/ddf.h"
#include "security/SecurityPolicy.h"
#include "util/SPConstants.h"
#include <saml/SAMLConfig.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/ObservableMetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/TrustEngine.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
class SHIBSP_API ArtifactResolver : public opensaml::MessageDecoder::ArtifactResolver {
public:
- ArtifactResolver() {}
- virtual ~ArtifactResolver() {}
+ ArtifactResolver();
+ virtual ~ArtifactResolver();
opensaml::saml1p::Response* resolve(
const std::vector<opensaml::SAMLArtifact*>& artifacts,
#ifndef __shibsp_soap11client_h__
#define __shibsp_soap11client_h__
-#include <shibsp/security/SecurityPolicy.h>
+#include <shibsp/base.h>
+
#include <saml/binding/SOAPClient.h>
-#include <xmltooling/security/CredentialResolver.h>
namespace shibsp {
class SHIBSP_API PropertySet;
+ class SHIBSP_API SecurityPolicy;
/**
* Specialized SOAPClient for SP environment.
*/
SOAPClient(SecurityPolicy& policy);
- virtual ~SOAPClient() {
- if (m_credResolver)
- m_credResolver->unlock();
- }
+ virtual ~SOAPClient();
/**
* Override handles message signing for SAML payloads.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "Application.h"
-#include "exceptions.h"
#include "binding/ArtifactResolver.h"
#include "binding/SOAPClient.h"
#include "security/SecurityPolicy.h"
+#include <saml/exceptions.h>
#include <saml/saml1/core/Protocols.h>
#include <saml/saml1/binding/SAML1SOAPClient.h>
#include <saml/saml2/core/Protocols.h>
#include <saml/saml2/binding/SAML2Artifact.h>
#include <saml/saml2/binding/SAML2SOAPClient.h>
+#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/util/SAMLConstants.h>
using namespace xmltooling;
using namespace std;
+ArtifactResolver::ArtifactResolver()
+{
+}
+
+ArtifactResolver::~ArtifactResolver()
+{
+}
+
saml1p::Response* ArtifactResolver::resolve(
const vector<SAMLArtifact*>& artifacts,
const IDPSSODescriptor& idpDescriptor,
#include "internal.h"
#include "Application.h"
-#include "exceptions.h"
#include "ServiceProvider.h"
#include "binding/SOAPClient.h"
+#include "security/SecurityPolicy.h"
+#include <saml/exceptions.h>
#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/signature/ContentReference.h>
+#include <xmltooling/security/Credential.h>
+#include <xmltooling/signature/Signature.h>
#include <xmltooling/soap/SOAP.h>
#include <xmltooling/soap/HTTPSOAPTransport.h>
#include <xmltooling/util/NDC.h>
{
}
+SOAPClient::~SOAPClient()
+{
+ if (m_credResolver)
+ m_credResolver->unlock();
+}
+
void SOAPClient::send(const soap11::Envelope& env, const char* from, MetadataCredentialCriteria& to, const char* endpoint)
{
// Check for message signing requirements.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/exceptions.h
*
- * Exception classes
+ * Exception classes.
*/
#ifndef __shibsp_exceptions_h__
#define __shibsp_exceptions_h__
#include <shibsp/base.h>
-#ifndef SHIBSP_LITE
-# include <saml/exceptions.h>
-#else
-# include <xmltooling/exceptions.h>
-#endif
+#include <xmltooling/exceptions.h>
namespace shibsp {
#include <shibsp/remoting/ddf.h>
#include <shibsp/util/DOMPropertySet.h>
+#include <map>
+#include <string>
+#include <xmltooling/logging.h>
+
#ifndef SHIBSP_LITE
-# include <saml/binding/MessageEncoder.h>
-# include <saml/saml2/core/Protocols.h>
+namespace opensaml {
+ class SAML_API MessageEncoder;
+ namespace saml2md {
+ class SAML_API RoleDescriptor;
+ };
+ namespace saml2p {
+ class SAML_API StatusResponseType;
+ };
+};
#endif
-#include <xmltooling/logging.h>
-#include <xmltooling/XMLObject.h>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
+
+namespace xmltooling {
+ class XMLTOOL_API HTTPRequest;
+ class XMLTOOL_API HTTPResponse;
+ class XMLTOOL_API XMLObject;
+};
namespace shibsp {
xmltooling::auto_ptr_char m_configNS;
public:
- virtual ~AbstractHandler() {}
+ virtual ~AbstractHandler();
private:
std::pair<std::string,const char*> getPostCookieNameProps(const Application& app, const char* relayState) const;
#include <shibsp/handler/AbstractHandler.h>
#include <shibsp/handler/RemotedHandler.h>
+
#ifndef SHIBSP_LITE
-# include <saml/binding/MessageDecoder.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
+namespace opensaml {
+ class SAML_API Assertion;
+ class SAML_API MessageDecoder;
+ namespace saml1 {
+ class SAML_API NameIdentifier;
+ };
+ namespace saml2 {
+ class SAML_API NameID;
+ };
+ namespace saml2md {
+ class SAML_API SPSSODescriptor;
+ };
+};
#endif
-#include <xmltooling/unicode.h>
namespace shibsp {
/**
* Constructor
*
- * @param e root of DOM configuration
- * @param appId ID of application that "owns" the handler
- * @param log a logging object to use
+ * @param e root of DOM configuration
+ * @param appId ID of application that "owns" the handler
+ * @param log a logging object to use
+ * @param filter optional filter controls what child elements to include as nested PropertySets
+ * @param remapper optional map of property rename rules for legacy property support
*/
- AssertionConsumerService(const xercesc::DOMElement* e, const char* appId, xmltooling::logging::Category& log);
+ AssertionConsumerService(
+ const xercesc::DOMElement* e,
+ const char* appId,
+ xmltooling::logging::Category& log,
+ xercesc::DOMNodeFilter* filter=NULL,
+ const std::map<std::string,std::string>* remapper=NULL
+ );
/**
* Enforce address checking requirements.
) const;
public:
- const char* getType() const {
- return "AssertionConsumerService";
- }
+ const char* getType() const;
#endif
private:
#if defined (_MSC_VER)
#pragma warning( pop )
#endif
-
};
#endif /* __shibsp_acshandler_h__ */
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/handler/Handler.h
*
- * Pluggable runtime functionality that implement protocols and services
+ * Pluggable runtime functionality that implement protocols and services.
*/
#ifndef __shibsp_handler_h__
#define __shibsp_handler_h__
#include <shibsp/util/PropertySet.h>
+
#ifndef SHIBSP_LITE
-# include <saml/saml2/metadata/Metadata.h>
+namespace opensaml {
+ namespace saml2md {
+ class SAML_API SPSSODescriptor;
+ };
+};
#endif
namespace shibsp {
{
MAKE_NONCOPYABLE(Handler);
protected:
- Handler() {}
+ Handler();
public:
- virtual ~Handler() {}
+ virtual ~Handler();
/**
* Executes handler functionality as an incoming request.
*
* @return a Handler type
*/
- virtual const char* getType() const {
- return getString("type").second;
- }
+ virtual const char* getType() const;
#endif
};
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_logout_h__
#define __shibsp_logout_h__
-#include <shibsp/SPRequest.h>
#include <shibsp/handler/RemotedHandler.h>
namespace shibsp {
class SHIBSP_API LogoutHandler : public RemotedHandler
{
public:
- virtual ~LogoutHandler() {}
+ virtual ~LogoutHandler();
/**
* The base method will iteratively attempt front-channel notification
void receive(DDF& in, std::ostream& out);
protected:
- LogoutHandler() : m_initiator(true) {}
+ LogoutHandler();
/** Flag indicating whether the subclass is acting as a LogoutInitiator. */
bool m_initiator;
) const;
/**
+ * @deprecated
* Sends a response template to the user agent informing it of the results of a logout attempt.
*
* @param application the Application to use in determining the logout template
bool local=true,
const char* status=NULL
) const;
+
+ /**
+ * Sends a response template to the user agent informing it of the results of a logout attempt.
+ *
+ * @param application the Application to use in determining the logout template
+ * @param request the HTTP client request to supply to the template
+ * @param response the HTTP response to use
+ * @param type designates the prefix of logout template name to use
+ */
+ std::pair<bool,long> sendLogoutPage(
+ const Application& application,
+ const xmltooling::HTTPRequest& request,
+ xmltooling::HTTPResponse& response,
+ const char* type
+ ) const;
};
#if defined (_MSC_VER)
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_remhandler_h__
#define __shibsp_remhandler_h__
-#include <shibsp/SPRequest.h>
#include <shibsp/handler/Handler.h>
#include <shibsp/remoting/ListenerService.h>
+namespace xmltooling {
+ class XMLTOOL_API HTTPRequest;
+ class XMLTOOL_API HTTPResponse;
+};
+
namespace shibsp {
/**
virtual ~RemotedHandler();
protected:
- RemotedHandler() {}
+ RemotedHandler();
/**
* Establishes message remoting using the supplied address.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
class SHIBSP_API SessionInitiator : public virtual Handler
{
+ friend void SHIBSP_API registerSessionInitiators();
protected:
- SessionInitiator() {}
+ /** Property remapper for configuration compatibility. */
+ static std::map<std::string,std::string> m_remapper;
+
+ SessionInitiator();
public:
- virtual ~SessionInitiator() {}
+ virtual ~SessionInitiator();
/**
* Executes an incoming request.
std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
#ifndef SHIBSP_LITE
- const char* getType() const {
- return "SessionInitiator";
- }
+ const char* getType() const;
#endif
};
-/*
- * Copyright 2001-2009 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * AbstractHandler.cpp
- *
- * Base class for handlers based on a DOMPropertySet.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "exceptions.h"
-#include "ServiceProvider.h"
-#include "SPRequest.h"
-#include "handler/AbstractHandler.h"
-#include "handler/LogoutHandler.h"
-#include "remoting/ListenerService.h"
-#include "util/CGIParser.h"
-#include "util/SPConstants.h"
-#include "util/TemplateParameters.h"
-
-#include <vector>
-#include <fstream>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/PathResolver.h>
-#include <xmltooling/util/URLEncoder.h>
-
-
-#ifndef SHIBSP_LITE
-# include <saml/saml1/core/Protocols.h>
-# include <saml/saml2/core/Protocols.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-# include <saml/util/SAMLConstants.h>
-# include <saml/SAMLConfig.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <xmltooling/util/StorageService.h>
-using namespace opensaml::saml2md;
-#else
-# include "lite/SAMLConstants.h"
-#endif
-
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/URLEncoder.h>
-
-using namespace shibsp;
-using namespace samlconstants;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-namespace shibsp {
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory MetadataGeneratorFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory StatusHandlerFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SessionHandlerFactory;
-
- void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {
- static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- int r;
- unsigned char b1,b2;
- buf.erase();
- for (unsigned int i=0; i<len; i+=4) {
- r = rand();
- b1 = (0x00FF & r);
- b2 = (0xFF00 & r) >> 8;
- buf += (DIGITS[(0xF0 & b1) >> 4 ]);
- buf += (DIGITS[0x0F & b1]);
- buf += (DIGITS[(0xF0 & b2) >> 4 ]);
- buf += (DIGITS[0x0F & b2]);
- }
- }
-};
-
-void SHIBSP_API shibsp::registerHandlers()
-{
- SPConfig& conf=SPConfig::getConfig();
-
- conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);
- conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);
- conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);
- conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);
- conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);
- conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory);
-
- conf.ArtifactResolutionServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2ArtifactResolutionFactory);
-
- conf.HandlerManager.registerFactory(SAML20_BINDING_URI, AssertionLookupFactory);
- conf.HandlerManager.registerFactory(METADATA_GENERATOR_HANDLER, MetadataGeneratorFactory);
- conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
- conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);
-
- conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);
- conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
- conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
- conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);
- conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);
- conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);
- conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2LogoutFactory);
- conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2LogoutFactory);
-
- conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2NameIDMgmtFactory);
- conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2NameIDMgmtFactory);
- conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2NameIDMgmtFactory);
- conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2NameIDMgmtFactory);
- conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2NameIDMgmtFactory);
-}
-
-AbstractHandler::AbstractHandler(
- const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
- ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {
- load(e,NULL,filter,remapper);
-}
-
-#ifndef SHIBSP_LITE
-
-void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleDescriptor* role) const
-{
- const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);
- if (r2) {
- const saml2p::Status* status = r2->getStatus();
- if (status) {
- const saml2p::StatusCode* sc = status->getStatusCode();
- const XMLCh* code = sc ? sc->getValue() : NULL;
- if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
- FatalProfileException ex("SAML response contained an error.");
- annotateException(&ex, role, status); // throws it
- }
- }
- }
-
- const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);
- if (r1) {
- const saml1p::Status* status = r1->getStatus();
- if (status) {
- const saml1p::StatusCode* sc = status->getStatusCode();
- const xmltooling::QName* code = sc ? sc->getValue() : NULL;
- if (code && *code != saml1p::StatusCode::SUCCESS) {
- FatalProfileException ex("SAML response contained an error.");
- ex.addProperty("statusCode", code->toString().c_str());
- if (sc->getStatusCode()) {
- code = sc->getStatusCode()->getValue();
- if (code)
- ex.addProperty("statusCode2", code->toString().c_str());
- }
- if (status->getStatusMessage()) {
- auto_ptr_char msg(status->getStatusMessage()->getMessage());
- if (msg.get() && *msg.get())
- ex.addProperty("statusMessage", msg.get());
- }
- ex.raise();
- }
- }
- }
-}
-
-void AbstractHandler::fillStatus(saml2p::StatusResponseType& response, const XMLCh* code, const XMLCh* subcode, const char* msg) const
-{
- saml2p::Status* status = saml2p::StatusBuilder::buildStatus();
- saml2p::StatusCode* scode = saml2p::StatusCodeBuilder::buildStatusCode();
- status->setStatusCode(scode);
- scode->setValue(code);
- if (subcode) {
- saml2p::StatusCode* ssubcode = saml2p::StatusCodeBuilder::buildStatusCode();
- scode->setStatusCode(ssubcode);
- ssubcode->setValue(subcode);
- }
- if (msg) {
- pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
- auto_ptr_XMLCh widemsg((flag.first && flag.second) ? msg : "Error processing request.");
- saml2p::StatusMessage* sm = saml2p::StatusMessageBuilder::buildStatusMessage();
- status->setStatusMessage(sm);
- sm->setMessage(widemsg.get());
- }
- response.setStatus(status);
-}
-
-long AbstractHandler::sendMessage(
- const MessageEncoder& encoder,
- XMLObject* msg,
- const char* relayState,
- const char* destination,
- const saml2md::RoleDescriptor* role,
- const Application& application,
- HTTPResponse& httpResponse,
- bool signIfPossible
- ) const
-{
- const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : NULL;
- const PropertySet* relyingParty = application.getRelyingParty(entity);
- pair<bool,const char*> flag = signIfPossible ? make_pair(true,(const char*)"true") : relyingParty->getString("signing");
- if (role && flag.first &&
- (!strcmp(flag.second, "true") ||
- (encoder.isUserAgentPresent() && !strcmp(flag.second, "front")) ||
- (!encoder.isUserAgentPresent() && !strcmp(flag.second, "back")))) {
- CredentialResolver* credResolver=application.getCredentialResolver();
- if (credResolver) {
- Locker credLocker(credResolver);
- const Credential* cred = NULL;
- pair<bool,const char*> keyName = relyingParty->getString("keyName");
- pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signingAlg");
- if (role) {
- MetadataCredentialCriteria mcc(*role);
- mcc.setUsage(Credential::SIGNING_CREDENTIAL);
- if (keyName.first)
- mcc.getKeyNames().insert(keyName.second);
- if (sigalg.first)
- mcc.setXMLAlgorithm(sigalg.second);
- cred = credResolver->resolve(&mcc);
- }
- else {
- CredentialCriteria cc;
- cc.setUsage(Credential::SIGNING_CREDENTIAL);
- if (keyName.first)
- cc.getKeyNames().insert(keyName.second);
- if (sigalg.first)
- cc.setXMLAlgorithm(sigalg.second);
- cred = credResolver->resolve(&cc);
- }
- if (cred) {
- // Signed request.
- return encoder.encode(
- httpResponse,
- msg,
- destination,
- entity,
- relayState,
- &application,
- cred,
- sigalg.second,
- relyingParty->getXMLString("digestAlg").second
- );
- }
- else {
- m_log.warn("no signing credential resolved, leaving message unsigned");
- }
- }
- else {
- m_log.warn("no credential resolver installed, leaving message unsigned");
- }
- }
-
- // Unsigned request.
- return encoder.encode(httpResponse, msg, destination, entity, relayState, &application);
-}
-
-#endif
-
-void AbstractHandler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const
-{
- if (relayState.empty())
- return;
-
- // No setting means just pass it by value.
- pair<bool,const char*> mech=getString("relayState");
- if (!mech.first || !mech.second || !*mech.second)
- return;
-
- if (!strcmp(mech.second, "cookie")) {
- // Here we store the state in a cookie and send a fixed
- // value so we can recognize it on the way back.
- if (relayState.find("cookie:") != 0) {
- const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
- pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibstate_");
- string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;
- // Generate a random key for the cookie name instead of the fixed name.
- string rsKey;
- generateRandomHex(rsKey,5);
- shib_cookie.first = "_shibstate_" + rsKey;
- response.setCookie(shib_cookie.first.c_str(),stateval.c_str());
- relayState = "cookie:" + rsKey;
- }
- }
- else if (strstr(mech.second,"ss:")==mech.second) {
- if (relayState.find("ss:") != 0) {
- mech.second+=3;
- if (*mech.second) {
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
- StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
- if (storage) {
- string rsKey;
- generateRandomHex(rsKey,5);
- if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))
- throw IOException("Attempted to insert duplicate storage key.");
- relayState = string(mech.second-3) + ':' + rsKey;
- }
- else {
- m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", mech.second);
- relayState.erase();
- }
-#endif
- }
- else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
- DDF out,in = DDF("set::RelayState").structure();
- in.addmember("id").string(mech.second);
- in.addmember("value").unsafe_string(relayState.c_str());
- DDFJanitor jin(in),jout(out);
- out = application.getServiceProvider().getListenerService()->send(in);
- if (!out.isstring())
- throw IOException("StorageService-backed RelayState mechanism did not return a state key.");
- relayState = string(mech.second-3) + ':' + out.string();
- }
- }
- }
- }
- else
- throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));
-}
-
-void AbstractHandler::recoverRelayState(
- const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear
- ) const
-{
- SPConfig& conf = SPConfig::getConfig();
-
- // Look for StorageService-backed state of the form "ss:SSID:key".
- const char* state = relayState.c_str();
- if (strstr(state,"ss:")==state) {
- state += 3;
- const char* key = strchr(state,':');
- if (key) {
- string ssid = relayState.substr(3, key - state);
- key++;
- if (!ssid.empty() && *key) {
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
- StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
- if (storage) {
- ssid = key;
- if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {
- if (clear)
- storage->deleteString("RelayState",ssid.c_str());
- return;
- }
- else
- relayState.erase();
- }
- else {
- m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());
- relayState.erase();
- }
-#endif
- }
- else if (conf.isEnabled(SPConfig::InProcess)) {
- DDF out,in = DDF("get::RelayState").structure();
- in.addmember("id").string(ssid.c_str());
- in.addmember("key").string(key);
- in.addmember("clear").integer(clear ? 1 : 0);
- DDFJanitor jin(in),jout(out);
- out = application.getServiceProvider().getListenerService()->send(in);
- if (!out.isstring()) {
- m_log.error("StorageService-backed RelayState mechanism did not return a state value.");
- relayState.erase();
- }
- else {
- relayState = out.string();
- return;
- }
- }
- }
- }
- }
-
- // Look for cookie-backed state of the form "cookie:key".
- if (strstr(state,"cookie:")==state) {
- state += 7;
- if (*state) {
- // Pull the value from the "relay state" cookie.
- pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
- relay_cookie.first = string("_shibstate_") + state;
- state = request.getCookie(relay_cookie.first.c_str());
- if (state && *state) {
- // URL-decode the value.
- char* rscopy=strdup(state);
- XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
- relayState = rscopy;
- free(rscopy);
-
- if (clear) {
- string exp(relay_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(relay_cookie.first.c_str(), exp.c_str());
- }
- return;
- }
- }
-
- relayState.erase();
- }
-
- // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).
- if (relayState.empty() || relayState == "default" || relayState == "cookie") {
- pair<bool,const char*> homeURL=application.getString("homeURL");
- if (homeURL.first)
- relayState=homeURL.second;
- else {
- // Compute a URL to the root of the site.
- int port = request.getPort();
- const char* scheme = request.getScheme();
- relayState = string(scheme) + "://" + request.getHostname();
- if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
- ostringstream portstr;
- portstr << port;
- relayState += ":" + portstr.str();
- }
- relayState += '/';
- }
- }
-}
-
-void AbstractHandler::preservePostData(
- const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
- ) const
-{
-#ifdef HAVE_STRCASECMP
- if (strcasecmp(request.getMethod(), "POST")) return;
-#else
- if (stricmp(request.getMethod(), "POST")) return;
-#endif
-
- // No specs mean no save.
- const PropertySet* props=application.getPropertySet("Sessions");
- pair<bool,const char*> mech = props->getString("postData");
- if (!mech.first) {
- m_log.info("postData property not supplied, form data will not be preserved across SSO");
- return;
- }
-
- DDF postData = getPostData(application, request);
- if (postData.isnull())
- return;
-
- if (strstr(mech.second,"ss:") == mech.second) {
- mech.second+=3;
- if (!*mech.second) {
- postData.destroy();
- throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3));
- }
-
- string postkey;
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- DDFJanitor postjan(postData);
-#ifndef SHIBSP_LITE
- StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
- if (storage) {
- // Use a random key
- string rsKey;
- SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
- rsKey = SAMLArtifact::toHex(rsKey);
- ostringstream out;
- out << postData;
- if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))
- throw IOException("Attempted to insert duplicate storage key.");
- postkey = string(mech.second-3) + ':' + rsKey;
- }
- else {
- m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second);
- }
-#endif
- }
- else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
- DDF out,in = DDF("set::PostData").structure();
- DDFJanitor jin(in),jout(out);
- in.addmember("id").string(mech.second);
- in.add(postData);
- out = application.getServiceProvider().getListenerService()->send(in);
- if (!out.isstring())
- throw IOException("StorageService-backed PostData mechanism did not return a state key.");
- postkey = string(mech.second-3) + ':' + out.string();
- }
-
- // Set a cookie with key info.
- pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
- postkey += shib_cookie.second;
- response.setCookie(shib_cookie.first.c_str(), postkey.c_str());
- }
- else {
- postData.destroy();
- throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second));
- }
-}
-
-DDF AbstractHandler::recoverPostData(
- const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
- ) const
-{
- // First we need the post recovery cookie.
- pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
- const char* cookie = request.getCookie(shib_cookie.first.c_str());
- if (!cookie || !*cookie)
- return DDF();
-
- // Clear the cookie.
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(shib_cookie.first.c_str(), exp.c_str());
-
- // Look for StorageService-backed state of the form "ss:SSID:key".
- const char* state = cookie;
- if (strstr(state, "ss:") == state) {
- state += 3;
- const char* key = strchr(state, ':');
- if (key) {
- string ssid = string(cookie).substr(3, key - state);
- key++;
- if (!ssid.empty() && *key) {
- SPConfig& conf = SPConfig::getConfig();
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
- StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
- if (storage) {
- if (storage->readString("PostData", key, &ssid) > 0) {
- storage->deleteString("PostData", key);
- istringstream inret(ssid);
- DDF ret;
- inret >> ret;
- return ret;
- }
- else {
- m_log.error("failed to recover form post data using key (%s)", key);
- }
- }
- else {
- m_log.error("storage-backed PostData with invalid StorageService ID (%s)", ssid.c_str());
- }
-#endif
- }
- else if (conf.isEnabled(SPConfig::InProcess)) {
- DDF in = DDF("get::PostData").structure();
- DDFJanitor jin(in);
- in.addmember("id").string(ssid.c_str());
- in.addmember("key").string(key);
- DDF out = application.getServiceProvider().getListenerService()->send(in);
- if (out.islist())
- return out;
- out.destroy();
- m_log.error("storageService-backed PostData mechanism did not return preserved data.");
- }
- }
- }
- }
- return DDF();
-}
-
-long AbstractHandler::sendPostResponse(
- const Application& application, HTTPResponse& httpResponse, const char* url, DDF& postData
- ) const
-{
- const PropertySet* props=application.getPropertySet("Sessions");
- pair<bool,const char*> postTemplate = props->getString("postTemplate");
- if (!postTemplate.first)
- throw ConfigurationException("Missing postTemplate property, unable to recreate form post.");
-
- string fname(postTemplate.second);
- ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
- if (!infile)
- throw ConfigurationException("Unable to access HTML template ($1).", params(1, fname.c_str()));
- TemplateParameters respParam;
- respParam.m_map["action"] = url;
-
- // Load the parameters into objects for the template.
- multimap<string,string>& collection = respParam.m_collectionMap["PostedData"];
- DDF param = postData.first();
- while (param.isstring()) {
- collection.insert(pair<const string,string>(param.name(), (param.string() ? param.string() : "")));
- param = postData.next();
- }
-
- stringstream str;
- XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam);
-
- pair<bool,bool> postExpire = props->getBool("postExpire");
-
- httpResponse.setContentType("text/html");
- if (!postExpire.first || postExpire.second) {
- httpResponse.setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
- httpResponse.setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
- httpResponse.setResponseHeader("Pragma", "no-cache");
- }
- return httpResponse.sendResponse(str);
-}
-
-pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const
-{
- // Decorates the name of the cookie with the relay state key, if any.
- // Doing so gives a better assurance that the recovered data really
- // belongs to the relayed request.
- pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");
- if (strstr(relayState, "cookie:") == relayState) {
- shib_cookie.first = string("_shibpost_") + (relayState + 7);
- }
- else if (strstr(relayState, "ss:") == relayState) {
- const char* pch = strchr(relayState + 3, ':');
- if (pch)
- shib_cookie.first = string("_shibpost_") + (pch + 1);
- }
- return shib_cookie;
-}
-
-DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const
-{
- string contentType = request.getContentType();
- if (contentType.compare("application/x-www-form-urlencoded") == 0) {
- const PropertySet* props=application.getPropertySet("Sessions");
- pair<bool,unsigned int> plimit = props->getUnsignedInt("postLimit");
- if (!plimit.first)
- plimit.second = 1024 * 1024;
- if (plimit.second == 0 || request.getContentLength() <= plimit.second) {
- CGIParser cgi(request);
- pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);
- if (params.first == params.second)
- return DDF();
- DDF child;
- DDF ret = DDF("parameters").list();
- for (; params.first != params.second; ++params.first) {
- if (!params.first->first.empty()) {
- child = DDF(params.first->first.c_str()).unsafe_string(params.first->second);
- ret.add(child);
- }
- }
- return ret;
- }
- else {
- m_log.warn("POST limit exceeded, ignoring %d bytes of posted data", request.getContentLength());
- }
- }
- else {
- m_log.info("ignoring POST data with non-standard encoding (%s)", contentType.c_str());
- }
- return DDF();
-}
+/*\r
+ * Copyright 2001-2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * AbstractHandler.cpp\r
+ *\r
+ * Base class for handlers based on a DOMPropertySet.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "Application.h"\r
+#include "ServiceProvider.h"\r
+#include "SPRequest.h"\r
+#include "handler/AbstractHandler.h"\r
+#include "handler/LogoutHandler.h"\r
+#include "remoting/ListenerService.h"\r
+#include "util/CGIParser.h"\r
+#include "util/SPConstants.h"\r
+#include "util/TemplateParameters.h"\r
+\r
+#include <vector>\r
+#include <fstream>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/PathResolver.h>\r
+#include <xmltooling/util/URLEncoder.h>\r
+\r
+\r
+#ifndef SHIBSP_LITE\r
+# include <saml/exceptions.h>\r
+# include <saml/SAMLConfig.h>\r
+# include <saml/binding/SAMLArtifact.h>\r
+# include <saml/saml1/core/Protocols.h>\r
+# include <saml/saml2/core/Protocols.h>\r
+# include <saml/saml2/metadata/Metadata.h>\r
+# include <saml/saml2/metadata/MetadataCredentialCriteria.h>\r
+# include <saml/util/SAMLConstants.h>\r
+# include <xmltooling/security/Credential.h>\r
+# include <xmltooling/security/CredentialResolver.h>\r
+# include <xmltooling/util/StorageService.h>\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+#else\r
+# include "lite/SAMLConstants.h"\r
+#endif\r
+\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/URLEncoder.h>\r
+\r
+using namespace shibsp;\r
+using namespace samlconstants;\r
+using namespace xmltooling;\r
+using namespace xercesc;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory MetadataGeneratorFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory StatusHandlerFactory;\r
+ SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SessionHandlerFactory;\r
+\r
+ void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {\r
+ static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\r
+ int r;\r
+ unsigned char b1,b2;\r
+ buf.erase();\r
+ for (unsigned int i=0; i<len; i+=4) {\r
+ r = rand();\r
+ b1 = (0x00FF & r);\r
+ b2 = (0xFF00 & r) >> 8;\r
+ buf += (DIGITS[(0xF0 & b1) >> 4 ]);\r
+ buf += (DIGITS[0x0F & b1]);\r
+ buf += (DIGITS[(0xF0 & b2) >> 4 ]);\r
+ buf += (DIGITS[0x0F & b2]);\r
+ }\r
+ }\r
+};\r
+\r
+void SHIBSP_API shibsp::registerHandlers()\r
+{\r
+ SPConfig& conf=SPConfig::getConfig();\r
+\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);\r
+ conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory);\r
+\r
+ conf.ArtifactResolutionServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2ArtifactResolutionFactory);\r
+\r
+ conf.HandlerManager.registerFactory(SAML20_BINDING_URI, AssertionLookupFactory);\r
+ conf.HandlerManager.registerFactory(METADATA_GENERATOR_HANDLER, MetadataGeneratorFactory);\r
+ conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);\r
+ conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);\r
+\r
+ conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);\r
+ conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);\r
+ conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);\r
+ conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);\r
+ conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);\r
+ conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);\r
+ conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2LogoutFactory);\r
+ conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2LogoutFactory);\r
+\r
+ conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2NameIDMgmtFactory);\r
+ conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2NameIDMgmtFactory);\r
+ conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2NameIDMgmtFactory);\r
+ conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2NameIDMgmtFactory);\r
+ conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2NameIDMgmtFactory);\r
+}\r
+\r
+Handler::Handler()\r
+{\r
+}\r
+\r
+Handler::~Handler()\r
+{\r
+}\r
+\r
+AbstractHandler::AbstractHandler(\r
+ const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper\r
+ ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {\r
+ load(e,NULL,filter,remapper);\r
+}\r
+\r
+AbstractHandler::~AbstractHandler()\r
+{\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+\r
+const char* Handler::getType() const\r
+{\r
+ return getString("type").second;\r
+}\r
+\r
+void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleDescriptor* role) const\r
+{\r
+ const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);\r
+ if (r2) {\r
+ const saml2p::Status* status = r2->getStatus();\r
+ if (status) {\r
+ const saml2p::StatusCode* sc = status->getStatusCode();\r
+ const XMLCh* code = sc ? sc->getValue() : NULL;\r
+ if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {\r
+ FatalProfileException ex("SAML response contained an error.");\r
+ annotateException(&ex, role, status); // throws it\r
+ }\r
+ }\r
+ }\r
+\r
+ const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);\r
+ if (r1) {\r
+ const saml1p::Status* status = r1->getStatus();\r
+ if (status) {\r
+ const saml1p::StatusCode* sc = status->getStatusCode();\r
+ const xmltooling::QName* code = sc ? sc->getValue() : NULL;\r
+ if (code && *code != saml1p::StatusCode::SUCCESS) {\r
+ FatalProfileException ex("SAML response contained an error.");\r
+ ex.addProperty("statusCode", code->toString().c_str());\r
+ if (sc->getStatusCode()) {\r
+ code = sc->getStatusCode()->getValue();\r
+ if (code)\r
+ ex.addProperty("statusCode2", code->toString().c_str());\r
+ }\r
+ if (status->getStatusMessage()) {\r
+ auto_ptr_char msg(status->getStatusMessage()->getMessage());\r
+ if (msg.get() && *msg.get())\r
+ ex.addProperty("statusMessage", msg.get());\r
+ }\r
+ ex.raise();\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void AbstractHandler::fillStatus(saml2p::StatusResponseType& response, const XMLCh* code, const XMLCh* subcode, const char* msg) const\r
+{\r
+ saml2p::Status* status = saml2p::StatusBuilder::buildStatus();\r
+ saml2p::StatusCode* scode = saml2p::StatusCodeBuilder::buildStatusCode();\r
+ status->setStatusCode(scode);\r
+ scode->setValue(code);\r
+ if (subcode) {\r
+ saml2p::StatusCode* ssubcode = saml2p::StatusCodeBuilder::buildStatusCode();\r
+ scode->setStatusCode(ssubcode);\r
+ ssubcode->setValue(subcode);\r
+ }\r
+ if (msg) {\r
+ pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());\r
+ auto_ptr_XMLCh widemsg((flag.first && flag.second) ? msg : "Error processing request.");\r
+ saml2p::StatusMessage* sm = saml2p::StatusMessageBuilder::buildStatusMessage();\r
+ status->setStatusMessage(sm);\r
+ sm->setMessage(widemsg.get());\r
+ }\r
+ response.setStatus(status);\r
+}\r
+\r
+long AbstractHandler::sendMessage(\r
+ const MessageEncoder& encoder,\r
+ XMLObject* msg,\r
+ const char* relayState,\r
+ const char* destination,\r
+ const saml2md::RoleDescriptor* role,\r
+ const Application& application,\r
+ HTTPResponse& httpResponse,\r
+ bool signIfPossible\r
+ ) const\r
+{\r
+ const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : NULL;\r
+ const PropertySet* relyingParty = application.getRelyingParty(entity);\r
+ pair<bool,const char*> flag = signIfPossible ? make_pair(true,(const char*)"true") : relyingParty->getString("signing");\r
+ if (role && flag.first &&\r
+ (!strcmp(flag.second, "true") ||\r
+ (encoder.isUserAgentPresent() && !strcmp(flag.second, "front")) ||\r
+ (!encoder.isUserAgentPresent() && !strcmp(flag.second, "back")))) {\r
+ CredentialResolver* credResolver=application.getCredentialResolver();\r
+ if (credResolver) {\r
+ Locker credLocker(credResolver);\r
+ const Credential* cred = NULL;\r
+ pair<bool,const char*> keyName = relyingParty->getString("keyName");\r
+ pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signingAlg");\r
+ if (role) {\r
+ MetadataCredentialCriteria mcc(*role);\r
+ mcc.setUsage(Credential::SIGNING_CREDENTIAL);\r
+ if (keyName.first)\r
+ mcc.getKeyNames().insert(keyName.second);\r
+ if (sigalg.first)\r
+ mcc.setXMLAlgorithm(sigalg.second);\r
+ cred = credResolver->resolve(&mcc);\r
+ }\r
+ else {\r
+ CredentialCriteria cc;\r
+ cc.setUsage(Credential::SIGNING_CREDENTIAL);\r
+ if (keyName.first)\r
+ cc.getKeyNames().insert(keyName.second);\r
+ if (sigalg.first)\r
+ cc.setXMLAlgorithm(sigalg.second);\r
+ cred = credResolver->resolve(&cc);\r
+ }\r
+ if (cred) {\r
+ // Signed request.\r
+ return encoder.encode(\r
+ httpResponse,\r
+ msg,\r
+ destination,\r
+ entity,\r
+ relayState,\r
+ &application,\r
+ cred,\r
+ sigalg.second,\r
+ relyingParty->getXMLString("digestAlg").second\r
+ );\r
+ }\r
+ else {\r
+ m_log.warn("no signing credential resolved, leaving message unsigned");\r
+ }\r
+ }\r
+ else {\r
+ m_log.warn("no credential resolver installed, leaving message unsigned");\r
+ }\r
+ }\r
+\r
+ // Unsigned request.\r
+ return encoder.encode(httpResponse, msg, destination, entity, relayState, &application);\r
+}\r
+\r
+#endif\r
+\r
+void AbstractHandler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const\r
+{\r
+ if (relayState.empty())\r
+ return;\r
+\r
+ // No setting means just pass it by value.\r
+ pair<bool,const char*> mech=getString("relayState");\r
+ if (!mech.first || !mech.second || !*mech.second)\r
+ return;\r
+\r
+ if (!strcmp(mech.second, "cookie")) {\r
+ // Here we store the state in a cookie and send a fixed\r
+ // value so we can recognize it on the way back.\r
+ if (relayState.find("cookie:") != 0) {\r
+ const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();\r
+ pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibstate_");\r
+ string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;\r
+ // Generate a random key for the cookie name instead of the fixed name.\r
+ string rsKey;\r
+ generateRandomHex(rsKey,5);\r
+ shib_cookie.first = "_shibstate_" + rsKey;\r
+ response.setCookie(shib_cookie.first.c_str(),stateval.c_str());\r
+ relayState = "cookie:" + rsKey;\r
+ }\r
+ }\r
+ else if (strstr(mech.second,"ss:")==mech.second) {\r
+ if (relayState.find("ss:") != 0) {\r
+ mech.second+=3;\r
+ if (*mech.second) {\r
+ if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+ StorageService* storage = application.getServiceProvider().getStorageService(mech.second);\r
+ if (storage) {\r
+ string rsKey;\r
+ generateRandomHex(rsKey,5);\r
+ if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))\r
+ throw IOException("Attempted to insert duplicate storage key.");\r
+ relayState = string(mech.second-3) + ':' + rsKey;\r
+ }\r
+ else {\r
+ m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", mech.second);\r
+ relayState.erase();\r
+ }\r
+#endif\r
+ }\r
+ else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+ DDF out,in = DDF("set::RelayState").structure();\r
+ in.addmember("id").string(mech.second);\r
+ in.addmember("value").unsafe_string(relayState.c_str());\r
+ DDFJanitor jin(in),jout(out);\r
+ out = application.getServiceProvider().getListenerService()->send(in);\r
+ if (!out.isstring())\r
+ throw IOException("StorageService-backed RelayState mechanism did not return a state key.");\r
+ relayState = string(mech.second-3) + ':' + out.string();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));\r
+}\r
+\r
+void AbstractHandler::recoverRelayState(\r
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear\r
+ ) const\r
+{\r
+ SPConfig& conf = SPConfig::getConfig();\r
+\r
+ // Look for StorageService-backed state of the form "ss:SSID:key".\r
+ const char* state = relayState.c_str();\r
+ if (strstr(state,"ss:")==state) {\r
+ state += 3;\r
+ const char* key = strchr(state,':');\r
+ if (key) {\r
+ string ssid = relayState.substr(3, key - state);\r
+ key++;\r
+ if (!ssid.empty() && *key) {\r
+ if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+ StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());\r
+ if (storage) {\r
+ ssid = key;\r
+ if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {\r
+ if (clear)\r
+ storage->deleteString("RelayState",ssid.c_str());\r
+ return;\r
+ }\r
+ else\r
+ relayState.erase();\r
+ }\r
+ else {\r
+ m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());\r
+ relayState.erase();\r
+ }\r
+#endif\r
+ }\r
+ else if (conf.isEnabled(SPConfig::InProcess)) {\r
+ DDF out,in = DDF("get::RelayState").structure();\r
+ in.addmember("id").string(ssid.c_str());\r
+ in.addmember("key").string(key);\r
+ in.addmember("clear").integer(clear ? 1 : 0);\r
+ DDFJanitor jin(in),jout(out);\r
+ out = application.getServiceProvider().getListenerService()->send(in);\r
+ if (!out.isstring()) {\r
+ m_log.error("StorageService-backed RelayState mechanism did not return a state value.");\r
+ relayState.erase();\r
+ }\r
+ else {\r
+ relayState = out.string();\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Look for cookie-backed state of the form "cookie:key".\r
+ if (strstr(state,"cookie:")==state) {\r
+ state += 7;\r
+ if (*state) {\r
+ // Pull the value from the "relay state" cookie.\r
+ pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");\r
+ relay_cookie.first = string("_shibstate_") + state;\r
+ state = request.getCookie(relay_cookie.first.c_str());\r
+ if (state && *state) {\r
+ // URL-decode the value.\r
+ char* rscopy=strdup(state);\r
+ XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);\r
+ relayState = rscopy;\r
+ free(rscopy);\r
+\r
+ if (clear) {\r
+ string exp(relay_cookie.second);\r
+ exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";\r
+ response.setCookie(relay_cookie.first.c_str(), exp.c_str());\r
+ }\r
+ return;\r
+ }\r
+ }\r
+\r
+ relayState.erase();\r
+ }\r
+\r
+ // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).\r
+ if (relayState.empty() || relayState == "default" || relayState == "cookie") {\r
+ pair<bool,const char*> homeURL=application.getString("homeURL");\r
+ if (homeURL.first)\r
+ relayState=homeURL.second;\r
+ else {\r
+ // Compute a URL to the root of the site.\r
+ int port = request.getPort();\r
+ const char* scheme = request.getScheme();\r
+ relayState = string(scheme) + "://" + request.getHostname();\r
+ if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {\r
+ ostringstream portstr;\r
+ portstr << port;\r
+ relayState += ":" + portstr.str();\r
+ }\r
+ relayState += '/';\r
+ }\r
+ }\r
+}\r
+\r
+void AbstractHandler::preservePostData(\r
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState\r
+ ) const\r
+{\r
+#ifdef HAVE_STRCASECMP\r
+ if (strcasecmp(request.getMethod(), "POST")) return;\r
+#else\r
+ if (stricmp(request.getMethod(), "POST")) return;\r
+#endif\r
+\r
+ // No specs mean no save.\r
+ const PropertySet* props=application.getPropertySet("Sessions");\r
+ pair<bool,const char*> mech = props->getString("postData");\r
+ if (!mech.first) {\r
+ m_log.info("postData property not supplied, form data will not be preserved across SSO");\r
+ return;\r
+ }\r
+\r
+ DDF postData = getPostData(application, request);\r
+ if (postData.isnull())\r
+ return;\r
+\r
+ if (strstr(mech.second,"ss:") == mech.second) {\r
+ mech.second+=3;\r
+ if (!*mech.second) {\r
+ postData.destroy();\r
+ throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3));\r
+ }\r
+\r
+ string postkey;\r
+ if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {\r
+ DDFJanitor postjan(postData);\r
+#ifndef SHIBSP_LITE\r
+ StorageService* storage = application.getServiceProvider().getStorageService(mech.second);\r
+ if (storage) {\r
+ // Use a random key\r
+ string rsKey;\r
+ SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+ rsKey = SAMLArtifact::toHex(rsKey);\r
+ ostringstream out;\r
+ out << postData;\r
+ if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))\r
+ throw IOException("Attempted to insert duplicate storage key.");\r
+ postkey = string(mech.second-3) + ':' + rsKey;\r
+ }\r
+ else {\r
+ m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second);\r
+ }\r
+#endif\r
+ }\r
+ else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+ DDF out,in = DDF("set::PostData").structure();\r
+ DDFJanitor jin(in),jout(out);\r
+ in.addmember("id").string(mech.second);\r
+ in.add(postData);\r
+ out = application.getServiceProvider().getListenerService()->send(in);\r
+ if (!out.isstring())\r
+ throw IOException("StorageService-backed PostData mechanism did not return a state key.");\r
+ postkey = string(mech.second-3) + ':' + out.string();\r
+ }\r
+\r
+ // Set a cookie with key info.\r
+ pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);\r
+ postkey += shib_cookie.second;\r
+ response.setCookie(shib_cookie.first.c_str(), postkey.c_str());\r
+ }\r
+ else {\r
+ postData.destroy();\r
+ throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second));\r
+ }\r
+}\r
+\r
+DDF AbstractHandler::recoverPostData(\r
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState\r
+ ) const\r
+{\r
+ // First we need the post recovery cookie.\r
+ pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);\r
+ const char* cookie = request.getCookie(shib_cookie.first.c_str());\r
+ if (!cookie || !*cookie)\r
+ return DDF();\r
+\r
+ // Clear the cookie.\r
+ string exp(shib_cookie.second);\r
+ exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";\r
+ response.setCookie(shib_cookie.first.c_str(), exp.c_str());\r
+\r
+ // Look for StorageService-backed state of the form "ss:SSID:key".\r
+ const char* state = cookie;\r
+ if (strstr(state, "ss:") == state) {\r
+ state += 3;\r
+ const char* key = strchr(state, ':');\r
+ if (key) {\r
+ string ssid = string(cookie).substr(3, key - state);\r
+ key++;\r
+ if (!ssid.empty() && *key) {\r
+ SPConfig& conf = SPConfig::getConfig();\r
+ if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+ StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());\r
+ if (storage) {\r
+ if (storage->readString("PostData", key, &ssid) > 0) {\r
+ storage->deleteString("PostData", key);\r
+ istringstream inret(ssid);\r
+ DDF ret;\r
+ inret >> ret;\r
+ return ret;\r
+ }\r
+ else {\r
+ m_log.error("failed to recover form post data using key (%s)", key);\r
+ }\r
+ }\r
+ else {\r
+ m_log.error("storage-backed PostData with invalid StorageService ID (%s)", ssid.c_str());\r
+ }\r
+#endif\r
+ }\r
+ else if (conf.isEnabled(SPConfig::InProcess)) {\r
+ DDF in = DDF("get::PostData").structure();\r
+ DDFJanitor jin(in);\r
+ in.addmember("id").string(ssid.c_str());\r
+ in.addmember("key").string(key);\r
+ DDF out = application.getServiceProvider().getListenerService()->send(in);\r
+ if (out.islist())\r
+ return out;\r
+ out.destroy();\r
+ m_log.error("storageService-backed PostData mechanism did not return preserved data.");\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return DDF();\r
+}\r
+\r
+long AbstractHandler::sendPostResponse(\r
+ const Application& application, HTTPResponse& httpResponse, const char* url, DDF& postData\r
+ ) const\r
+{\r
+ HTTPResponse::sanitizeURL(url);\r
+\r
+ const PropertySet* props=application.getPropertySet("Sessions");\r
+ pair<bool,const char*> postTemplate = props->getString("postTemplate");\r
+ if (!postTemplate.first)\r
+ throw ConfigurationException("Missing postTemplate property, unable to recreate form post.");\r
+\r
+ string fname(postTemplate.second);\r
+ ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());\r
+ if (!infile)\r
+ throw ConfigurationException("Unable to access HTML template ($1).", params(1, fname.c_str()));\r
+ TemplateParameters respParam;\r
+ respParam.m_map["action"] = url;\r
+\r
+ // Load the parameters into objects for the template.\r
+ multimap<string,string>& collection = respParam.m_collectionMap["PostedData"];\r
+ DDF param = postData.first();\r
+ while (!param.isnull()) {\r
+ collection.insert(pair<const string,string>(param.name(), (param.string() ? param.string() : "")));\r
+ param = postData.next();\r
+ }\r
+\r
+ stringstream str;\r
+ XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam);\r
+\r
+ pair<bool,bool> postExpire = props->getBool("postExpire");\r
+\r
+ httpResponse.setContentType("text/html");\r
+ if (!postExpire.first || postExpire.second) {\r
+ httpResponse.setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");\r
+ httpResponse.setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");\r
+ httpResponse.setResponseHeader("Pragma", "no-cache");\r
+ }\r
+ return httpResponse.sendResponse(str);\r
+}\r
+\r
+pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const\r
+{\r
+ // Decorates the name of the cookie with the relay state key, if any.\r
+ // Doing so gives a better assurance that the recovered data really\r
+ // belongs to the relayed request.\r
+ pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");\r
+ if (strstr(relayState, "cookie:") == relayState) {\r
+ shib_cookie.first = string("_shibpost_") + (relayState + 7);\r
+ }\r
+ else if (strstr(relayState, "ss:") == relayState) {\r
+ const char* pch = strchr(relayState + 3, ':');\r
+ if (pch)\r
+ shib_cookie.first = string("_shibpost_") + (pch + 1);\r
+ }\r
+ return shib_cookie;\r
+}\r
+\r
+DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const\r
+{\r
+ string contentType = request.getContentType();\r
+ if (contentType.compare("application/x-www-form-urlencoded") == 0) {\r
+ const PropertySet* props=application.getPropertySet("Sessions");\r
+ pair<bool,unsigned int> plimit = props->getUnsignedInt("postLimit");\r
+ if (!plimit.first)\r
+ plimit.second = 1024 * 1024;\r
+ if (plimit.second == 0 || request.getContentLength() <= plimit.second) {\r
+ CGIParser cgi(request);\r
+ pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);\r
+ if (params.first == params.second)\r
+ return DDF("parameters").list();\r
+ DDF child;\r
+ DDF ret = DDF("parameters").list();\r
+ for (; params.first != params.second; ++params.first) {\r
+ if (!params.first->first.empty()) {\r
+ child = DDF(params.first->first.c_str()).unsafe_string(params.first->second);\r
+ ret.add(child);\r
+ }\r
+ }\r
+ return ret;\r
+ }\r
+ else {\r
+ m_log.warn("POST limit exceeded, ignoring %d bytes of posted data", request.getContentLength());\r
+ }\r
+ }\r
+ else {\r
+ m_log.info("ignoring POST data with non-standard encoding (%s)", contentType.c_str());\r
+ }\r
+ return DDF();\r
+}\r
*/
#include "internal.h"
-#include "Application.h"
#include "exceptions.h"
+#include "Application.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AssertionConsumerService.h"
#include "util/SPConstants.h"
# include "attribute/resolver/ResolutionContext.h"
# include "metadata/MetadataProviderCriteria.h"
# include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
# include <saml/saml1/core/Assertions.h>
+# include <saml/saml2/metadata/Metadata.h>
# include <saml/util/CommonDomainCookie.h>
using namespace samlconstants;
using opensaml::saml2md::MetadataProvider;
using namespace xmltooling;
using namespace std;
-AssertionConsumerService::AssertionConsumerService(const DOMElement* e, const char* appId, Category& log)
- : AbstractHandler(e, log)
+AssertionConsumerService::AssertionConsumerService(
+ const DOMElement* e, const char* appId, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
+ ) : AbstractHandler(e, log, filter, remapper)
#ifndef SHIBSP_LITE
,m_decoder(NULL), m_role(samlconstants::SAML20MD_NS, opensaml::saml2md::IDPSSODescriptor::LOCAL_NAME)
#endif
#ifndef SHIBSP_LITE
+const char* AssertionConsumerService::getType() const
+{
+ return "AssertionConsumerService";
+}
+
void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const
{
const char* loc = getString("Location").second;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
-#include "Application.h"
#include "exceptions.h"
+#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCacheEx.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#include "util/SPConstants.h"
+#ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
+# include <saml/Assertion.h>
+# include <xmltooling/util/XMLHelper.h>
+using namespace opensaml;
+#endif
+
using namespace shibspconstants;
using namespace shibsp;
-using namespace opensaml;
using namespace xmltooling;
using namespace std;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/LogoutHandler.h"
if (!session_id.empty()) {
// Do back channel notification.
vector<string> sessions(1, session_id);
- if (!notifyBackChannel(app, request.getRequestURL(), sessions, true)) {
- app.getServiceProvider().getSessionCache()->remove(app, request, &request);
- return sendLogoutPage(app, request, request, true, "Partial logout failure.");
- }
- request.getServiceProvider().getSessionCache()->remove(app, request, &request);
+ bool result = notifyBackChannel(app, request.getRequestURL(), sessions, true);
+ app.getServiceProvider().getSessionCache()->remove(app, request, &request);
+ if (!result)
+ return sendLogoutPage(app, request, request, "partial");
}
// Route back to return location specified, or use the local template.
const char* dest = request.getParameter("return");
if (dest)
return make_pair(true, request.sendRedirect(dest));
- return sendLogoutPage(app, request, request, true, "Logout was successful.");
+ return sendLogoutPage(app, request, request, "local");
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
+#include "SPRequest.h"
#include "handler/LogoutHandler.h"
#include "util/TemplateParameters.h"
using namespace xmltooling;
using namespace std;
+LogoutHandler::LogoutHandler() : m_initiator(true)
+{
+}
+
+LogoutHandler::~LogoutHandler()
+{
+}
+
pair<bool,long> LogoutHandler::sendLogoutPage(
const Application& application, const HTTPRequest& request, HTTPResponse& response, bool local, const char* status
) const
{
+ return sendLogoutPage(application, request, response, local ? "local" : "global");
+}
+
+pair<bool,long> LogoutHandler::sendLogoutPage(
+ const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* type
+ ) const
+{
+ string tname = string(type) + "Logout";
const PropertySet* props = application.getPropertySet("Errors");
- pair<bool,const char*> prop = props ? props->getString(local ? "localLogout" : "globalLogout") : pair<bool,const char*>(false,NULL);
- if (prop.first) {
- response.setContentType("text/html");
- response.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
- response.setResponseHeader("Cache-Control","private,no-store,no-cache");
- string fname(prop.second);
- ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
- if (!infile)
- throw ConfigurationException("Unable to access $1 HTML template.", params(1,local ? "localLogout" : "globalLogout"));
- TemplateParameters tp;
- tp.m_request = &request;
- tp.setPropertySet(props);
- if (status)
- tp.m_map["logoutStatus"] = status;
- stringstream str;
- XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp);
- return make_pair(true,response.sendResponse(str));
+ pair<bool,const char*> prop = props ? props->getString(tname.c_str()) : pair<bool,const char*>(false,NULL);
+ if (!prop.first) {
+ tname += ".html";
+ prop.second = tname.c_str();
}
- prop = application.getString("homeURL");
- if (!prop.first)
- prop.second = "/";
- return make_pair(true,response.sendRedirect(prop.second));
+ response.setContentType("text/html");
+ response.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
+ response.setResponseHeader("Cache-Control","private,no-store,no-cache");
+ string fname(prop.second);
+ ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
+ if (!infile)
+ throw ConfigurationException("Unable to access $1 HTML template.", params(1,prop.second));
+ TemplateParameters tp;
+ tp.m_request = &request;
+ tp.setPropertySet(props);
+ tp.m_map["logoutStatus"] = "Logout completed successfully."; // Backward compatibility.
+ stringstream str;
+ XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp);
+ return make_pair(true,response.sendResponse(str));
}
pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "Application.h"
#include "exceptions.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#ifndef SHIBSP_LITE
# include "metadata/MetadataProviderCriteria.h"
+# include <saml/exceptions.h>
+# include <saml/SAMLConfig.h>
+# include <saml/signature/ContentReference.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
+# include <xmltooling/XMLToolingConfig.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/security/CredentialCriteria.h>
+# include <xmltooling/signature/Signature.h>
+# include <xmltooling/util/ParserPool.h>
# include <xmltooling/util/PathResolver.h>
+# include <xercesc/framework/LocalFileInputSource.hpp>
+# include <xercesc/framework/Wrapper4InputSource.hpp>
#endif
-#include <xercesc/framework/LocalFileInputSource.hpp>
-#include <xercesc/framework/Wrapper4InputSource.hpp>
using namespace shibsp;
#ifndef SHIBSP_LITE
entity = EntityDescriptorBuilder::buildEntityDescriptor();
}
+ if (!entity->getID())
+ entity->setID(SAMLConfig::getConfig().generateIdentifier());
+
auto_ptr<EntityDescriptor> wrapper(entity);
pair<bool,unsigned int> cache = getUnsignedInt("cacheDuration");
if (cache.first) {
#include "Application.h"
#include "exceptions.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/RemotedHandler.h"
#include <algorithm>
}
}
+RemotedHandler::RemotedHandler()
+{
+}
+
RemotedHandler::~RemotedHandler()
{
SPConfig& conf = SPConfig::getConfig();
#include "handler/AssertionConsumerService.h"
#ifndef SHIBSP_LITE
-# include "exceptions.h"
# include "Application.h"
# include "ServiceProvider.h"
# include "SessionCache.h"
# include "attribute/resolver/ResolutionContext.h"
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
+# include <saml/binding/SecurityPolicy.h>
+# include <saml/binding/SecurityPolicyRule.h>
# include <saml/saml1/core/Assertions.h>
# include <saml/saml1/core/Protocols.h>
# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/io/HTTPRequest.h>
+# include <xmltooling/util/DateTime.h>
using namespace opensaml::saml1;
using namespace opensaml::saml1p;
using namespace opensaml;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
-#include "Application.h"
#include "exceptions.h"
+#include "Application.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#include "util/SPConstants.h"
#ifndef SHIBSP_LITE
# include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
# include <saml/binding/ArtifactMap.h>
# include <saml/binding/MessageEncoder.h>
using namespace opensaml::saml2md;
using namespace opensaml::saml2p;
using namespace opensaml::saml2;
+using namespace opensaml;
using namespace samlconstants;
#endif
using namespace shibspconstants;
using namespace shibsp;
-using namespace opensaml;
using namespace soap11;
using namespace xmltooling;
using namespace std;
#include "handler/AssertionConsumerService.h"
#ifndef SHIBSP_LITE
-# include "exceptions.h"
# include "Application.h"
# include "ServiceProvider.h"
# include "SessionCache.h"
# include "attribute/resolver/ResolutionContext.h"
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
+# include <saml/binding/SecurityPolicyRule.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
# include <saml/saml2/profile/SAML2AssertionPolicy.h>
+# include <xmltooling/XMLToolingConfig.h>
+# include <xmltooling/io/HTTPRequest.h>
+# include <xmltooling/util/DateTime.h>
using namespace opensaml::saml2;
using namespace opensaml::saml2p;
using namespace opensaml::saml2md;
#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/LogoutHandler.h"
#include "util/SPConstants.h"
# include "metadata/MetadataProviderCriteria.h"
# include "util/TemplateParameters.h"
# include <fstream>
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
# include <xmltooling/util/URLEncoder.h>
using namespace opensaml::saml2;
// If relay state is set, recover the original return URL.
if (!relayState.empty())
recoverRelayState(application, request, response, relayState);
+
+ // Check for partial logout.
+ const StatusCode* sc = logoutResponse->getStatus() ? logoutResponse->getStatus()->getStatusCode() : NULL;
+ sc = sc ? sc->getStatusCode() : NULL;
+ if (sc && XMLString::equals(sc->getValue(), StatusCode::PARTIAL_LOGOUT))
+ return sendLogoutPage(application, request, response, "partial");
+
if (!relayState.empty())
return make_pair(true, response.sendRedirect(relayState.c_str()));
- // Return template for completion of global logout, or redirect to homeURL.
- return sendLogoutPage(application, request, response, false, "Global logout completed.");
+ // Return template for completion of logout.
+ return sendLogoutPage(application, request, response, "global");
}
FatalProfileException ex("Incoming message was not a samlp:LogoutRequest or samlp:LogoutResponse.");
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/LogoutHandler.h"
#ifndef SHIBSP_LITE
# include "binding/SOAPClient.h"
# include "metadata/MetadataProviderCriteria.h"
+# include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/binding/SAML2SOAPClient.h>
# include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/signature/ContentReference.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/signature/Signature.h>
using namespace opensaml::saml2;
using namespace opensaml::saml2p;
using namespace opensaml::saml2md;
if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
session->unlock();
application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
- return sendLogoutPage(application, httpRequest, httpResponse, true, "Partial logout failure.");
+ return sendLogoutPage(application, httpRequest, httpResponse, "partial");
}
#ifndef SHIBSP_LITE
}
}
if (!ep || !encoder) {
- m_log.warn("no compatible front channel SingleLogoutService, trying back channel...");
+ m_log.debug("no compatible front channel SingleLogoutService, trying back channel...");
shibsp::SecurityPolicy policy(application);
shibsp::SOAPClient soaper(policy);
MetadataCredentialCriteria mcc(*role);
}
}
+ // No answer at all?
if (!logoutResponse) {
- ret = sendLogoutPage(
- application, httpRequest, httpResponse, false,
- endpoints.empty() ?
- "Identity provider does not support SAML 2 Single Logout protocol." :
- "Identity provider did not respond to logout request."
- );
+ if (endpoints.empty())
+ m_log.info("IdP doesn't support single logout protocol over a compatible binding");
+ else
+ m_log.warn("IdP didn't respond to logout request");
+ ret = sendLogoutPage(application, httpRequest, httpResponse, "partial");
}
- else if (!logoutResponse->getStatus() || !logoutResponse->getStatus()->getStatusCode() ||
- !XMLString::equals(logoutResponse->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
- delete logoutResponse;
- ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Identity provider returned a SAML error in response to logout request.");
+
+ // Check the status, looking for non-success or a partial logout code.
+ const StatusCode* sc = logoutResponse->getStatus() ? logoutResponse->getStatus()->getStatusCode() : NULL;
+ bool partial = (!sc || !XMLString::equals(sc->getValue(), StatusCode::SUCCESS));
+ if (!partial) {
+ // Success, but still need to check for partial.
+ partial = XMLString::equals(sc->getStatusCode()->getValue(), StatusCode::PARTIAL_LOGOUT);
}
+ delete logoutResponse;
+ if (partial)
+ ret = sendLogoutPage(application, httpRequest, httpResponse, "partial");
else {
- delete logoutResponse;
const char* returnloc = httpRequest.getParameter("return");
if (returnloc) {
ret.second = httpResponse.sendRedirect(returnloc);
ret.first = true;
}
- ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Logout completed successfully.");
+ ret = sendLogoutPage(application, httpRequest, httpResponse, "global");
}
if (session) {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#include "util/SPConstants.h"
# include "security/SecurityPolicy.h"
# include "util/TemplateParameters.h"
# include <fstream>
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
# include <xmltooling/util/URLEncoder.h>
using namespace opensaml::saml2;
# include <saml/saml2/metadata/EndpointManager.h>
# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/util/SAMLConstants.h>
using namespace opensaml::saml2;
using namespace opensaml::saml2p;
using namespace opensaml::saml2md;
#else
+# include "lite/SAMLConstants.h"
#include <xercesc/util/XMLUniDefs.hpp>
#endif
bool forceAuthn,
const char* authnContextClassRef,
const char* authnContextComparison,
+ const char* NameIDFormat,
+ const char* SPNameQualifier,
string& relayState
) const;
};
SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2")), m_appId(appId),
+ : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2"), NULL, &m_remapper), m_appId(appId),
m_paosNS(samlconstants::PAOS_NS), m_ecpNS(samlconstants::SAML20ECP_NS), m_paosBinding(samlconstants::SAML20_BINDING_PAOS)
{
static const XMLCh ECP[] = UNICODE_LITERAL_3(E,C,P);
string postData;
const Handler* ACS=NULL;
const char* option;
- pair<bool,const char*> acClass;
- pair<bool,const char*> acComp;
+ pair<bool,const char*> acClass, acComp, nidFormat, spQual;
bool isPassive=false,forceAuthn=false;
const Application& app=request.getApplication();
if (option) {
ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
else if (ECP && !XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_PAOS)) {
request.log(SPRequest::SPWarn, "acsIndex in request referenced a non-PAOS ACS, using default ACS location");
ACS = NULL;
acComp.first = true;
else
acComp = getString("authnContextComparison");
+
+ if (nidFormat.second = request.getParameter("NameIDFormat"))
+ nidFormat.first = true;
+ else
+ nidFormat = getString("NameIDFormat");
+
+ if (spQual.second = request.getParameter("SPNameQualifier"))
+ spQual.first = true;
+ else
+ spQual = getString("SPNameQualifier");
}
else {
// We're running as a "virtual handler" from within the filter.
acComp = settings->getString("authnContextComparison");
if (!acComp.first)
acComp = getString("authnContextComparison");
+ nidFormat = settings->getString("NameIDFormat");
+ if (!nidFormat.first)
+ nidFormat = getString("NameIDFormat");
+ spQual = settings->getString("SPNameQualifier");
+ if (!spQual.first)
+ spQual = getString("SPNameQualifier");
}
if (ECP)
ACS = handlers.front();
}
else {
- pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+ pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
if (index.first) {
ACS = app.getAssertionConsumerServiceByIndex(index.second);
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
}
if (!ACS)
ACS = app.getDefaultAssertionConsumerService();
if (ACSbinding.first) {
pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
- m_log.info("configured or requested ACS has non-SAML 2.0 binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 2.0 binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
}
else if (strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST) &&
strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) &&
strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN)) {
- m_log.info("configured or requested ACS has non-SAML 2.0 binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 2.0 binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
}
}
}
isPassive, forceAuthn,
acClass.first ? acClass.second : NULL,
acComp.first ? acComp.second : NULL,
+ nidFormat.first ? nidFormat.second : NULL,
+ spQual.first ? spQual.second : NULL,
target
);
}
isPassive, forceAuthn,
acClass.first ? acClass.second : NULL,
acComp.first ? acComp.second : NULL,
+ nidFormat.first ? nidFormat.second : NULL,
+ spQual.first ? spQual.second : NULL,
target
);
}
in.addmember("authnContextClassRef").string(acClass.second);
if (acComp.first)
in.addmember("authnContextComparison").string(acComp.second);
+ if (nidFormat.first)
+ in.addmember("NameIDFormat").string(nidFormat.second);
+ if (spQual.first)
+ in.addmember("SPNameQualifier").string(spQual.second);
if (acsByIndex.first && acsByIndex.second) {
if (ACS) {
// Determine index to use.
in["acsLocation"].string(), bind.get(),
in["isPassive"].integer()==1, in["forceAuthn"].integer()==1,
in["authnContextClassRef"].string(), in["authnContextComparison"].string(),
+ in["NameIDFormat"].string(), in["SPNameQualifier"].string(),
relayState
);
if (!ret.isstruct())
bool forceAuthn,
const char* authnContextClassRef,
const char* authnContextComparison,
+ const char* NameIDFormat,
+ const char* SPNameQualifier,
string& relayState
) const
{
req->setNameIDPolicy(namepol);
namepol->AllowCreate(true);
}
+ if (NameIDFormat && *NameIDFormat) {
+ auto_ptr_XMLCh wideform(NameIDFormat);
+ req->getNameIDPolicy()->setFormat(wideform.get());
+ }
+ if (SPNameQualifier && *SPNameQualifier) {
+ auto_ptr_XMLCh widequal(SPNameQualifier);
+ req->getNameIDPolicy()->setSPNameQualifier(widequal.get());
+ }
if (authnContextClassRef || authnContextComparison) {
RequestedAuthnContext* reqContext = req->getRequestedAuthnContext();
if (!reqContext) {
using namespace std;
#ifndef SHIBSP_LITE
+# include <saml/saml2/metadata/Metadata.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
using namespace opensaml::saml2md;
#endif
const char* option;
bool isPassive=false;
const Application& app=request.getApplication();
+ pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
if (isHandler) {
option = request.getParameter("SAMLDS");
option = request.getParameter("isPassive");
if (option)
isPassive = !strcmp(option,"true");
+
+ option = request.getParameter("discoveryURL");
+ if (option)
+ discoveryURL.second = option;
}
else {
// We're running as a "virtual handler" from within the filter.
target=request.getRequestURL();
pair<bool,bool> passopt = getBool("isPassive");
isPassive = passopt.first && passopt.second;
+ discoveryURL = request.getRequestSettings().first->getString("discoveryURL");
}
- m_log.debug("sending request to SAMLDS (%s)", m_url);
+ if (!discoveryURL.first)
+ discoveryURL.second = m_url;
+ m_log.debug("sending request to SAMLDS (%s)", discoveryURL.second);
// Compute the return URL. We start with a self-referential link.
string returnURL=request.getHandlerURL(target.c_str());
returnURL = returnURL + "&target=" + urlenc->encode(target.c_str());;
}
- string req=string(m_url) + (strchr(m_url,'?') ? '&' : '?') + "entityID=" + urlenc->encode(app.getString("entityID").second) +
+ string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "entityID=" + urlenc->encode(app.getString("entityID").second) +
"&return=" + urlenc->encode(returnURL.c_str());
if (m_returnParam)
req = req + "&returnIDParam=" + m_returnParam;
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory CookieSessionInitiatorFactory;
};
+map<string,string> SessionInitiator::m_remapper;
+
void SHIBSP_API shibsp::registerSessionInitiators()
{
SPConfig& conf=SPConfig::getConfig();
conf.SessionInitiatorManager.registerFactory(TRANSFORM_SESSION_INITIATOR, TransformSessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(FORM_SESSION_INITIATOR, FormSessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(COOKIE_SESSION_INITIATOR, CookieSessionInitiatorFactory);
+
+ SessionInitiator::m_remapper["defaultACSIndex"] = "acsIndex";
+}
+
+SessionInitiator::SessionInitiator()
+{
+}
+
+SessionInitiator::~SessionInitiator()
+{
+}
+
+#ifndef SHIBSP_LITE
+const char* SessionInitiator::getType() const
+{
+ return "SessionInitiator";
}
+#endif
pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
{
# include "metadata/MetadataProviderCriteria.h"
# include <saml/saml2/metadata/Metadata.h>
# include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/util/SAMLConstants.h>
+#else
+# include "lite/SAMLConstants.h"
#endif
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/URLEncoder.h>
{
public:
Shib1SessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.Shib1")), m_appId(appId) {
+ : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.Shib1"), NULL, &m_remapper), m_appId(appId) {
// If Location isn't set, defer address registration until the setParent call.
pair<bool,const char*> loc = getString("Location");
if (loc.first) {
if (option) {
ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
}
option = request.getParameter("target");
// Since we're not passing by index, we need to fully compute the return URL.
if (!ACS) {
- pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+ pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
if (index.first) {
ACS = app.getAssertionConsumerServiceByIndex(index.second);
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
}
if (!ACS)
ACS = app.getDefaultAssertionConsumerService();
if (ACSbinding.first) {
pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
- m_log.info("configured or requested ACS has non-SAML 1.x binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 1.x binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
}
else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
- m_log.info("configured or requested ACS has non-SAML 1.x binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 1.x binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
}
}
#include "Application.h"
#include "exceptions.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#include "util/CGIParser.h"
# include "SessionCache.h"
# include "metadata/MetadataProviderCriteria.h"
# include <saml/version.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/security/CredentialCriteria.h>
using namespace opensaml::saml2md;
using namespace opensaml;
using namespace xmlsignature;
#include "handler/AbstractHandler.h"
#include "handler/SessionInitiator.h"
+#ifndef SHIBSP_LITE
+# include <saml/util/SAMLConstants.h>
+#else
+# include "lite/SAMLConstants.h"
+#endif
+
#include <ctime>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/URLEncoder.h>
{
public:
WAYFSessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.WAYF")), m_url(NULL) {
+ : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.WAYF"), NULL, &m_remapper), m_url(NULL) {
pair<bool,const char*> url = getString("URL");
if (!url.first)
throw ConfigurationException("WAYF SessionInitiator requires a URL property.");
const char* option;
const Handler* ACS=NULL;
const Application& app=request.getApplication();
+ pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
if (isHandler) {
option=request.getParameter("acsIndex");
if (option) {
ACS=app.getAssertionConsumerServiceByIndex(atoi(option));
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
}
option = request.getParameter("target");
if (option)
target = option;
recoverRelayState(request.getApplication(), request, request, target, false);
+
+ option = request.getParameter("discoveryURL");
+ if (option)
+ discoveryURL.second = option;
}
else {
// We're running as a "virtual handler" from within the filter.
// The target resource is the current one and everything else is defaulted.
target=request.getRequestURL();
+ discoveryURL = request.getRequestSettings().first->getString("discoveryURL");
}
// Since we're not passing by index, we need to fully compute the return URL.
if (!ACS) {
- pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+ pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
if (index.first) {
ACS = app.getAssertionConsumerServiceByIndex(index.second);
if (!ACS)
- request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+ request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
}
if (!ACS)
ACS = app.getDefaultAssertionConsumerService();
if (ACSbinding.first) {
pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
- m_log.info("configured or requested ACS has non-SAML 1.x binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 1.x binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
}
else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
- m_log.info("configured or requested ACS has non-SAML 1.x binding");
- return make_pair(false,0L);
+ m_log.error("configured or requested ACS has non-SAML 1.x binding");
+ throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
}
}
- m_log.debug("sending request to WAYF (%s)", m_url);
+ if (!discoveryURL.first)
+ discoveryURL.second = m_url;
+ m_log.debug("sending request to WAYF (%s)", discoveryURL.second);
// Compute the ACS URL. We add the ACS location to the base handlerURL.
string ACSloc=request.getHandlerURL(target.c_str());
char timebuf[16];
sprintf(timebuf,"%lu",time(NULL));
const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
- string req=string(m_url) + (strchr(m_url,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
+ string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
"&time=" + timebuf + "&target=" + urlenc->encode(target.c_str()) +
"&providerId=" + urlenc->encode(app.getString("entityID").second);
-/*\r
- * Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * ChainingAccessControl.cpp\r
- *\r
- * Access control plugin that combines other plugins.\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
- class ChainingAccessControl : public AccessControl\r
- {\r
- public:\r
- ChainingAccessControl(const DOMElement* e);\r
-\r
- ~ChainingAccessControl() {\r
- for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
- }\r
-\r
- Lockable* lock() {\r
- for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));\r
- return this;\r
- }\r
- void unlock() {\r
- for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));\r
- }\r
-\r
- aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
- private:\r
- enum operator_t { OP_AND, OP_OR } m_op;\r
- vector<AccessControl*> m_ac;\r
- };\r
-\r
- AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)\r
- {\r
- return new ChainingAccessControl(e);\r
- }\r
-\r
- static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
- static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);\r
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);\r
- static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);\r
- static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);\r
-\r
- extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);\r
-}\r
-\r
-void SHIBSP_API shibsp::registerAccessControls()\r
-{\r
- SPConfig& conf=SPConfig::getConfig();\r
- conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);\r
- conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
- conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
-}\r
-\r
-ChainingAccessControl::ChainingAccessControl(const DOMElement* e)\r
-{\r
- const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;\r
- if (XMLString::equals(op, AND))\r
- m_op=OP_AND;\r
- else if (XMLString::equals(op, OR))\r
- m_op=OP_OR;\r
- else\r
- throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");\r
-\r
- try {\r
- e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;\r
- while (e) {\r
- auto_ptr_char type(e->getAttributeNS(NULL, _type));\r
- if (type.get() && *type.get()) {\r
- Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());\r
- m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));\r
- }\r
- e = XMLHelper::getNextSiblingElement(e, _AccessControl);\r
- }\r
- }\r
- catch (exception&) {\r
- for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
- throw;\r
- }\r
- if (m_ac.empty())\r
- throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");\r
-}\r
-\r
-AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
- switch (m_op) {\r
- case OP_AND:\r
- {\r
- for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
- if ((*i)->authorized(request, session) != shib_acl_true)\r
- return shib_acl_false;\r
- }\r
- return shib_acl_true;\r
- }\r
-\r
- case OP_OR:\r
- {\r
- for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
- if ((*i)->authorized(request,session) == shib_acl_true)\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
- }\r
- request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");\r
- return shib_acl_false;\r
-}\r
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ChainingAccessControl.cpp
+ *
+ * Access control plugin that combines other plugins.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+ class ChainingAccessControl : public AccessControl
+ {
+ public:
+ ChainingAccessControl(const DOMElement* e);
+
+ ~ChainingAccessControl() {
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+ }
+
+ Lockable* lock() {
+ for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+ return this;
+ }
+ void unlock() {
+ for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+ }
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ private:
+ enum operator_t { OP_AND, OP_OR } m_op;
+ vector<AccessControl*> m_ac;
+ };
+
+ AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
+ {
+ return new ChainingAccessControl(e);
+ }
+
+ static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+ static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+ static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);
+ static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);
+
+ extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);
+}
+
+void SHIBSP_API shibsp::registerAccessControls()
+{
+ SPConfig& conf=SPConfig::getConfig();
+ conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);
+ conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
+ conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);
+}
+
+AccessControl::AccessControl()
+{
+}
+
+AccessControl::~AccessControl()
+{
+}
+
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)
+{
+ const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;
+ if (XMLString::equals(op, AND))
+ m_op=OP_AND;
+ else if (XMLString::equals(op, OR))
+ m_op=OP_OR;
+ else
+ throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
+
+ try {
+ e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;
+ while (e) {
+ auto_ptr_char type(e->getAttributeNS(NULL, _type));
+ if (type.get() && *type.get()) {
+ Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());
+ m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));
+ }
+ e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+ }
+ }
+ catch (exception&) {
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+ throw;
+ }
+ if (m_ac.empty())
+ throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
+}
+
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+ switch (m_op) {
+ case OP_AND:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+ if ((*i)->authorized(request, session) != shib_acl_true)
+ return shib_acl_false;
+ }
+ return shib_acl_true;
+ }
+
+ case OP_OR:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+ if ((*i)->authorized(request,session) == shib_acl_true)
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ }
+ request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");
+ return shib_acl_false;
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "remoting/ListenerService.h"
#include "util/SPConstants.h"
+#include <algorithm>
+#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
+#include <xmltooling/util/DateTime.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
#ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
+# include <saml/saml2/core/Assertions.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/XMLToolingConfig.h>
# include <xmltooling/util/StorageService.h>
using namespace opensaml::saml2md;
#else
SPConfig::getConfig().SessionCacheManager.registerFactory(STORAGESERVICE_SESSION_CACHE, StorageServiceCacheFactory);
}
+Session::Session()
+{
+}
+
+Session::~Session()
+{
+}
+
void StoredSession::unmarshallAttributes() const
{
Attribute* attribute;
#endif
+SessionCache::SessionCache()
+{
+}
+
+SessionCache::~SessionCache()
+{
+}
+
+SessionCacheEx::SessionCacheEx()
+{
+}
+
+SessionCacheEx::~SessionCacheEx()
+{
+}
+
SSCache::SSCache(const DOMElement* e)
: m_log(Category::getInstance(SHIBSP_LOGCAT".SessionCache")), inproc(true), m_cacheTimeout(28800),
#ifndef SHIBSP_LITE
-/*\r
- * Copyright 2001-2007 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLAccessControl.cpp\r
- *\r
- * XML-based access control syntax\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-#include "attribute/Attribute.h"\r
-\r
-#include <xmltooling/util/ReloadableXMLFile.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xercesc/util/regx/RegularExpression.hpp>\r
-\r
-#ifndef HAVE_STRCASECMP\r
-# define strcasecmp _stricmp\r
-#endif\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
- class Rule : public AccessControl\r
- {\r
- public:\r
- Rule(const DOMElement* e);\r
- ~Rule() {}\r
-\r
- Lockable* lock() {return this;}\r
- void unlock() {}\r
-\r
- aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
- private:\r
- string m_alias;\r
- vector <string> m_vals;\r
- };\r
-\r
- class RuleRegex : public AccessControl\r
- {\r
- public:\r
- RuleRegex(const DOMElement* e);\r
- ~RuleRegex() {\r
- delete m_re;\r
- }\r
-\r
- Lockable* lock() {return this;}\r
- void unlock() {}\r
-\r
- aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
- private:\r
- string m_alias;\r
- auto_arrayptr<char> m_exp;\r
- RegularExpression* m_re;\r
- };\r
-\r
- class Operator : public AccessControl\r
- {\r
- public:\r
- Operator(const DOMElement* e);\r
- ~Operator();\r
-\r
- Lockable* lock() {return this;}\r
- void unlock() {}\r
-\r
- aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
- private:\r
- enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
- vector<AccessControl*> m_operands;\r
- };\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( push )\r
- #pragma warning( disable : 4250 )\r
-#endif\r
-\r
- class XMLAccessControl : public AccessControl, public ReloadableXMLFile\r
- {\r
- public:\r
- XMLAccessControl(const DOMElement* e)\r
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {\r
- load(); // guarantees an exception or the policy is loaded\r
- }\r
-\r
- ~XMLAccessControl() {\r
- delete m_rootAuthz;\r
- }\r
-\r
- aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
- protected:\r
- pair<bool,DOMElement*> load();\r
-\r
- private:\r
- AccessControl* m_rootAuthz;\r
- };\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( pop )\r
-#endif\r
-\r
- AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)\r
- {\r
- return new XMLAccessControl(e);\r
- }\r
-\r
- static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
- static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);\r
- static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i);\r
- static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t);\r
- static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e);\r
- static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T);\r
- static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);\r
- static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);\r
- static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e);\r
- static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
-}\r
-\r
-Rule::Rule(const DOMElement* e)\r
-{\r
- auto_ptr_char req(e->getAttributeNS(NULL,require));\r
- if (!req.get() || !*req.get())\r
- throw ConfigurationException("Access control rule missing require attribute");\r
- m_alias=req.get();\r
-\r
- auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
- if (!vals.get())\r
- return;\r
-\r
- const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
- if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
- if (*vals.get())\r
- m_vals.push_back(vals.get());\r
- return;\r
- }\r
-\r
-#ifdef HAVE_STRTOK_R\r
- char* pos=NULL;\r
- const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
-#else\r
- const char* token=strtok(const_cast<char*>(vals.get())," ");\r
-#endif\r
- while (token) {\r
- m_vals.push_back(token);\r
-#ifdef HAVE_STRTOK_R\r
- token=strtok_r(NULL," ",&pos);\r
-#else\r
- token=strtok(NULL," ");\r
-#endif\r
- }\r
-}\r
-\r
-AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const\r
-{\r
- // We can make this more complex later using pluggable comparison functions,\r
- // but for now, just a straight port to the new Attribute API.\r
-\r
- // Map alias in rule to the attribute.\r
- if (!session) {\r
- request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
- return shib_acl_false;\r
- }\r
-\r
- if (m_alias == "valid-user") {\r
- if (session) {\r
- request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
- if (m_alias == "user") {\r
- for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
- if (*i == request.getRemoteUser()) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- }\r
- return shib_acl_false;\r
- }\r
- else if (m_alias == "authnContextClassRef") {\r
- const char* ref = session->getAuthnContextClassRef();\r
- for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
- if (!strcmp(i->c_str(),ref)) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- }\r
- return shib_acl_false;\r
- }\r
- else if (m_alias == "authnContextDeclRef") {\r
- const char* ref = session->getAuthnContextDeclRef();\r
- for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
- if (!strcmp(i->c_str(),ref)) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- }\r
- return shib_acl_false;\r
- }\r
-\r
- // Find the attribute(s) matching the require rule.\r
- pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
- session->getIndexedAttributes().equal_range(m_alias);\r
- if (attrs.first == attrs.second) {\r
- request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
- return shib_acl_false;\r
- }\r
-\r
- for (; attrs.first != attrs.second; ++attrs.first) {\r
- bool caseSensitive = attrs.first->second->isCaseSensitive();\r
-\r
- // Now we have to intersect the attribute's values against the rule's list.\r
- const vector<string>& vals = attrs.first->second->getSerializedValues();\r
- for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
- for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
- if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- }\r
- }\r
- }\r
-\r
- return shib_acl_false;\r
-}\r
-\r
-RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))\r
-{\r
- auto_ptr_char req(e->getAttributeNS(NULL,require));\r
- if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
- throw ConfigurationException("Access control rule missing require attribute or element content.");\r
- m_alias=req.get();\r
-\r
- const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
- bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
- try {\r
- m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));\r
- }\r
- catch (XMLException& ex) {\r
- auto_ptr_char tmp(ex.getMessage());\r
- throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));\r
- }\r
-}\r
-\r
-AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const\r
-{\r
- // Map alias in rule to the attribute.\r
- if (!session) {\r
- request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
- return shib_acl_false;\r
- }\r
-\r
- if (m_alias == "valid-user") {\r
- if (session) {\r
- request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
-\r
- try {\r
- if (m_alias == "user") {\r
- if (m_re->matches(request.getRemoteUser().c_str())) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
- else if (m_alias == "authnContextClassRef") {\r
- if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
- else if (m_alias == "authnContextDeclRef") {\r
- if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
-\r
- // Find the attribute(s) matching the require rule.\r
- pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
- session->getIndexedAttributes().equal_range(m_alias);\r
- if (attrs.first == attrs.second) {\r
- request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
- return shib_acl_false;\r
- }\r
-\r
- for (; attrs.first != attrs.second; ++attrs.first) {\r
- // Now we have to intersect the attribute's values against the regular expression.\r
- const vector<string>& vals = attrs.first->second->getSerializedValues();\r
- for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
- if (m_re->matches(j->c_str())) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");\r
- return shib_acl_true;\r
- }\r
- }\r
- }\r
- }\r
- catch (XMLException& ex) {\r
- auto_ptr_char tmp(ex.getMessage());\r
- request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
- }\r
-\r
- return shib_acl_false;\r
-}\r
-\r
-Operator::Operator(const DOMElement* e)\r
-{\r
- if (XMLString::equals(e->getLocalName(),NOT))\r
- m_op=OP_NOT;\r
- else if (XMLString::equals(e->getLocalName(),AND))\r
- m_op=OP_AND;\r
- else if (XMLString::equals(e->getLocalName(),OR))\r
- m_op=OP_OR;\r
- else\r
- throw ConfigurationException("Unrecognized operator in access control rule");\r
-\r
- try {\r
- e=XMLHelper::getFirstChildElement(e);\r
- if (XMLString::equals(e->getLocalName(),_Rule))\r
- m_operands.push_back(new Rule(e));\r
- else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
- m_operands.push_back(new RuleRegex(e));\r
- else\r
- m_operands.push_back(new Operator(e));\r
-\r
- if (m_op==OP_NOT)\r
- return;\r
-\r
- e=XMLHelper::getNextSiblingElement(e);\r
- while (e) {\r
- if (XMLString::equals(e->getLocalName(),_Rule))\r
- m_operands.push_back(new Rule(e));\r
- else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
- m_operands.push_back(new RuleRegex(e));\r
- else\r
- m_operands.push_back(new Operator(e));\r
- e=XMLHelper::getNextSiblingElement(e);\r
- }\r
- }\r
- catch (exception&) {\r
- for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
- throw;\r
- }\r
-}\r
-\r
-Operator::~Operator()\r
-{\r
- for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
-}\r
-\r
-AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const\r
-{\r
- switch (m_op) {\r
- case OP_NOT:\r
- switch (m_operands.front()->authorized(request,session)) {\r
- case shib_acl_true:\r
- return shib_acl_false;\r
- case shib_acl_false:\r
- return shib_acl_true;\r
- default:\r
- return shib_acl_indeterminate;\r
- }\r
-\r
- case OP_AND:\r
- {\r
- for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
- if ((*i)->authorized(request,session) != shib_acl_true)\r
- return shib_acl_false;\r
- }\r
- return shib_acl_true;\r
- }\r
-\r
- case OP_OR:\r
- {\r
- for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
- if ((*i)->authorized(request,session) == shib_acl_true)\r
- return shib_acl_true;\r
- }\r
- return shib_acl_false;\r
- }\r
- }\r
- request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");\r
- return shib_acl_false;\r
-}\r
-\r
-pair<bool,DOMElement*> XMLAccessControl::load()\r
-{\r
- // Load from source using base class.\r
- pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
-\r
- // If we own it, wrap it.\r
- XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
-\r
- // Check for AccessControl wrapper and drop a level.\r
- if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
- raw.second = XMLHelper::getFirstChildElement(raw.second);\r
-\r
- AccessControl* authz;\r
- if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
- authz=new Rule(raw.second);\r
- else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))\r
- authz=new RuleRegex(raw.second);\r
- else\r
- authz=new Operator(raw.second);\r
-\r
- delete m_rootAuthz;\r
- m_rootAuthz = authz;\r
- return make_pair(false,(DOMElement*)NULL);\r
-}\r
-\r
-AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
- return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * XMLAccessControl.cpp
+ *
+ * XML-based access control syntax
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+#include "attribute/Attribute.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+
+#ifndef HAVE_STRCASECMP
+# define strcasecmp _stricmp
+#endif
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+ class Rule : public AccessControl
+ {
+ public:
+ Rule(const DOMElement* e);
+ ~Rule() {}
+
+ Lockable* lock() {return this;}
+ void unlock() {}
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ private:
+ string m_alias;
+ vector <string> m_vals;
+ };
+
+ class RuleRegex : public AccessControl
+ {
+ public:
+ RuleRegex(const DOMElement* e);
+ ~RuleRegex() {
+ delete m_re;
+ }
+
+ Lockable* lock() {return this;}
+ void unlock() {}
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ private:
+ string m_alias;
+ auto_arrayptr<char> m_exp;
+ RegularExpression* m_re;
+ };
+
+ class Operator : public AccessControl
+ {
+ public:
+ Operator(const DOMElement* e);
+ ~Operator();
+
+ Lockable* lock() {return this;}
+ void unlock() {}
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ private:
+ enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
+ vector<AccessControl*> m_operands;
+ };
+
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4250 )
+#endif
+
+ class XMLAccessControl : public AccessControl, public ReloadableXMLFile
+ {
+ public:
+ XMLAccessControl(const DOMElement* e)
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {
+ load(); // guarantees an exception or the policy is loaded
+ }
+
+ ~XMLAccessControl() {
+ delete m_rootAuthz;
+ }
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ protected:
+ pair<bool,DOMElement*> load();
+
+ private:
+ AccessControl* m_rootAuthz;
+ };
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+ AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)
+ {
+ return new XMLAccessControl(e);
+ }
+
+ static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+ static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);
+ static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i);
+ static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t);
+ static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e);
+ static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T);
+ static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);
+ static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);
+ static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e);
+ static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);
+}
+
+Rule::Rule(const DOMElement* e)
+{
+ auto_ptr_char req(e->getAttributeNS(NULL,require));
+ if (!req.get() || !*req.get())
+ throw ConfigurationException("Access control rule missing require attribute");
+ m_alias=req.get();
+
+ auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));
+ if (!vals.get())
+ return;
+
+ const XMLCh* flag = e->getAttributeNS(NULL,_list);
+ if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {
+ if (*vals.get())
+ m_vals.push_back(vals.get());
+ return;
+ }
+
+#ifdef HAVE_STRTOK_R
+ char* pos=NULL;
+ const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
+#else
+ const char* token=strtok(const_cast<char*>(vals.get())," ");
+#endif
+ while (token) {
+ m_vals.push_back(token);
+#ifdef HAVE_STRTOK_R
+ token=strtok_r(NULL," ",&pos);
+#else
+ token=strtok(NULL," ");
+#endif
+ }
+}
+
+AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
+{
+ // We can make this more complex later using pluggable comparison functions,
+ // but for now, just a straight port to the new Attribute API.
+
+ // Map alias in rule to the attribute.
+ if (!session) {
+ request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+ return shib_acl_false;
+ }
+
+ if (m_alias == "valid-user") {
+ if (session) {
+ request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ if (m_alias == "user") {
+ for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+ if (*i == request.getRemoteUser()) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");
+ return shib_acl_true;
+ }
+ }
+ return shib_acl_false;
+ }
+ else if (m_alias == "authnContextClassRef") {
+ const char* ref = session->getAuthnContextClassRef();
+ for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+ if (!strcmp(i->c_str(),ref)) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");
+ return shib_acl_true;
+ }
+ }
+ return shib_acl_false;
+ }
+ else if (m_alias == "authnContextDeclRef") {
+ const char* ref = session->getAuthnContextDeclRef();
+ for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+ if (!strcmp(i->c_str(),ref)) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");
+ return shib_acl_true;
+ }
+ }
+ return shib_acl_false;
+ }
+
+ // Find the attribute(s) matching the require rule.
+ pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+ session->getIndexedAttributes().equal_range(m_alias);
+ if (attrs.first == attrs.second) {
+ request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+ return shib_acl_false;
+ }
+
+ for (; attrs.first != attrs.second; ++attrs.first) {
+ bool caseSensitive = attrs.first->second->isCaseSensitive();
+
+ // Now we have to intersect the attribute's values against the rule's list.
+ const vector<string>& vals = attrs.first->second->getSerializedValues();
+ for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+ for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+ if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");
+ return shib_acl_true;
+ }
+ }
+ }
+ }
+
+ return shib_acl_false;
+}
+
+RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))
+{
+ auto_ptr_char req(e->getAttributeNS(NULL,require));
+ if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())
+ throw ConfigurationException("Access control rule missing require attribute or element content.");
+ m_alias=req.get();
+
+ const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);
+ bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+ try {
+ m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));
+ }
+}
+
+AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const
+{
+ // Map alias in rule to the attribute.
+ if (!session) {
+ request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+ return shib_acl_false;
+ }
+
+ if (m_alias == "valid-user") {
+ if (session) {
+ request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+
+ try {
+ if (m_alias == "user") {
+ if (m_re->matches(request.getRemoteUser().c_str())) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ else if (m_alias == "authnContextClassRef") {
+ if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ else if (m_alias == "authnContextDeclRef") {
+ if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+
+ // Find the attribute(s) matching the require rule.
+ pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+ session->getIndexedAttributes().equal_range(m_alias);
+ if (attrs.first == attrs.second) {
+ request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+ return shib_acl_false;
+ }
+
+ for (; attrs.first != attrs.second; ++attrs.first) {
+ // Now we have to intersect the attribute's values against the regular expression.
+ const vector<string>& vals = attrs.first->second->getSerializedValues();
+ for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+ if (m_re->matches(j->c_str())) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");
+ return shib_acl_true;
+ }
+ }
+ }
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());
+ }
+
+ return shib_acl_false;
+}
+
+Operator::Operator(const DOMElement* e)
+{
+ if (XMLString::equals(e->getLocalName(),NOT))
+ m_op=OP_NOT;
+ else if (XMLString::equals(e->getLocalName(),AND))
+ m_op=OP_AND;
+ else if (XMLString::equals(e->getLocalName(),OR))
+ m_op=OP_OR;
+ else
+ throw ConfigurationException("Unrecognized operator in access control rule");
+
+ try {
+ e=XMLHelper::getFirstChildElement(e);
+ if (XMLString::equals(e->getLocalName(),_Rule))
+ m_operands.push_back(new Rule(e));
+ else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+ m_operands.push_back(new RuleRegex(e));
+ else
+ m_operands.push_back(new Operator(e));
+
+ if (m_op==OP_NOT)
+ return;
+
+ e=XMLHelper::getNextSiblingElement(e);
+ while (e) {
+ if (XMLString::equals(e->getLocalName(),_Rule))
+ m_operands.push_back(new Rule(e));
+ else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+ m_operands.push_back(new RuleRegex(e));
+ else
+ m_operands.push_back(new Operator(e));
+ e=XMLHelper::getNextSiblingElement(e);
+ }
+ }
+ catch (exception&) {
+ for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+ throw;
+ }
+}
+
+Operator::~Operator()
+{
+ for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+}
+
+AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const
+{
+ switch (m_op) {
+ case OP_NOT:
+ switch (m_operands.front()->authorized(request,session)) {
+ case shib_acl_true:
+ return shib_acl_false;
+ case shib_acl_false:
+ return shib_acl_true;
+ default:
+ return shib_acl_indeterminate;
+ }
+
+ case OP_AND:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+ if ((*i)->authorized(request,session) != shib_acl_true)
+ return shib_acl_false;
+ }
+ return shib_acl_true;
+ }
+
+ case OP_OR:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+ if ((*i)->authorized(request,session) == shib_acl_true)
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ }
+ request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");
+ return shib_acl_false;
+}
+
+pair<bool,DOMElement*> XMLAccessControl::load()
+{
+ // Load from source using base class.
+ pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
+
+ // If we own it, wrap it.
+ XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
+
+ // Check for AccessControl wrapper and drop a level.
+ if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
+ raw.second = XMLHelper::getFirstChildElement(raw.second);
+
+ AccessControl* authz;
+ if (XMLString::equals(raw.second->getLocalName(),_Rule))
+ authz=new Rule(raw.second);
+ else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))
+ authz=new RuleRegex(raw.second);
+ else
+ authz=new Operator(raw.second);
+
+ delete m_rootAuthz;
+ m_rootAuthz = authz;
+ return make_pair(false,(DOMElement*)NULL);
+}
+
+AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+ return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;
+}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/** XMLRequestMapper.cpp
*
- * XML-based RequestMapper implementation
+ * XML-based RequestMapper implementation.
*/
#include "internal.h"
#include "util/DOMPropertySet.h"
#include "util/SPConstants.h"
+#include <algorithm>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReloadableXMLFile.h>
#include <xmltooling/util/XMLHelper.h>
conf.RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER, XMLRequestMapperFactory);
}
+RequestMapper::RequestMapper()
+{
+}
+
+RequestMapper::~RequestMapper()
+{
+}
+
void Override::loadACL(const DOMElement* e, Category& log)
{
try {
-/*
- * Copyright 2001-2009 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * XMLServiceProvider.cpp
- *
- * XML-based SP configuration and mgmt
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "version.h"
-#include "AccessControl.h"
-#include "Application.h"
-#include "RequestMapper.h"
-#include "ServiceProvider.h"
-#include "SessionCache.h"
-#include "SPConfig.h"
-#include "SPRequest.h"
-#include "handler/SessionInitiator.h"
-#include "remoting/ListenerService.h"
-#include "util/DOMPropertySet.h"
-#include "util/SPConstants.h"
-
-#if defined(XMLTOOLING_LOG4SHIB)
-# include <log4shib/PropertyConfigurator.hh>
-#elif defined(XMLTOOLING_LOG4CPP)
-# include <log4cpp/PropertyConfigurator.hh>
-#else
-# error "Supported logging library not available."
-#endif
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/version.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/ReloadableXMLFile.h>
-#include <xmltooling/util/TemplateEngine.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifndef SHIBSP_LITE
-# include "TransactionLog.h"
-# include "attribute/filtering/AttributeFilter.h"
-# include "attribute/resolver/AttributeExtractor.h"
-# include "attribute/resolver/AttributeResolver.h"
-# include "security/PKIXTrustEngine.h"
-# include <saml/SAMLConfig.h>
-# include <saml/version.h>
-# include <saml/binding/ArtifactMap.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/binding/SAML2ArtifactType0004.h>
-# include <xmltooling/util/ReplayCache.h>
-using namespace opensaml::saml2;
-using namespace opensaml::saml2p;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-#endif
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace std;
-
-#ifndef min
-# define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-namespace {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- static vector<const Handler*> g_noHandlers;
-
- // Application configuration wrapper
- class SHIBSP_DLLLOCAL XMLApplication : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter
- {
- public:
- XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL);
- ~XMLApplication() { cleanup(); }
-
- const char* getHash() const {return m_hash.c_str();}
-
-#ifndef SHIBSP_LITE
- SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {
- throw ConfigurationException("No support for SAML 1.x artifact generation.");
- }
- SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {
- pair<bool,int> index = make_pair(false,0);
- const PropertySet* props = getRelyingParty(relyingParty);
- index = props->getInt("artifactEndpointIndex");
- if (!index.first)
- index = getArtifactEndpointIndex();
- return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1(props->getString("entityID").second),index.first ? index.second : 1);
- }
-
- MetadataProvider* getMetadataProvider(bool required=true) const {
- if (required && !m_base && !m_metadata)
- throw ConfigurationException("No MetadataProvider available.");
- return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata;
- }
- TrustEngine* getTrustEngine(bool required=true) const {
- if (required && !m_base && !m_trust)
- throw ConfigurationException("No TrustEngine available.");
- return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust;
- }
- AttributeExtractor* getAttributeExtractor() const {
- return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;
- }
- AttributeFilter* getAttributeFilter() const {
- return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;
- }
- AttributeResolver* getAttributeResolver() const {
- return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;
- }
- CredentialResolver* getCredentialResolver() const {
- return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;
- }
- const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;
- const PropertySet* getRelyingParty(const XMLCh* entityID) const;
- const vector<const XMLCh*>* getAudiences() const {
- return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences;
- }
-#endif
- string getNotificationURL(const char* resource, bool front, unsigned int index) const;
-
- const vector<string>& getRemoteUserAttributeIds() const {
- return (m_remoteUsers.empty() && m_base) ? m_base->getRemoteUserAttributeIds() : m_remoteUsers;
- }
-
- void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;
- void setHeader(SPRequest& request, const char* name, const char* value) const;
- string getSecureHeader(const SPRequest& request, const char* name) const;
-
- const SessionInitiator* getDefaultSessionInitiator() const;
- const SessionInitiator* getSessionInitiatorById(const char* id) const;
- const Handler* getDefaultAssertionConsumerService() const;
- const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;
- const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;
- const Handler* getHandler(const char* path) const;
- void getHandlers(vector<const Handler*>& handlers) const;
-
- void receive(DDF& in, ostream& out) {
- // Only current function is to return the headers to clear.
- DDF header;
- DDF ret=DDF(NULL).list();
- DDFJanitor jret(ret);
- for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) {
- header = DDF(i->first.c_str()).string(i->second.c_str());
- ret.add(header);
- }
- out << ret;
- }
-
- // Provides filter to exclude special config elements.
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
- short
-#else
- FilterAction
-#endif
- acceptNode(const DOMNode* node) const;
-
- private:
- void cleanup();
- const XMLApplication* m_base;
- string m_hash;
- std::pair<std::string,std::string> m_attributePrefix;
-#ifndef SHIBSP_LITE
- MetadataProvider* m_metadata;
- TrustEngine* m_trust;
- AttributeExtractor* m_attrExtractor;
- AttributeFilter* m_attrFilter;
- AttributeResolver* m_attrResolver;
- CredentialResolver* m_credResolver;
- vector<const XMLCh*> m_audiences;
-
- // RelyingParty properties
- map<xstring,PropertySet*> m_partyMap;
-#endif
- vector<string> m_remoteUsers,m_frontLogout,m_backLogout;
-
- // manage handler objects
- vector<Handler*> m_handlers;
-
- // maps location (path info) to applicable handlers
- map<string,const Handler*> m_handlerMap;
-
- // maps unique indexes to consumer services
- map<unsigned int,const Handler*> m_acsIndexMap;
-
- // pointer to default consumer service
- const Handler* m_acsDefault;
-
- // maps binding strings to supporting consumer service(s)
- typedef map<xstring,vector<const Handler*> > ACSBindingMap;
- ACSBindingMap m_acsBindingMap;
-
- // pointer to default session initiator
- const SessionInitiator* m_sessionInitDefault;
-
- // maps unique ID strings to session initiators
- map<string,const SessionInitiator*> m_sessionInitMap;
-
- // pointer to default artifact resolution service
- const Handler* m_artifactResolutionDefault;
-
- pair<bool,int> getArtifactEndpointIndex() const {
- if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index");
- return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0);
- }
- };
-
- // Top-level configuration implementation
- class SHIBSP_DLLLOCAL XMLConfig;
- class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter
- {
- public:
- XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);
- ~XMLConfigImpl();
-
- RequestMapper* m_requestMapper;
- map<string,Application*> m_appmap;
-#ifndef SHIBSP_LITE
- map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
- vector< pair< string, pair<string,string> > > m_transportOptions;
-#endif
-
- // Provides filter to exclude special config elements.
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
- short
-#else
- FilterAction
-#endif
- acceptNode(const DOMNode* node) const;
-
- void setDocument(DOMDocument* doc) {
- m_document = doc;
- }
-
- private:
- void doExtensions(const DOMElement* e, const char* label, Category& log);
- void cleanup();
-
- const XMLConfig* m_outer;
- DOMDocument* m_document;
- };
-
- class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile
-#ifndef SHIBSP_LITE
- ,public Remoted
-#endif
- {
- public:
- XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),
- m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)
-#ifndef SHIBSP_LITE
- , m_tranLog(NULL)
-#endif
- {
- }
-
- void init() {
- load();
- }
-
- ~XMLConfig() {
- delete m_impl;
- delete m_sessionCache;
- delete m_listener;
-#ifndef SHIBSP_LITE
- delete m_tranLog;
- SAMLConfig::getConfig().setArtifactMap(NULL);
- XMLToolingConfig::getConfig().setReplayCache(NULL);
- for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());
-#endif
- }
-
- // PropertySet
- const PropertySet* getParent() const { return m_impl->getParent(); }
- void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}
- pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}
- pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}
- pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}
- pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}
- pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}
- void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}
- const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}
- const DOMElement* getElement() const {return m_impl->getElement();}
-
- // ServiceProvider
-#ifndef SHIBSP_LITE
- // Remoted
- void receive(DDF& in, ostream& out);
-
- TransactionLog* getTransactionLog() const {
- if (m_tranLog)
- return m_tranLog;
- throw ConfigurationException("No TransactionLog available.");
- }
-
- StorageService* getStorageService(const char* id) const {
- if (id) {
- map<string,StorageService*>::const_iterator i=m_storage.find(id);
- if (i!=m_storage.end())
- return i->second;
- }
- return NULL;
- }
-#endif
-
- ListenerService* getListenerService(bool required=true) const {
- if (required && !m_listener)
- throw ConfigurationException("No ListenerService available.");
- return m_listener;
- }
-
- SessionCache* getSessionCache(bool required=true) const {
- if (required && !m_sessionCache)
- throw ConfigurationException("No SessionCache available.");
- return m_sessionCache;
- }
-
- RequestMapper* getRequestMapper(bool required=true) const {
- if (required && !m_impl->m_requestMapper)
- throw ConfigurationException("No RequestMapper available.");
- return m_impl->m_requestMapper;
- }
-
- const Application* getApplication(const char* applicationId) const {
- map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);
- return (i!=m_impl->m_appmap.end()) ? i->second : NULL;
- }
-
-#ifndef SHIBSP_LITE
- const PropertySet* getPolicySettings(const char* id) const {
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
- if (i!=m_impl->m_policyMap.end())
- return i->second.first;
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
- }
-
- const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
- if (i!=m_impl->m_policyMap.end())
- return i->second.second;
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
- }
-
- bool setTransportOptions(SOAPTransport& transport) const {
- bool ret = true;
- vector< pair< string, pair<string,string> > >::const_iterator opt;
- for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {
- if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {
- m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());
- ret = false;
- }
- }
- return ret;
- }
-#endif
-
- protected:
- pair<bool,DOMElement*> load();
-
- private:
- friend class XMLConfigImpl;
- XMLConfigImpl* m_impl;
- mutable ListenerService* m_listener;
- mutable SessionCache* m_sessionCache;
-#ifndef SHIBSP_LITE
- mutable TransactionLog* m_tranLog;
- mutable map<string,StorageService*> m_storage;
-#endif
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- static const XMLCh ApplicationOverride[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e);
- static const XMLCh ApplicationDefaults[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,D,e,f,a,u,l,t,s);
- static const XMLCh _ArtifactMap[] = UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);
- static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
- static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
- static const XMLCh _AttributeResolver[] = UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);
- static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);
- static const XMLCh _ArtifactResolutionService[] =UNICODE_LITERAL_25(A,r,t,i,f,a,c,t,R,e,s,o,l,u,t,i,o,n,S,e,r,v,i,c,e);
- static const XMLCh _Audience[] = UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);
- static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);
- static const XMLCh Channel[]= UNICODE_LITERAL_7(C,h,a,n,n,e,l);
- static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
- static const XMLCh _Extensions[] = UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);
- static const XMLCh _fatal[] = UNICODE_LITERAL_5(f,a,t,a,l);
- static const XMLCh _Handler[] = UNICODE_LITERAL_7(H,a,n,d,l,e,r);
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
- static const XMLCh InProcess[] = UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);
- static const XMLCh Library[] = UNICODE_LITERAL_7(L,i,b,r,a,r,y);
- static const XMLCh Listener[] = UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);
- static const XMLCh Location[] = UNICODE_LITERAL_8(L,o,c,a,t,i,o,n);
- static const XMLCh logger[] = UNICODE_LITERAL_6(l,o,g,g,e,r);
- static const XMLCh _LogoutInitiator[] = UNICODE_LITERAL_15(L,o,g,o,u,t,I,n,i,t,i,a,t,o,r);
- static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);
- static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
- static const XMLCh Notify[] = UNICODE_LITERAL_6(N,o,t,i,f,y);
- static const XMLCh _option[] = UNICODE_LITERAL_6(o,p,t,i,o,n);
- static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
- static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);
- static const XMLCh Policy[] = UNICODE_LITERAL_6(P,o,l,i,c,y);
- static const XMLCh PolicyRule[] = UNICODE_LITERAL_10(P,o,l,i,c,y,R,u,l,e);
- static const XMLCh _provider[] = UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);
- static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
- static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
- static const XMLCh _RequestMapper[] = UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);
- static const XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e);
- static const XMLCh SecurityPolicies[] = UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);
- static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
- static const XMLCh _SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
- static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);
- static const XMLCh Site[] = UNICODE_LITERAL_4(S,i,t,e);
- static const XMLCh _StorageService[] = UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);
- static const XMLCh TCPListener[] = UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);
- static const XMLCh TransportOption[] = UNICODE_LITERAL_15(T,r,a,n,s,p,o,r,t,O,p,t,i,o,n);
- static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
- static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);
-
-#ifndef SHIBSP_LITE
- class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter
- {
- public:
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
- short
-#else
- FilterAction
-#endif
- acceptNode(const DOMNode* node) const {
- return FILTER_REJECT;
- }
- };
-#endif
-};
-
-namespace shibsp {
- ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)
- {
- return new XMLConfig(e);
- }
-};
-
-XMLApplication::XMLApplication(
- const ServiceProvider* sp,
- const DOMElement* e,
- const XMLApplication* base
- ) : Application(sp), m_base(base),
-#ifndef SHIBSP_LITE
- m_metadata(NULL), m_trust(NULL),
- m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL),
- m_credResolver(NULL),
-#endif
- m_acsDefault(NULL), m_sessionInitDefault(NULL), m_artifactResolutionDefault(NULL)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("XMLApplication");
-#endif
- Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");
-
- try {
- // First load any property sets.
- load(e,NULL,this);
- if (base)
- setParent(base);
-
- SPConfig& conf=SPConfig::getConfig();
-#ifndef SHIBSP_LITE
- SAMLConfig& samlConf=SAMLConfig::getConfig();
- XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
-#endif
-
- // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.
- static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- string tohash=getId();
- tohash+=getString("entityID").second;
- for (const char* ch = tohash.c_str(); *ch; ++ch) {
- m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);
- m_hash += (DIGITS[0x0F & *ch]);
- }
-
- // Populate prefix pair.
- m_attributePrefix.second = "HTTP_";
- pair<bool,const char*> prefix = getString("attributePrefix");
- if (prefix.first) {
- m_attributePrefix.first = prefix.second;
- const char* pch = prefix.second;
- while (*pch) {
- m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
- }
-
- // Load attribute ID lists for REMOTE_USER and header clearing.
- if (conf.isEnabled(SPConfig::InProcess)) {
- pair<bool,const char*> attributes = getString("REMOTE_USER");
- if (attributes.first) {
- char* dup = strdup(attributes.second);
- char* pos;
- char* start = dup;
- while (start && *start) {
- while (*start && isspace(*start))
- start++;
- if (!*start)
- break;
- pos = strchr(start,' ');
- if (pos)
- *pos=0;
- m_remoteUsers.push_back(start);
- start = pos ? pos+1 : NULL;
- }
- free(dup);
- }
-
- attributes = getString("unsetHeaders");
- if (attributes.first) {
- string transformedprefix(m_attributePrefix.second);
- const char* pch;
- prefix = getString("metadataAttributePrefix");
- if (prefix.first) {
- pch = prefix.second;
- while (*pch) {
- transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
- }
- char* dup = strdup(attributes.second);
- char* pos;
- char* start = dup;
- while (start && *start) {
- while (*start && isspace(*start))
- start++;
- if (!*start)
- break;
- pos = strchr(start,' ');
- if (pos)
- *pos=0;
-
- string transformed;
- pch = start;
- while (*pch) {
- transformed += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
-
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
- if (prefix.first)
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
- start = pos ? pos+1 : NULL;
- }
- free(dup);
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
- }
- }
-
- Handler* handler=NULL;
- const PropertySet* sessions = getPropertySet("Sessions");
-
- // Process assertion export handler.
- pair<bool,const char*> location = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,NULL);
- if (location.first) {
- try {
- DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler);
- exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second);
- pair<bool,const XMLCh*> exportACL = sessions->getXMLString("exportACL");
- if (exportACL.first) {
- static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);
- exportElement->setAttributeNS(NULL,_acl,exportACL.second);
- }
- handler = conf.HandlerManager.newPlugin(
- samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())
- );
- m_handlers.push_back(handler);
-
- // Insert into location map. If it contains the handlerURL, we skip past that part.
- const char* pch = strstr(location.second, sessions->getString("handlerURL").second);
- if (pch)
- location.second = pch + strlen(sessions->getString("handlerURL").second);
- if (*location.second == '/')
- m_handlerMap[location.second]=handler;
- else
- m_handlerMap[string("/") + location.second]=handler;
- }
- catch (exception& ex) {
- log.error("caught exception installing assertion lookup handler: %s", ex.what());
- }
- }
-
- // Process other handlers.
- bool hardACS=false, hardSessionInit=false, hardArt=false;
- const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;
- while (child) {
- try {
- // A handler is based on the Binding property in conjunction with the element name.
- // If it's an ACS or SI, also handle index/id mappings and defaulting.
- if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
- if (!bindprop.get() || !*(bindprop.get())) {
- log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
- // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)
- m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
- m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;
-
- if (!hardACS) {
- pair<bool,bool> defprop=handler->getBool("isDefault");
- if (defprop.first) {
- if (defprop.second) {
- hardACS=true;
- m_acsDefault=handler;
- }
- }
- else if (!m_acsDefault)
- m_acsDefault=handler;
- }
- }
- else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- if (!type.get() || !*(type.get())) {
- log.warn("SessionInitiator element has no type attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));
- handler=sihandler;
- pair<bool,const char*> si_id=handler->getString("id");
- if (si_id.first && si_id.second)
- m_sessionInitMap[si_id.second]=sihandler;
- if (!hardSessionInit) {
- pair<bool,bool> defprop=handler->getBool("isDefault");
- if (defprop.first) {
- if (defprop.second) {
- hardSessionInit=true;
- m_sessionInitDefault=sihandler;
- }
- }
- else if (!m_sessionInitDefault)
- m_sessionInitDefault=sihandler;
- }
- }
- else if (XMLString::equals(child->getLocalName(),_LogoutInitiator)) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- if (!type.get() || !*(type.get())) {
- log.warn("LogoutInitiator element has no type attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.LogoutInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));
- }
- else if (XMLString::equals(child->getLocalName(),_ArtifactResolutionService)) {
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
- if (!bindprop.get() || !*(bindprop.get())) {
- log.warn("md:ArtifactResolutionService element has no Binding attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-
- if (!hardArt) {
- pair<bool,bool> defprop=handler->getBool("isDefault");
- if (defprop.first) {
- if (defprop.second) {
- hardArt=true;
- m_artifactResolutionDefault=handler;
- }
- }
- else if (!m_artifactResolutionDefault)
- m_artifactResolutionDefault=handler;
- }
- }
- else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
- if (!bindprop.get() || !*(bindprop.get())) {
- log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
- }
- else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
- if (!bindprop.get() || !*(bindprop.get())) {
- log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
- }
- else {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- if (!type.get() || !*(type.get())) {
- log.warn("Handler element has no type attribute, skipping it...");
- child = XMLHelper::getNextSiblingElement(child);
- continue;
- }
- handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));
- }
-
- m_handlers.push_back(handler);
-
- // Insert into location map.
- location=handler->getString("Location");
- if (location.first && *location.second == '/')
- m_handlerMap[location.second]=handler;
- else if (location.first)
- m_handlerMap[string("/") + location.second]=handler;
-
- }
- catch (exception& ex) {
- log.error("caught exception processing handler element: %s", ex.what());
- }
-
- child = XMLHelper::getNextSiblingElement(child);
- }
-
- // Notification.
- DOMNodeList* nlist=e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS,Notify);
- for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++) {
- if (nlist->item(i)->getParentNode()->isSameNode(e)) {
- const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Channel);
- auto_ptr_char loc(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Location));
- if (loc.get() && *loc.get()) {
- if (channel && *channel == chLatin_f)
- m_frontLogout.push_back(loc.get());
- else
- m_backLogout.push_back(loc.get());
- }
- }
- }
-
-#ifndef SHIBSP_LITE
- nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);
- if (nlist && nlist->getLength()) {
- log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
- for (XMLSize_t i=0; i<nlist->getLength(); i++)
- if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
- m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
- }
-
- if (conf.isEnabled(SPConfig::Metadata)) {
- child = XMLHelper::getFirstChildElement(e,_MetadataProvider);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building MetadataProvider of type %s...",type.get());
- try {
- auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));
- mp->init();
- m_metadata = mp.release();
- }
- catch (exception& ex) {
- log.crit("error building/initializing MetadataProvider: %s", ex.what());
- }
- }
- }
-
- if (conf.isEnabled(SPConfig::Trust)) {
- child = XMLHelper::getFirstChildElement(e,_TrustEngine);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building TrustEngine of type %s...",type.get());
- try {
- m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("error building TrustEngine: %s", ex.what());
- }
- }
- }
-
- if (conf.isEnabled(SPConfig::AttributeResolution)) {
- child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building AttributeExtractor of type %s...",type.get());
- try {
- m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("error building AttributeExtractor: %s", ex.what());
- }
- }
-
- child = XMLHelper::getFirstChildElement(e,_AttributeFilter);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building AttributeFilter of type %s...",type.get());
- try {
- m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("error building AttributeFilter: %s", ex.what());
- }
- }
-
- child = XMLHelper::getFirstChildElement(e,_AttributeResolver);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building AttributeResolver of type %s...",type.get());
- try {
- m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("error building AttributeResolver: %s", ex.what());
- }
- }
-
- if (m_unsetHeaders.empty()) {
- vector<string> unsetHeaders;
- if (m_attrExtractor) {
- Locker extlock(m_attrExtractor);
- m_attrExtractor->getAttributeIds(unsetHeaders);
- }
- else if (m_base && m_base->m_attrExtractor) {
- Locker extlock(m_base->m_attrExtractor);
- m_base->m_attrExtractor->getAttributeIds(unsetHeaders);
- }
- if (m_attrResolver) {
- Locker reslock(m_attrResolver);
- m_attrResolver->getAttributeIds(unsetHeaders);
- }
- else if (m_base && m_base->m_attrResolver) {
- Locker extlock(m_base->m_attrResolver);
- m_base->m_attrResolver->getAttributeIds(unsetHeaders);
- }
- if (!unsetHeaders.empty()) {
- string transformedprefix(m_attributePrefix.second);
- const char* pch;
- pair<bool,const char*> prefix = getString("metadataAttributePrefix");
- if (prefix.first) {
- pch = prefix.second;
- while (*pch) {
- transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
- }
- for (vector<string>::const_iterator hdr = unsetHeaders.begin(); hdr!=unsetHeaders.end(); ++hdr) {
- string transformed;
- pch = hdr->c_str();
- while (*pch) {
- transformed += (isalnum(*pch) ? toupper(*pch) : '_');
- pch++;
- }
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
- if (prefix.first)
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
- }
- }
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
- }
- }
-
- if (conf.isEnabled(SPConfig::Credentials)) {
- child = XMLHelper::getFirstChildElement(e,_CredentialResolver);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building CredentialResolver of type %s...",type.get());
- try {
- m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("error building CredentialResolver: %s", ex.what());
- }
- }
- }
-
- // Finally, load relying parties.
- child = XMLHelper::getFirstChildElement(e,RelyingParty);
- while (child) {
- auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
- rp->load(child,NULL,this);
- rp->setParent(this);
- m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();
- child = XMLHelper::getNextSiblingElement(child,RelyingParty);
- }
-#endif
-
- // Out of process only, we register a listener endpoint.
- if (!conf.isEnabled(SPConfig::InProcess)) {
- ListenerService* listener = sp->getListenerService(false);
- if (listener) {
- string addr=string(getId()) + "::getHeaders::Application";
- listener->regListener(addr.c_str(),this);
- }
- else
- log.info("no ListenerService available, Application remoting disabled");
- }
- }
- catch (exception&) {
- cleanup();
- throw;
- }
-#ifndef _DEBUG
- catch (...) {
- cleanup();
- throw;
- }
-#endif
-}
-
-void XMLApplication::cleanup()
-{
- ListenerService* listener=getServiceProvider().getListenerService(false);
- if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
- string addr=string(getId()) + "::getHeaders::Application";
- listener->unregListener(addr.c_str(),this);
- }
- for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
- m_handlers.clear();
-#ifndef SHIBSP_LITE
- for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());
- m_partyMap.clear();
- delete m_credResolver;
- m_credResolver = NULL;
- delete m_attrResolver;
- m_attrResolver = NULL;
- delete m_attrFilter;
- m_attrFilter = NULL;
- delete m_attrExtractor;
- m_attrExtractor = NULL;
- delete m_trust;
- m_trust = NULL;
- delete m_metadata;
- m_metadata = NULL;
-#endif
-}
-
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-short
-#else
-DOMNodeFilter::FilterAction
-#endif
-XMLApplication::acceptNode(const DOMNode* node) const
-{
- const XMLCh* name=node->getLocalName();
- if (XMLString::equals(name,ApplicationOverride) ||
- XMLString::equals(name,_Audience) ||
- XMLString::equals(name,Notify) ||
- XMLString::equals(name,_Handler) ||
- XMLString::equals(name,_AssertionConsumerService) ||
- XMLString::equals(name,_ArtifactResolutionService) ||
- XMLString::equals(name,_LogoutInitiator) ||
- XMLString::equals(name,_ManageNameIDService) ||
- XMLString::equals(name,_SessionInitiator) ||
- XMLString::equals(name,_SingleLogoutService) ||
- XMLString::equals(name,RelyingParty) ||
- XMLString::equals(name,_MetadataProvider) ||
- XMLString::equals(name,_TrustEngine) ||
- XMLString::equals(name,_CredentialResolver) ||
- XMLString::equals(name,_AttributeFilter) ||
- XMLString::equals(name,_AttributeExtractor) ||
- XMLString::equals(name,_AttributeResolver))
- return FILTER_REJECT;
-
- return FILTER_ACCEPT;
-}
-
-#ifndef SHIBSP_LITE
-
-const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provider) const
-{
- if (!provider)
- return this;
-
- map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());
- if (i!=m_partyMap.end())
- return i->second;
- const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
- while (group) {
- if (group->getName()) {
- i=m_partyMap.find(group->getName());
- if (i!=m_partyMap.end())
- return i->second;
- }
- group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
- }
- return this;
-}
-
-const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const
-{
- if (!entityID)
- return this;
-
- map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);
- if (i!=m_partyMap.end())
- return i->second;
- return this;
-}
-
-#endif
-
-string XMLApplication::getNotificationURL(const char* resource, bool front, unsigned int index) const
-{
- const vector<string>& locs = front ? m_frontLogout : m_backLogout;
- if (locs.empty())
- return m_base ? m_base->getNotificationURL(resource, front, index) : string();
- else if (index >= locs.size())
- return string();
-
-#ifdef HAVE_STRCASECMP
- if (!resource || (strncasecmp(resource,"http://",7) && strncasecmp(resource,"https://",8)))
-#else
- if (!resource || (strnicmp(resource,"http://",7) && strnicmp(resource,"https://",8)))
-#endif
- throw ConfigurationException("Request URL was not absolute.");
-
- const char* handler=locs[index].c_str();
-
- // Should never happen...
- if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
- throw ConfigurationException(
- "Invalid Location property ($1) in Notify element for Application ($2)",
- params(2, handler ? handler : "null", getId())
- );
-
- // The "Location" property can be in one of three formats:
- //
- // 1) a full URI: http://host/foo/bar
- // 2) a hostless URI: http:///foo/bar
- // 3) a relative path: /foo/bar
- //
- // # Protocol Host Path
- // 1 handler handler handler
- // 2 handler resource handler
- // 3 resource resource handler
-
- const char* path = NULL;
-
- // Decide whether to use the handler or the resource for the "protocol"
- const char* prot;
- if (*handler != '/') {
- prot = handler;
- }
- else {
- prot = resource;
- path = handler;
- }
-
- // break apart the "protocol" string into protocol, host, and "the rest"
- const char* colon=strchr(prot,':');
- colon += 3;
- const char* slash=strchr(colon,'/');
- if (!path)
- path = slash;
-
- // Compute the actual protocol and store.
- string notifyURL(prot, colon-prot);
-
- // create the "host" from either the colon/slash or from the target string
- // If prot == handler then we're in either #1 or #2, else #3.
- // If slash == colon then we're in #2.
- if (prot != handler || slash == colon) {
- colon = strchr(resource, ':');
- colon += 3; // Get past the ://
- slash = strchr(colon, '/');
- }
- string host(colon, (slash ? slash-colon : strlen(colon)));
-
- // Build the URL
- notifyURL += host + path;
- return notifyURL;
-}
-
-void XMLApplication::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
-{
- if (!m_attributePrefix.first.empty()) {
- string temp = m_attributePrefix.first + rawname;
- string temp2 = m_attributePrefix.second + (cginame + 5);
- request.clearHeader(temp.c_str(), temp2.c_str());
- }
- else if (m_base) {
- m_base->clearHeader(request, rawname, cginame);
- }
- else {
- request.clearHeader(rawname, cginame);
- }
-}
-
-void XMLApplication::setHeader(SPRequest& request, const char* name, const char* value) const
-{
- if (!m_attributePrefix.first.empty()) {
- string temp = m_attributePrefix.first + name;
- request.setHeader(temp.c_str(), value);
- }
- else if (m_base) {
- m_base->setHeader(request, name, value);
- }
- else {
- request.setHeader(name, value);
- }
-}
-
-string XMLApplication::getSecureHeader(const SPRequest& request, const char* name) const
-{
- if (!m_attributePrefix.first.empty()) {
- string temp = m_attributePrefix.first + name;
- return request.getSecureHeader(temp.c_str());
- }
- else if (m_base) {
- return m_base->getSecureHeader(request,name);
- }
- else {
- return request.getSecureHeader(name);
- }
-}
-
-const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const
-{
- if (m_sessionInitDefault) return m_sessionInitDefault;
- return m_base ? m_base->getDefaultSessionInitiator() : NULL;
-}
-
-const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const
-{
- map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);
- if (i!=m_sessionInitMap.end()) return i->second;
- return m_base ? m_base->getSessionInitiatorById(id) : NULL;
-}
-
-const Handler* XMLApplication::getDefaultAssertionConsumerService() const
-{
- if (m_acsDefault) return m_acsDefault;
- return m_base ? m_base->getDefaultAssertionConsumerService() : NULL;
-}
-
-const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const
-{
- map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
- if (i!=m_acsIndexMap.end()) return i->second;
- return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;
-}
-
-const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
-{
- ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
- if (i!=m_acsBindingMap.end())
- return i->second;
- return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
-}
-
-const Handler* XMLApplication::getHandler(const char* path) const
-{
- string wrap(path);
- wrap = wrap.substr(0,wrap.find(';'));
- map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
- if (i!=m_handlerMap.end())
- return i->second;
- return m_base ? m_base->getHandler(path) : NULL;
-}
-
-void XMLApplication::getHandlers(vector<const Handler*>& handlers) const
-{
- handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());
- if (m_base) {
- for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {
- if (m_handlerMap.count(h->first) == 0)
- handlers.push_back(h->second);
- }
- }
-}
-
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-short
-#else
-DOMNodeFilter::FilterAction
-#endif
-XMLConfigImpl::acceptNode(const DOMNode* node) const
-{
- if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))
- return FILTER_ACCEPT;
- const XMLCh* name=node->getLocalName();
- if (XMLString::equals(name,ApplicationDefaults) ||
- XMLString::equals(name,_ArtifactMap) ||
- XMLString::equals(name,_Extensions) ||
- XMLString::equals(name,Listener) ||
- XMLString::equals(name,_RequestMapper) ||
- XMLString::equals(name,_ReplayCache) ||
- XMLString::equals(name,SecurityPolicies) ||
- XMLString::equals(name,_SessionCache) ||
- XMLString::equals(name,Site) ||
- XMLString::equals(name,_StorageService) ||
- XMLString::equals(name,TCPListener) ||
- XMLString::equals(name,TransportOption) ||
- XMLString::equals(name,UnixListener))
- return FILTER_REJECT;
-
- return FILTER_ACCEPT;
-}
-
-void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log)
-{
- const DOMElement* exts=XMLHelper::getFirstChildElement(e,_Extensions);
- if (exts) {
- exts=XMLHelper::getFirstChildElement(exts,Library);
- while (exts) {
- auto_ptr_char path(exts->getAttributeNS(NULL,_path));
- try {
- if (path.get()) {
- if (!XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts))
- throw ConfigurationException("XMLToolingConfig::load_library failed.");
- log.debug("loaded %s extension library (%s)", label, path.get());
- }
- }
- catch (exception& e) {
- const XMLCh* fatal=exts->getAttributeNS(NULL,_fatal);
- if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) {
- log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what());
- throw;
- }
- else {
- log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what());
- }
- }
- exts=XMLHelper::getNextSiblingElement(exts,Library);
- }
- }
-}
-
-XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)
- : m_requestMapper(NULL), m_outer(outer), m_document(NULL)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("XMLConfigImpl");
-#endif
-
- try {
- SPConfig& conf=SPConfig::getConfig();
-#ifndef SHIBSP_LITE
- SAMLConfig& samlConf=SAMLConfig::getConfig();
-#endif
- XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
- const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);
- const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess);
-
- // Initialize log4cpp manually in order to redirect log messages as soon as possible.
- if (conf.isEnabled(SPConfig::Logging)) {
- const XMLCh* logconf=NULL;
- if (conf.isEnabled(SPConfig::OutOfProcess))
- logconf=SHAR->getAttributeNS(NULL,logger);
- else if (conf.isEnabled(SPConfig::InProcess))
- logconf=SHIRE->getAttributeNS(NULL,logger);
- if (!logconf || !*logconf)
- logconf=e->getAttributeNS(NULL,logger);
- if (logconf && *logconf) {
- auto_ptr_char logpath(logconf);
- log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());
- if (!XMLToolingConfig::getConfig().log_config(logpath.get()))
- log.crit("failed to load new logging configuration from (%s)", logpath.get());
- }
-
-#ifndef SHIBSP_LITE
- if (first)
- m_outer->m_tranLog = new TransactionLog();
-#endif
- }
-
- // Re-log library versions now that logging is set up.
-#ifndef SHIBSP_LITE
- log.info(
- "Library versions: Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
- XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, OPENSAML_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT
- );
-#else
- log.info(
- "Library versions: Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
- XERCES_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT
- );
-#endif
-
- // First load any property sets.
- load(e,NULL,this);
-
- const DOMElement* child;
- string plugtype;
-
- // Much of the processing can only occur on the first instantiation.
- if (first) {
- // Set clock skew.
- pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
- if (skew.first)
- xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
-
- pair<bool,const char*> unsafe = getString("unsafeChars");
- if (unsafe.first)
- TemplateEngine::unsafe_chars = unsafe.second;
-
- // Extensions
- doExtensions(e, "global", log);
- if (conf.isEnabled(SPConfig::OutOfProcess))
- doExtensions(SHAR, "out of process", log);
-
- if (conf.isEnabled(SPConfig::InProcess))
- doExtensions(SHIRE, "in process", log);
-
- // Instantiate the ListenerService and SessionCache objects.
- if (conf.isEnabled(SPConfig::Listener)) {
- child=XMLHelper::getFirstChildElement(e,UnixListener);
- if (child)
- plugtype=UNIX_LISTENER_SERVICE;
- else {
- child=XMLHelper::getFirstChildElement(e,TCPListener);
- if (child)
- plugtype=TCP_LISTENER_SERVICE;
- else {
- child=XMLHelper::getFirstChildElement(e,Listener);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- if (type.get())
- plugtype=type.get();
- }
- }
- }
- if (child) {
- log.info("building ListenerService of type %s...", plugtype.c_str());
- m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);
- }
- else {
- log.fatal("can't build ListenerService, missing conf:Listener element?");
- throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?");
- }
- }
-
-#ifndef SHIBSP_LITE
- if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
- m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));
- }
-#endif
-
- if (conf.isEnabled(SPConfig::Caching)) {
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
- // First build any StorageServices.
- child=XMLHelper::getFirstChildElement(e,_StorageService);
- while (child) {
- auto_ptr_char id(child->getAttributeNS(NULL,_id));
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- try {
- log.info("building StorageService (%s) of type %s...", id.get(), type.get());
- m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child);
- }
- catch (exception& ex) {
- log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what());
- }
- child=XMLHelper::getNextSiblingElement(child,_StorageService);
- }
-
- // Replay cache.
- StorageService* replaySS=NULL;
- child=XMLHelper::getFirstChildElement(e,_ReplayCache);
- if (child) {
- auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));
- if (ssid.get() && *ssid.get()) {
- if (m_outer->m_storage.count(ssid.get()))
- replaySS = m_outer->m_storage[ssid.get()];
- if (replaySS)
- log.info("building ReplayCache on top of StorageService (%s)...", ssid.get());
- else
- log.warn("unable to locate StorageService (%s) for ReplayCache, using dedicated in-memory instance", ssid.get());
- }
- xmlConf.setReplayCache(new ReplayCache(replaySS));
- }
- else {
- log.warn("no ReplayCache built, missing conf:ReplayCache element?");
- }
-
- // ArtifactMap
- child=XMLHelper::getFirstChildElement(e,_ArtifactMap);
- if (child) {
- auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));
- if (ssid.get() && *ssid.get() && m_outer->m_storage.count(ssid.get())) {
- log.info("building ArtifactMap on top of StorageService (%s)...", ssid.get());
- samlConf.setArtifactMap(new ArtifactMap(child, m_outer->m_storage[ssid.get()]));
- }
- }
- if (samlConf.getArtifactMap()==NULL) {
- log.info("building in-memory ArtifactMap...");
- samlConf.setArtifactMap(new ArtifactMap(child));
- }
-#endif
- }
- child=XMLHelper::getFirstChildElement(e,_SessionCache);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building SessionCache of type %s...",type.get());
- m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(), child);
- }
- else {
- log.fatal("can't build SessionCache, missing conf:SessionCache element?");
- throw ConfigurationException("Can't build SessionCache, missing conf:SessionCache element?");
- }
- }
- } // end of first-time-only stuff
-
- // Back to the fully dynamic stuff...next up is the RequestMapper.
- if (conf.isEnabled(SPConfig::RequestMapping)) {
- child=XMLHelper::getFirstChildElement(e,_RequestMapper);
- if (child) {
- auto_ptr_char type(child->getAttributeNS(NULL,_type));
- log.info("building RequestMapper of type %s...",type.get());
- m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);
- }
- else {
- log.fatal("can't build RequestMapper, missing conf:RequestMapper element?");
- throw ConfigurationException("Can't build RequestMapper, missing conf:RequestMapper element?");
- }
- }
-
-#ifndef SHIBSP_LITE
- // Load security policies.
- child = XMLHelper::getLastChildElement(e,SecurityPolicies);
- if (child) {
- PolicyNodeFilter filter;
- child = XMLHelper::getFirstChildElement(child,Policy);
- while (child) {
- auto_ptr_char id(child->getAttributeNS(NULL,_id));
- pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];
- rules.first = NULL;
- auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
- settings->load(child, NULL, &filter);
- rules.first = settings.release();
-
- // Process PolicyRule elements.
- const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);
- while (rule) {
- auto_ptr_char type(rule->getAttributeNS(NULL,_type));
- try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
- }
- catch (exception& ex) {
- log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
- }
- rule = XMLHelper::getNextSiblingElement(rule,PolicyRule);
- }
-
- if (rules.second.size() == 0) {
- // Process Rule elements.
- log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");
- rule = XMLHelper::getFirstChildElement(child,Rule);
- while (rule) {
- auto_ptr_char type(rule->getAttributeNS(NULL,_type));
- try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
- }
- catch (exception& ex) {
- log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
- }
- rule = XMLHelper::getNextSiblingElement(rule,Rule);
- }
-
- // Manually add a basic Conditions rule.
- log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL));
- }
-
- child = XMLHelper::getNextSiblingElement(child,Policy);
- }
- }
-
- // Process TransportOption elements.
- child = XMLHelper::getLastChildElement(e,TransportOption);
- while (child) {
- if (child->hasChildNodes()) {
- auto_ptr_char provider(child->getAttributeNS(NULL,_provider));
- auto_ptr_char option(child->getAttributeNS(NULL,_option));
- auto_ptr_char value(child->getFirstChild()->getNodeValue());
- if (provider.get() && *provider.get() && option.get() && *option.get() && value.get() && *value.get()) {
- m_transportOptions.push_back(make_pair(string(provider.get()), make_pair(string(option.get()), string(value.get()))));
- }
- }
- child = XMLHelper::getPreviousSiblingElement(child,TransportOption);
- }
-#endif
-
- // Load the default application. This actually has a fixed ID of "default". ;-)
- child=XMLHelper::getLastChildElement(e,ApplicationDefaults);
- if (!child) {
- log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
- throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
- }
- XMLApplication* defapp=new XMLApplication(m_outer,child);
- m_appmap[defapp->getId()]=defapp;
-
- // Load any overrides.
- child = XMLHelper::getFirstChildElement(child,ApplicationOverride);
- while (child) {
- auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer,child,defapp));
- if (m_appmap.count(iapp->getId()))
- log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
- else {
- const char* iappid=iapp->getId();
- m_appmap[iappid]=iapp.release();
- }
-
- child = XMLHelper::getNextSiblingElement(child,ApplicationOverride);
- }
- }
- catch (exception&) {
- cleanup();
- throw;
- }
-}
-
-XMLConfigImpl::~XMLConfigImpl()
-{
- cleanup();
-}
-
-void XMLConfigImpl::cleanup()
-{
- for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());
- m_appmap.clear();
-#ifndef SHIBSP_LITE
- for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i=m_policyMap.begin(); i!=m_policyMap.end(); ++i) {
- delete i->second.first;
- for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());
- }
- m_policyMap.clear();
-#endif
- delete m_requestMapper;
- m_requestMapper = NULL;
- if (m_document)
- m_document->release();
- m_document = NULL;
-}
-
-#ifndef SHIBSP_LITE
-void XMLConfig::receive(DDF& in, ostream& out)
-{
- if (!strcmp(in.name(), "get::RelayState")) {
- const char* id = in["id"].string();
- const char* key = in["key"].string();
- if (!id || !key)
- throw ListenerException("Required parameters missing for RelayState recovery.");
-
- string relayState;
- StorageService* storage = getStorageService(id);
- if (storage) {
- if (storage->readString("RelayState",key,&relayState)>0) {
- if (in["clear"].integer())
- storage->deleteString("RelayState",key);
- }
- }
- else {
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
- "Storage-backed RelayState with invalid StorageService ID (%s)", id
- );
- }
-
- // Repack for return to caller.
- DDF ret=DDF(NULL).unsafe_string(relayState.c_str());
- DDFJanitor jret(ret);
- out << ret;
- }
- else if (!strcmp(in.name(), "set::RelayState")) {
- const char* id = in["id"].string();
- const char* value = in["value"].string();
- if (!id || !value)
- throw ListenerException("Required parameters missing for RelayState creation.");
-
- string rsKey;
- StorageService* storage = getStorageService(id);
- if (storage) {
- SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
- rsKey = SAMLArtifact::toHex(rsKey);
- storage->createString("RelayState", rsKey.c_str(), value, time(NULL) + 600);
- }
- else {
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
- "Storage-backed RelayState with invalid StorageService ID (%s)", id
- );
- }
-
- // Repack for return to caller.
- DDF ret=DDF(NULL).string(rsKey.c_str());
- DDFJanitor jret(ret);
- out << ret;
- }
- else if (!strcmp(in.name(), "get::PostData")) {
- const char* id = in["id"].string();
- const char* key = in["key"].string();
- if (!id || !key)
- throw ListenerException("Required parameters missing for PostData recovery.");
-
- string postData;
- StorageService* storage = getStorageService(id);
- if (storage) {
- if (storage->readString("PostData",key,&postData) > 0) {
- storage->deleteString("PostData",key);
- }
- }
- else {
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
- "Storage-backed PostData with invalid StorageService ID (%s)", id
- );
- }
- // If the data's empty, we'll send nothing back.
- // If not, we don't need to round trip it, just send back the serialized DDF list.
- if (postData.empty()) {
- DDF ret(NULL);
- DDFJanitor jret(ret);
- out << ret;
- }
- else {
- out << postData;
- }
- }
- else if (!strcmp(in.name(), "set::PostData")) {
- const char* id = in["id"].string();
- if (!id || !in["parameters"].islist())
- throw ListenerException("Required parameters missing for PostData creation.");
-
- string rsKey;
- StorageService* storage = getStorageService(id);
- if (storage) {
- SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
- rsKey = SAMLArtifact::toHex(rsKey);
- ostringstream params;
- params << in["parameters"];
- storage->createString("PostData", rsKey.c_str(), params.str().c_str(), time(NULL) + 600);
- }
- else {
- Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
- "Storage-backed PostData with invalid StorageService ID (%s)", id
- );
- }
-
- // Repack for return to caller.
- DDF ret=DDF(NULL).string(rsKey.c_str());
- DDFJanitor jret(ret);
- out << ret;
- }
-}
-#endif
-
-pair<bool,DOMElement*> XMLConfig::load()
-{
- // Load from source using base class.
- pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-
- // If we own it, wrap it.
- XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
-
- XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this,m_log);
-
- // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
- impl->setDocument(docjanitor.release());
-
- delete m_impl;
- m_impl = impl;
-
- return make_pair(false,(DOMElement*)NULL);
-}
+/*\r
+ * Copyright 2001-2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * XMLServiceProvider.cpp\r
+ *\r
+ * XML-based SP configuration and mgmt.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "version.h"\r
+#include "AccessControl.h"\r
+#include "Application.h"\r
+#include "RequestMapper.h"\r
+#include "ServiceProvider.h"\r
+#include "SessionCache.h"\r
+#include "SPConfig.h"\r
+#include "SPRequest.h"\r
+#include "handler/SessionInitiator.h"\r
+#include "remoting/ListenerService.h"\r
+#include "util/DOMPropertySet.h"\r
+#include "util/SPConstants.h"\r
+\r
+#if defined(XMLTOOLING_LOG4SHIB)\r
+# include <log4shib/PropertyConfigurator.hh>\r
+#elif defined(XMLTOOLING_LOG4CPP)\r
+# include <log4cpp/PropertyConfigurator.hh>\r
+#else\r
+# error "Supported logging library not available."\r
+#endif\r
+#include <algorithm>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/version.h>\r
+#include <xmltooling/util/NDC.h>\r
+#include <xmltooling/util/ReloadableXMLFile.h>\r
+#include <xmltooling/util/TemplateEngine.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+#ifndef SHIBSP_LITE\r
+# include "TransactionLog.h"\r
+# include "attribute/filtering/AttributeFilter.h"\r
+# include "attribute/resolver/AttributeExtractor.h"\r
+# include "attribute/resolver/AttributeResolver.h"\r
+# include "security/PKIXTrustEngine.h"\r
+# include <saml/SAMLConfig.h>\r
+# include <saml/version.h>\r
+# include <saml/binding/ArtifactMap.h>\r
+# include <saml/binding/SAMLArtifact.h>\r
+# include <saml/binding/SecurityPolicyRule.h>\r
+# include <saml/saml1/core/Assertions.h>\r
+# include <saml/saml2/core/Assertions.h>\r
+# include <saml/saml2/binding/SAML2ArtifactType0004.h>\r
+# include <saml/saml2/metadata/Metadata.h>\r
+# include <saml/saml2/metadata/MetadataProvider.h>\r
+# include <saml/util/SAMLConstants.h>\r
+# include <xmltooling/security/CredentialResolver.h>\r
+# include <xmltooling/security/SecurityHelper.h>\r
+# include <xmltooling/security/TrustEngine.h>\r
+# include <xmltooling/util/ReplayCache.h>\r
+# include <xmltooling/util/StorageService.h>\r
+using namespace opensaml::saml2;\r
+using namespace opensaml::saml2p;\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+#else\r
+# include "lite/SAMLConstants.h"\r
+#endif\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+#ifndef min\r
+# define min(a,b) (((a) < (b)) ? (a) : (b))\r
+#endif\r
+\r
+namespace {\r
+\r
+#if defined (_MSC_VER)\r
+ #pragma warning( push )\r
+ #pragma warning( disable : 4250 )\r
+#endif\r
+\r
+ static vector<const Handler*> g_noHandlers;\r
+\r
+ // Application configuration wrapper\r
+ class SHIBSP_DLLLOCAL XMLApplication : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter\r
+ {\r
+ public:\r
+ XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL);\r
+ ~XMLApplication() { cleanup(); }\r
+\r
+ const char* getHash() const {return m_hash.c_str();}\r
+\r
+#ifndef SHIBSP_LITE\r
+ SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {\r
+ throw ConfigurationException("No support for SAML 1.x artifact generation.");\r
+ }\r
+ SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {\r
+ pair<bool,int> index = make_pair(false,0);\r
+ const PropertySet* props = getRelyingParty(relyingParty);\r
+ index = props->getInt("artifactEndpointIndex");\r
+ if (!index.first)\r
+ index = getArtifactEndpointIndex();\r
+ pair<bool,const char*> entityID = props->getString("entityID");\r
+ return new SAML2ArtifactType0004(\r
+ SecurityHelper::doHash("SHA1", entityID.second, strlen(entityID.second), false),\r
+ index.first ? index.second : 1\r
+ );\r
+ }\r
+\r
+ MetadataProvider* getMetadataProvider(bool required=true) const {\r
+ if (required && !m_base && !m_metadata)\r
+ throw ConfigurationException("No MetadataProvider available.");\r
+ return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata;\r
+ }\r
+ TrustEngine* getTrustEngine(bool required=true) const {\r
+ if (required && !m_base && !m_trust)\r
+ throw ConfigurationException("No TrustEngine available.");\r
+ return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust;\r
+ }\r
+ AttributeExtractor* getAttributeExtractor() const {\r
+ return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;\r
+ }\r
+ AttributeFilter* getAttributeFilter() const {\r
+ return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;\r
+ }\r
+ AttributeResolver* getAttributeResolver() const {\r
+ return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;\r
+ }\r
+ CredentialResolver* getCredentialResolver() const {\r
+ return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;\r
+ }\r
+ const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;\r
+ const PropertySet* getRelyingParty(const XMLCh* entityID) const;\r
+ const vector<const XMLCh*>* getAudiences() const {\r
+ return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences;\r
+ }\r
+#endif\r
+ string getNotificationURL(const char* resource, bool front, unsigned int index) const;\r
+\r
+ const vector<string>& getRemoteUserAttributeIds() const {\r
+ return (m_remoteUsers.empty() && m_base) ? m_base->getRemoteUserAttributeIds() : m_remoteUsers;\r
+ }\r
+\r
+ void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;\r
+ void setHeader(SPRequest& request, const char* name, const char* value) const;\r
+ string getSecureHeader(const SPRequest& request, const char* name) const;\r
+\r
+ const SessionInitiator* getDefaultSessionInitiator() const;\r
+ const SessionInitiator* getSessionInitiatorById(const char* id) const;\r
+ const Handler* getDefaultAssertionConsumerService() const;\r
+ const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;\r
+ const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;\r
+ const Handler* getHandler(const char* path) const;\r
+ void getHandlers(vector<const Handler*>& handlers) const;\r
+\r
+ void receive(DDF& in, ostream& out) {\r
+ // Only current function is to return the headers to clear.\r
+ DDF header;\r
+ DDF ret=DDF(NULL).list();\r
+ DDFJanitor jret(ret);\r
+ for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) {\r
+ header = DDF(i->first.c_str()).string(i->second.c_str());\r
+ ret.add(header);\r
+ }\r
+ out << ret;\r
+ }\r
+\r
+ // Provides filter to exclude special config elements.\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+ short\r
+#else\r
+ FilterAction\r
+#endif\r
+ acceptNode(const DOMNode* node) const;\r
+\r
+ private:\r
+ void cleanup();\r
+ const XMLApplication* m_base;\r
+ string m_hash;\r
+ std::pair<std::string,std::string> m_attributePrefix;\r
+#ifndef SHIBSP_LITE\r
+ MetadataProvider* m_metadata;\r
+ TrustEngine* m_trust;\r
+ AttributeExtractor* m_attrExtractor;\r
+ AttributeFilter* m_attrFilter;\r
+ AttributeResolver* m_attrResolver;\r
+ CredentialResolver* m_credResolver;\r
+ vector<const XMLCh*> m_audiences;\r
+\r
+ // RelyingParty properties\r
+ map<xstring,PropertySet*> m_partyMap;\r
+#endif\r
+ vector<string> m_remoteUsers,m_frontLogout,m_backLogout;\r
+\r
+ // manage handler objects\r
+ vector<Handler*> m_handlers;\r
+\r
+ // maps location (path info) to applicable handlers\r
+ map<string,const Handler*> m_handlerMap;\r
+\r
+ // maps unique indexes to consumer services\r
+ map<unsigned int,const Handler*> m_acsIndexMap;\r
+\r
+ // pointer to default consumer service\r
+ const Handler* m_acsDefault;\r
+\r
+ // maps binding strings to supporting consumer service(s)\r
+ typedef map<xstring,vector<const Handler*> > ACSBindingMap;\r
+ ACSBindingMap m_acsBindingMap;\r
+\r
+ // pointer to default session initiator\r
+ const SessionInitiator* m_sessionInitDefault;\r
+\r
+ // maps unique ID strings to session initiators\r
+ map<string,const SessionInitiator*> m_sessionInitMap;\r
+\r
+ // pointer to default artifact resolution service\r
+ const Handler* m_artifactResolutionDefault;\r
+\r
+ pair<bool,int> getArtifactEndpointIndex() const {\r
+ if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index");\r
+ return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0);\r
+ }\r
+ };\r
+\r
+ // Top-level configuration implementation\r
+ class SHIBSP_DLLLOCAL XMLConfig;\r
+ class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter\r
+ {\r
+ public:\r
+ XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);\r
+ ~XMLConfigImpl();\r
+\r
+ RequestMapper* m_requestMapper;\r
+ map<string,Application*> m_appmap;\r
+#ifndef SHIBSP_LITE\r
+ map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;\r
+ vector< pair< string, pair<string,string> > > m_transportOptions;\r
+#endif\r
+\r
+ // Provides filter to exclude special config elements.\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+ short\r
+#else\r
+ FilterAction\r
+#endif\r
+ acceptNode(const DOMNode* node) const;\r
+\r
+ void setDocument(DOMDocument* doc) {\r
+ m_document = doc;\r
+ }\r
+\r
+ private:\r
+ void doExtensions(const DOMElement* e, const char* label, Category& log);\r
+ void cleanup();\r
+\r
+ const XMLConfig* m_outer;\r
+ DOMDocument* m_document;\r
+ };\r
+\r
+ class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile\r
+#ifndef SHIBSP_LITE\r
+ ,public Remoted\r
+#endif\r
+ {\r
+ public:\r
+ XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),\r
+ m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)\r
+#ifndef SHIBSP_LITE\r
+ , m_tranLog(NULL)\r
+#endif\r
+ {\r
+ }\r
+\r
+ void init() {\r
+ load();\r
+ }\r
+\r
+ ~XMLConfig() {\r
+ delete m_impl;\r
+ delete m_sessionCache;\r
+ delete m_listener;\r
+#ifndef SHIBSP_LITE\r
+ delete m_tranLog;\r
+ SAMLConfig::getConfig().setArtifactMap(NULL);\r
+ XMLToolingConfig::getConfig().setReplayCache(NULL);\r
+ for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());\r
+#endif\r
+ }\r
+\r
+ // PropertySet\r
+ const PropertySet* getParent() const { return m_impl->getParent(); }\r
+ void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}\r
+ pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}\r
+ pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}\r
+ pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}\r
+ pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}\r
+ pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}\r
+ void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}\r
+ const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}\r
+ const DOMElement* getElement() const {return m_impl->getElement();}\r
+\r
+ // ServiceProvider\r
+#ifndef SHIBSP_LITE\r
+ // Remoted\r
+ void receive(DDF& in, ostream& out);\r
+\r
+ TransactionLog* getTransactionLog() const {\r
+ if (m_tranLog)\r
+ return m_tranLog;\r
+ throw ConfigurationException("No TransactionLog available.");\r
+ }\r
+\r
+ StorageService* getStorageService(const char* id) const {\r
+ if (id) {\r
+ map<string,StorageService*>::const_iterator i=m_storage.find(id);\r
+ if (i!=m_storage.end())\r
+ return i->second;\r
+ }\r
+ return NULL;\r
+ }\r
+#endif\r
+\r
+ ListenerService* getListenerService(bool required=true) const {\r
+ if (required && !m_listener)\r
+ throw ConfigurationException("No ListenerService available.");\r
+ return m_listener;\r
+ }\r
+\r
+ SessionCache* getSessionCache(bool required=true) const {\r
+ if (required && !m_sessionCache)\r
+ throw ConfigurationException("No SessionCache available.");\r
+ return m_sessionCache;\r
+ }\r
+\r
+ RequestMapper* getRequestMapper(bool required=true) const {\r
+ if (required && !m_impl->m_requestMapper)\r
+ throw ConfigurationException("No RequestMapper available.");\r
+ return m_impl->m_requestMapper;\r
+ }\r
+\r
+ const Application* getApplication(const char* applicationId) const {\r
+ map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);\r
+ return (i!=m_impl->m_appmap.end()) ? i->second : NULL;\r
+ }\r
+\r
+#ifndef SHIBSP_LITE\r
+ const PropertySet* getPolicySettings(const char* id) const {\r
+ map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
+ if (i!=m_impl->m_policyMap.end())\r
+ return i->second.first;\r
+ throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
+ }\r
+\r
+ const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {\r
+ map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
+ if (i!=m_impl->m_policyMap.end())\r
+ return i->second.second;\r
+ throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
+ }\r
+\r
+ bool setTransportOptions(SOAPTransport& transport) const {\r
+ bool ret = true;\r
+ vector< pair< string, pair<string,string> > >::const_iterator opt;\r
+ for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {\r
+ if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {\r
+ m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());\r
+ ret = false;\r
+ }\r
+ }\r
+ return ret;\r
+ }\r
+#endif\r
+\r
+ protected:\r
+ pair<bool,DOMElement*> load();\r
+\r
+ private:\r
+ friend class XMLConfigImpl;\r
+ XMLConfigImpl* m_impl;\r
+ mutable ListenerService* m_listener;\r
+ mutable SessionCache* m_sessionCache;\r
+#ifndef SHIBSP_LITE\r
+ mutable TransactionLog* m_tranLog;\r
+ mutable map<string,StorageService*> m_storage;\r
+#endif\r
+ };\r
+\r
+#if defined (_MSC_VER)\r
+ #pragma warning( pop )\r
+#endif\r
+\r
+ static const XMLCh ApplicationOverride[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e);\r
+ static const XMLCh ApplicationDefaults[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,D,e,f,a,u,l,t,s);\r
+ static const XMLCh _ArtifactMap[] = UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);\r
+ static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);\r
+ static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);\r
+ static const XMLCh _AttributeResolver[] = UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);\r
+ static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);\r
+ static const XMLCh _ArtifactResolutionService[] =UNICODE_LITERAL_25(A,r,t,i,f,a,c,t,R,e,s,o,l,u,t,i,o,n,S,e,r,v,i,c,e);\r
+ static const XMLCh _Audience[] = UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);\r
+ static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);\r
+ static const XMLCh Channel[]= UNICODE_LITERAL_7(C,h,a,n,n,e,l);\r
+ static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);\r
+ static const XMLCh _Extensions[] = UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);\r
+ static const XMLCh _fatal[] = UNICODE_LITERAL_5(f,a,t,a,l);\r
+ static const XMLCh _Handler[] = UNICODE_LITERAL_7(H,a,n,d,l,e,r);\r
+ static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);\r
+ static const XMLCh InProcess[] = UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);\r
+ static const XMLCh Library[] = UNICODE_LITERAL_7(L,i,b,r,a,r,y);\r
+ static const XMLCh Listener[] = UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);\r
+ static const XMLCh Location[] = UNICODE_LITERAL_8(L,o,c,a,t,i,o,n);\r
+ static const XMLCh logger[] = UNICODE_LITERAL_6(l,o,g,g,e,r);\r
+ static const XMLCh _LogoutInitiator[] = UNICODE_LITERAL_15(L,o,g,o,u,t,I,n,i,t,i,a,t,o,r);\r
+ static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);\r
+ static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);\r
+ static const XMLCh Notify[] = UNICODE_LITERAL_6(N,o,t,i,f,y);\r
+ static const XMLCh _option[] = UNICODE_LITERAL_6(o,p,t,i,o,n);\r
+ static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);\r
+ static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);\r
+ static const XMLCh Policy[] = UNICODE_LITERAL_6(P,o,l,i,c,y);\r
+ static const XMLCh PolicyRule[] = UNICODE_LITERAL_10(P,o,l,i,c,y,R,u,l,e);\r
+ static const XMLCh _provider[] = UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);\r
+ static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);\r
+ static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);\r
+ static const XMLCh _RequestMapper[] = UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);\r
+ static const XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e);\r
+ static const XMLCh SecurityPolicies[] = UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);\r
+ static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);\r
+ static const XMLCh _SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
+ static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);\r
+ static const XMLCh Site[] = UNICODE_LITERAL_4(S,i,t,e);\r
+ static const XMLCh _StorageService[] = UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);\r
+ static const XMLCh TCPListener[] = UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);\r
+ static const XMLCh TransportOption[] = UNICODE_LITERAL_15(T,r,a,n,s,p,o,r,t,O,p,t,i,o,n);\r
+ static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);\r
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);\r
+ static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);\r
+\r
+#ifndef SHIBSP_LITE\r
+ class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter\r
+ {\r
+ public:\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+ short\r
+#else\r
+ FilterAction\r
+#endif\r
+ acceptNode(const DOMNode* node) const {\r
+ return FILTER_REJECT;\r
+ }\r
+ };\r
+#endif\r
+};\r
+\r
+namespace shibsp {\r
+ ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)\r
+ {\r
+ return new XMLConfig(e);\r
+ }\r
+};\r
+\r
+XMLApplication::XMLApplication(\r
+ const ServiceProvider* sp,\r
+ const DOMElement* e,\r
+ const XMLApplication* base\r
+ ) : Application(sp), m_base(base),\r
+#ifndef SHIBSP_LITE\r
+ m_metadata(NULL), m_trust(NULL),\r
+ m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL),\r
+ m_credResolver(NULL),\r
+#endif\r
+ m_acsDefault(NULL), m_sessionInitDefault(NULL), m_artifactResolutionDefault(NULL)\r
+{\r
+#ifdef _DEBUG\r
+ xmltooling::NDC ndc("XMLApplication");\r
+#endif\r
+ Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");\r
+\r
+ try {\r
+ // First load any property sets.\r
+ load(e,NULL,this);\r
+ if (base)\r
+ setParent(base);\r
+\r
+ SPConfig& conf=SPConfig::getConfig();\r
+#ifndef SHIBSP_LITE\r
+ SAMLConfig& samlConf=SAMLConfig::getConfig();\r
+ XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();\r
+#endif\r
+\r
+ // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.\r
+ static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\r
+ string tohash=getId();\r
+ tohash+=getString("entityID").second;\r
+ for (const char* ch = tohash.c_str(); *ch; ++ch) {\r
+ m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);\r
+ m_hash += (DIGITS[0x0F & *ch]);\r
+ }\r
+\r
+ // Populate prefix pair.\r
+ m_attributePrefix.second = "HTTP_";\r
+ pair<bool,const char*> prefix = getString("attributePrefix");\r
+ if (prefix.first) {\r
+ m_attributePrefix.first = prefix.second;\r
+ const char* pch = prefix.second;\r
+ while (*pch) {\r
+ m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');\r
+ pch++;\r
+ }\r
+ }\r
+\r
+ // Load attribute ID lists for REMOTE_USER and header clearing.\r
+ if (conf.isEnabled(SPConfig::InProcess)) {\r
+ pair<bool,const char*> attributes = getString("REMOTE_USER");\r
+ if (attributes.first) {\r
+ char* dup = strdup(attributes.second);\r
+ char* pos;\r
+ char* start = dup;\r
+ while (start && *start) {\r
+ while (*start && isspace(*start))\r
+ start++;\r
+ if (!*start)\r
+ break;\r
+ pos = strchr(start,' ');\r
+ if (pos)\r
+ *pos=0;\r
+ m_remoteUsers.push_back(start);\r
+ start = pos ? pos+1 : NULL;\r
+ }\r
+ free(dup);\r
+ }\r
+\r
+ attributes = getString("unsetHeaders");\r
+ if (attributes.first) {\r
+ string transformedprefix(m_attributePrefix.second);\r
+ const char* pch;\r
+ prefix = getString("metadataAttributePrefix");\r
+ if (prefix.first) {\r
+ pch = prefix.second;\r
+ while (*pch) {\r
+ transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');\r
+ pch++;\r
+ }\r
+ }\r
+ char* dup = strdup(attributes.second);\r
+ char* pos;\r
+ char* start = dup;\r
+ while (start && *start) {\r
+ while (*start && isspace(*start))\r
+ start++;\r
+ if (!*start)\r
+ break;\r
+ pos = strchr(start,' ');\r
+ if (pos)\r
+ *pos=0;\r
+\r
+ string transformed;\r
+ pch = start;\r
+ while (*pch) {\r
+ transformed += (isalnum(*pch) ? toupper(*pch) : '_');\r
+ pch++;\r
+ }\r
+\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));\r
+ if (prefix.first)\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));\r
+ start = pos ? pos+1 : NULL;\r
+ }\r
+ free(dup);\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));\r
+ }\r
+ }\r
+\r
+ Handler* handler=NULL;\r
+ const PropertySet* sessions = getPropertySet("Sessions");\r
+\r
+ // Process assertion export handler.\r
+ pair<bool,const char*> location = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,NULL);\r
+ if (location.first) {\r
+ try {\r
+ DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler);\r
+ exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second);\r
+ pair<bool,const XMLCh*> exportACL = sessions->getXMLString("exportACL");\r
+ if (exportACL.first) {\r
+ static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);\r
+ exportElement->setAttributeNS(NULL,_acl,exportACL.second);\r
+ }\r
+ handler = conf.HandlerManager.newPlugin(\r
+ samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())\r
+ );\r
+ m_handlers.push_back(handler);\r
+\r
+ // Insert into location map. If it contains the handlerURL, we skip past that part.\r
+ const char* pch = strstr(location.second, sessions->getString("handlerURL").second);\r
+ if (pch)\r
+ location.second = pch + strlen(sessions->getString("handlerURL").second);\r
+ if (*location.second == '/')\r
+ m_handlerMap[location.second]=handler;\r
+ else\r
+ m_handlerMap[string("/") + location.second]=handler;\r
+ }\r
+ catch (exception& ex) {\r
+ log.error("caught exception installing assertion lookup handler: %s", ex.what());\r
+ }\r
+ }\r
+\r
+ // Process other handlers.\r
+ bool hardACS=false, hardSessionInit=false, hardArt=false;\r
+ const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;\r
+ while (child) {\r
+ try {\r
+ // A handler is based on the Binding property in conjunction with the element name.\r
+ // If it's an ACS or SI, also handle index/id mappings and defaulting.\r
+ if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {\r
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+ if (!bindprop.get() || !*(bindprop.get())) {\r
+ log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+ // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)\r
+ m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);\r
+ m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;\r
+\r
+ if (!hardACS) {\r
+ pair<bool,bool> defprop=handler->getBool("isDefault");\r
+ if (defprop.first) {\r
+ if (defprop.second) {\r
+ hardACS=true;\r
+ m_acsDefault=handler;\r
+ }\r
+ }\r
+ else if (!m_acsDefault)\r
+ m_acsDefault=handler;\r
+ }\r
+ }\r
+ else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ if (!type.get() || !*(type.get())) {\r
+ log.warn("SessionInitiator element has no type attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+ handler=sihandler;\r
+ pair<bool,const char*> si_id=handler->getString("id");\r
+ if (si_id.first && si_id.second)\r
+ m_sessionInitMap[si_id.second]=sihandler;\r
+ if (!hardSessionInit) {\r
+ pair<bool,bool> defprop=handler->getBool("isDefault");\r
+ if (defprop.first) {\r
+ if (defprop.second) {\r
+ hardSessionInit=true;\r
+ m_sessionInitDefault=sihandler;\r
+ }\r
+ }\r
+ else if (!m_sessionInitDefault)\r
+ m_sessionInitDefault=sihandler;\r
+ }\r
+ }\r
+ else if (XMLString::equals(child->getLocalName(),_LogoutInitiator)) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ if (!type.get() || !*(type.get())) {\r
+ log.warn("LogoutInitiator element has no type attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.LogoutInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+ }\r
+ else if (XMLString::equals(child->getLocalName(),_ArtifactResolutionService)) {\r
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+ if (!bindprop.get() || !*(bindprop.get())) {\r
+ log.warn("md:ArtifactResolutionService element has no Binding attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+\r
+ if (!hardArt) {\r
+ pair<bool,bool> defprop=handler->getBool("isDefault");\r
+ if (defprop.first) {\r
+ if (defprop.second) {\r
+ hardArt=true;\r
+ m_artifactResolutionDefault=handler;\r
+ }\r
+ }\r
+ else if (!m_artifactResolutionDefault)\r
+ m_artifactResolutionDefault=handler;\r
+ }\r
+ }\r
+ else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {\r
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+ if (!bindprop.get() || !*(bindprop.get())) {\r
+ log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+ }\r
+ else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {\r
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+ if (!bindprop.get() || !*(bindprop.get())) {\r
+ log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+ }\r
+ else {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ if (!type.get() || !*(type.get())) {\r
+ log.warn("Handler element has no type attribute, skipping it...");\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ continue;\r
+ }\r
+ handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));\r
+ }\r
+\r
+ m_handlers.push_back(handler);\r
+\r
+ // Insert into location map.\r
+ location=handler->getString("Location");\r
+ if (location.first && *location.second == '/')\r
+ m_handlerMap[location.second]=handler;\r
+ else if (location.first)\r
+ m_handlerMap[string("/") + location.second]=handler;\r
+\r
+ }\r
+ catch (exception& ex) {\r
+ log.error("caught exception processing handler element: %s", ex.what());\r
+ }\r
+\r
+ child = XMLHelper::getNextSiblingElement(child);\r
+ }\r
+\r
+ // Notification.\r
+ DOMNodeList* nlist=e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS,Notify);\r
+ for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++) {\r
+ if (nlist->item(i)->getParentNode()->isSameNode(e)) {\r
+ const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Channel);\r
+ auto_ptr_char loc(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Location));\r
+ if (loc.get() && *loc.get()) {\r
+ if (channel && *channel == chLatin_f)\r
+ m_frontLogout.push_back(loc.get());\r
+ else\r
+ m_backLogout.push_back(loc.get());\r
+ }\r
+ }\r
+ }\r
+\r
+#ifndef SHIBSP_LITE\r
+ nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);\r
+ if (nlist && nlist->getLength()) {\r
+ log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");\r
+ for (XMLSize_t i=0; i<nlist->getLength(); i++)\r
+ if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())\r
+ m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());\r
+ }\r
+\r
+ if (conf.isEnabled(SPConfig::Metadata)) {\r
+ child = XMLHelper::getFirstChildElement(e,_MetadataProvider);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building MetadataProvider of type %s...",type.get());\r
+ try {\r
+ auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));\r
+ mp->init();\r
+ m_metadata = mp.release();\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building/initializing MetadataProvider: %s", ex.what());\r
+ }\r
+ }\r
+ }\r
+\r
+ if (conf.isEnabled(SPConfig::Trust)) {\r
+ child = XMLHelper::getFirstChildElement(e,_TrustEngine);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building TrustEngine of type %s...",type.get());\r
+ try {\r
+ m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building TrustEngine: %s", ex.what());\r
+ }\r
+ }\r
+ }\r
+\r
+ if (conf.isEnabled(SPConfig::AttributeResolution)) {\r
+ child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building AttributeExtractor of type %s...",type.get());\r
+ try {\r
+ m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building AttributeExtractor: %s", ex.what());\r
+ }\r
+ }\r
+\r
+ child = XMLHelper::getFirstChildElement(e,_AttributeFilter);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building AttributeFilter of type %s...",type.get());\r
+ try {\r
+ m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building AttributeFilter: %s", ex.what());\r
+ }\r
+ }\r
+\r
+ child = XMLHelper::getFirstChildElement(e,_AttributeResolver);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building AttributeResolver of type %s...",type.get());\r
+ try {\r
+ m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building AttributeResolver: %s", ex.what());\r
+ }\r
+ }\r
+\r
+ if (m_unsetHeaders.empty()) {\r
+ vector<string> unsetHeaders;\r
+ if (m_attrExtractor) {\r
+ Locker extlock(m_attrExtractor);\r
+ m_attrExtractor->getAttributeIds(unsetHeaders);\r
+ }\r
+ else if (m_base && m_base->m_attrExtractor) {\r
+ Locker extlock(m_base->m_attrExtractor);\r
+ m_base->m_attrExtractor->getAttributeIds(unsetHeaders);\r
+ }\r
+ if (m_attrResolver) {\r
+ Locker reslock(m_attrResolver);\r
+ m_attrResolver->getAttributeIds(unsetHeaders);\r
+ }\r
+ else if (m_base && m_base->m_attrResolver) {\r
+ Locker extlock(m_base->m_attrResolver);\r
+ m_base->m_attrResolver->getAttributeIds(unsetHeaders);\r
+ }\r
+ if (!unsetHeaders.empty()) {\r
+ string transformedprefix(m_attributePrefix.second);\r
+ const char* pch;\r
+ pair<bool,const char*> prefix = getString("metadataAttributePrefix");\r
+ if (prefix.first) {\r
+ pch = prefix.second;\r
+ while (*pch) {\r
+ transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');\r
+ pch++;\r
+ }\r
+ }\r
+ for (vector<string>::const_iterator hdr = unsetHeaders.begin(); hdr!=unsetHeaders.end(); ++hdr) {\r
+ string transformed;\r
+ pch = hdr->c_str();\r
+ while (*pch) {\r
+ transformed += (isalnum(*pch) ? toupper(*pch) : '_');\r
+ pch++;\r
+ }\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));\r
+ if (prefix.first)\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));\r
+ }\r
+ }\r
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));\r
+ }\r
+ }\r
+\r
+ if (conf.isEnabled(SPConfig::Credentials)) {\r
+ child = XMLHelper::getFirstChildElement(e,_CredentialResolver);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building CredentialResolver of type %s...",type.get());\r
+ try {\r
+ m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error building CredentialResolver: %s", ex.what());\r
+ }\r
+ }\r
+ }\r
+\r
+ // Finally, load relying parties.\r
+ child = XMLHelper::getFirstChildElement(e,RelyingParty);\r
+ while (child) {\r
+ auto_ptr<DOMPropertySet> rp(new DOMPropertySet());\r
+ rp->load(child,NULL,this);\r
+ rp->setParent(this);\r
+ m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();\r
+ child = XMLHelper::getNextSiblingElement(child,RelyingParty);\r
+ }\r
+#endif\r
+\r
+ // Out of process only, we register a listener endpoint.\r
+ if (!conf.isEnabled(SPConfig::InProcess)) {\r
+ ListenerService* listener = sp->getListenerService(false);\r
+ if (listener) {\r
+ string addr=string(getId()) + "::getHeaders::Application";\r
+ listener->regListener(addr.c_str(),this);\r
+ }\r
+ else\r
+ log.info("no ListenerService available, Application remoting disabled");\r
+ }\r
+ }\r
+ catch (exception&) {\r
+ cleanup();\r
+ throw;\r
+ }\r
+#ifndef _DEBUG\r
+ catch (...) {\r
+ cleanup();\r
+ throw;\r
+ }\r
+#endif\r
+}\r
+\r
+void XMLApplication::cleanup()\r
+{\r
+ ListenerService* listener=getServiceProvider().getListenerService(false);\r
+ if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+ string addr=string(getId()) + "::getHeaders::Application";\r
+ listener->unregListener(addr.c_str(),this);\r
+ }\r
+ for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());\r
+ m_handlers.clear();\r
+#ifndef SHIBSP_LITE\r
+ for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());\r
+ m_partyMap.clear();\r
+ delete m_credResolver;\r
+ m_credResolver = NULL;\r
+ delete m_attrResolver;\r
+ m_attrResolver = NULL;\r
+ delete m_attrFilter;\r
+ m_attrFilter = NULL;\r
+ delete m_attrExtractor;\r
+ m_attrExtractor = NULL;\r
+ delete m_trust;\r
+ m_trust = NULL;\r
+ delete m_metadata;\r
+ m_metadata = NULL;\r
+#endif\r
+}\r
+\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+short\r
+#else\r
+DOMNodeFilter::FilterAction\r
+#endif\r
+XMLApplication::acceptNode(const DOMNode* node) const\r
+{\r
+ const XMLCh* name=node->getLocalName();\r
+ if (XMLString::equals(name,ApplicationOverride) ||\r
+ XMLString::equals(name,_Audience) ||\r
+ XMLString::equals(name,Notify) ||\r
+ XMLString::equals(name,_Handler) ||\r
+ XMLString::equals(name,_AssertionConsumerService) ||\r
+ XMLString::equals(name,_ArtifactResolutionService) ||\r
+ XMLString::equals(name,_LogoutInitiator) ||\r
+ XMLString::equals(name,_ManageNameIDService) ||\r
+ XMLString::equals(name,_SessionInitiator) ||\r
+ XMLString::equals(name,_SingleLogoutService) ||\r
+ XMLString::equals(name,RelyingParty) ||\r
+ XMLString::equals(name,_MetadataProvider) ||\r
+ XMLString::equals(name,_TrustEngine) ||\r
+ XMLString::equals(name,_CredentialResolver) ||\r
+ XMLString::equals(name,_AttributeFilter) ||\r
+ XMLString::equals(name,_AttributeExtractor) ||\r
+ XMLString::equals(name,_AttributeResolver))\r
+ return FILTER_REJECT;\r
+\r
+ return FILTER_ACCEPT;\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+\r
+const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provider) const\r
+{\r
+ if (!provider)\r
+ return this;\r
+\r
+ map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());\r
+ if (i!=m_partyMap.end())\r
+ return i->second;\r
+ const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());\r
+ while (group) {\r
+ if (group->getName()) {\r
+ i=m_partyMap.find(group->getName());\r
+ if (i!=m_partyMap.end())\r
+ return i->second;\r
+ }\r
+ group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());\r
+ }\r
+ return this;\r
+}\r
+\r
+const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const\r
+{\r
+ if (!entityID)\r
+ return this;\r
+\r
+ map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);\r
+ if (i!=m_partyMap.end())\r
+ return i->second;\r
+ return this;\r
+}\r
+\r
+#endif\r
+\r
+string XMLApplication::getNotificationURL(const char* resource, bool front, unsigned int index) const\r
+{\r
+ const vector<string>& locs = front ? m_frontLogout : m_backLogout;\r
+ if (locs.empty())\r
+ return m_base ? m_base->getNotificationURL(resource, front, index) : string();\r
+ else if (index >= locs.size())\r
+ return string();\r
+\r
+#ifdef HAVE_STRCASECMP\r
+ if (!resource || (strncasecmp(resource,"http://",7) && strncasecmp(resource,"https://",8)))\r
+#else\r
+ if (!resource || (strnicmp(resource,"http://",7) && strnicmp(resource,"https://",8)))\r
+#endif\r
+ throw ConfigurationException("Request URL was not absolute.");\r
+\r
+ const char* handler=locs[index].c_str();\r
+\r
+ // Should never happen...\r
+ if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))\r
+ throw ConfigurationException(\r
+ "Invalid Location property ($1) in Notify element for Application ($2)",\r
+ params(2, handler ? handler : "null", getId())\r
+ );\r
+\r
+ // The "Location" property can be in one of three formats:\r
+ //\r
+ // 1) a full URI: http://host/foo/bar\r
+ // 2) a hostless URI: http:///foo/bar\r
+ // 3) a relative path: /foo/bar\r
+ //\r
+ // # Protocol Host Path\r
+ // 1 handler handler handler\r
+ // 2 handler resource handler\r
+ // 3 resource resource handler\r
+\r
+ const char* path = NULL;\r
+\r
+ // Decide whether to use the handler or the resource for the "protocol"\r
+ const char* prot;\r
+ if (*handler != '/') {\r
+ prot = handler;\r
+ }\r
+ else {\r
+ prot = resource;\r
+ path = handler;\r
+ }\r
+\r
+ // break apart the "protocol" string into protocol, host, and "the rest"\r
+ const char* colon=strchr(prot,':');\r
+ colon += 3;\r
+ const char* slash=strchr(colon,'/');\r
+ if (!path)\r
+ path = slash;\r
+\r
+ // Compute the actual protocol and store.\r
+ string notifyURL(prot, colon-prot);\r
+\r
+ // create the "host" from either the colon/slash or from the target string\r
+ // If prot == handler then we're in either #1 or #2, else #3.\r
+ // If slash == colon then we're in #2.\r
+ if (prot != handler || slash == colon) {\r
+ colon = strchr(resource, ':');\r
+ colon += 3; // Get past the ://\r
+ slash = strchr(colon, '/');\r
+ }\r
+ string host(colon, (slash ? slash-colon : strlen(colon)));\r
+\r
+ // Build the URL\r
+ notifyURL += host + path;\r
+ return notifyURL;\r
+}\r
+\r
+void XMLApplication::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const\r
+{\r
+ if (!m_attributePrefix.first.empty()) {\r
+ string temp = m_attributePrefix.first + rawname;\r
+ string temp2 = m_attributePrefix.second + (cginame + 5);\r
+ request.clearHeader(temp.c_str(), temp2.c_str());\r
+ }\r
+ else if (m_base) {\r
+ m_base->clearHeader(request, rawname, cginame);\r
+ }\r
+ else {\r
+ request.clearHeader(rawname, cginame);\r
+ }\r
+}\r
+\r
+void XMLApplication::setHeader(SPRequest& request, const char* name, const char* value) const\r
+{\r
+ if (!m_attributePrefix.first.empty()) {\r
+ string temp = m_attributePrefix.first + name;\r
+ request.setHeader(temp.c_str(), value);\r
+ }\r
+ else if (m_base) {\r
+ m_base->setHeader(request, name, value);\r
+ }\r
+ else {\r
+ request.setHeader(name, value);\r
+ }\r
+}\r
+\r
+string XMLApplication::getSecureHeader(const SPRequest& request, const char* name) const\r
+{\r
+ if (!m_attributePrefix.first.empty()) {\r
+ string temp = m_attributePrefix.first + name;\r
+ return request.getSecureHeader(temp.c_str());\r
+ }\r
+ else if (m_base) {\r
+ return m_base->getSecureHeader(request,name);\r
+ }\r
+ else {\r
+ return request.getSecureHeader(name);\r
+ }\r
+}\r
+\r
+const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const\r
+{\r
+ if (m_sessionInitDefault) return m_sessionInitDefault;\r
+ return m_base ? m_base->getDefaultSessionInitiator() : NULL;\r
+}\r
+\r
+const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const\r
+{\r
+ map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);\r
+ if (i!=m_sessionInitMap.end()) return i->second;\r
+ return m_base ? m_base->getSessionInitiatorById(id) : NULL;\r
+}\r
+\r
+const Handler* XMLApplication::getDefaultAssertionConsumerService() const\r
+{\r
+ if (m_acsDefault) return m_acsDefault;\r
+ return m_base ? m_base->getDefaultAssertionConsumerService() : NULL;\r
+}\r
+\r
+const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const\r
+{\r
+ map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);\r
+ if (i!=m_acsIndexMap.end()) return i->second;\r
+ return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;\r
+}\r
+\r
+const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const\r
+{\r
+ ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);\r
+ if (i!=m_acsBindingMap.end())\r
+ return i->second;\r
+ return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;\r
+}\r
+\r
+const Handler* XMLApplication::getHandler(const char* path) const\r
+{\r
+ string wrap(path);\r
+ wrap = wrap.substr(0,wrap.find(';'));\r
+ map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));\r
+ if (i!=m_handlerMap.end())\r
+ return i->second;\r
+ return m_base ? m_base->getHandler(path) : NULL;\r
+}\r
+\r
+void XMLApplication::getHandlers(vector<const Handler*>& handlers) const\r
+{\r
+ handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());\r
+ if (m_base) {\r
+ for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {\r
+ if (m_handlerMap.count(h->first) == 0)\r
+ handlers.push_back(h->second);\r
+ }\r
+ }\r
+}\r
+\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+short\r
+#else\r
+DOMNodeFilter::FilterAction\r
+#endif\r
+XMLConfigImpl::acceptNode(const DOMNode* node) const\r
+{\r
+ if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))\r
+ return FILTER_ACCEPT;\r
+ const XMLCh* name=node->getLocalName();\r
+ if (XMLString::equals(name,ApplicationDefaults) ||\r
+ XMLString::equals(name,_ArtifactMap) ||\r
+ XMLString::equals(name,_Extensions) ||\r
+ XMLString::equals(name,Listener) ||\r
+ XMLString::equals(name,_RequestMapper) ||\r
+ XMLString::equals(name,_ReplayCache) ||\r
+ XMLString::equals(name,SecurityPolicies) ||\r
+ XMLString::equals(name,_SessionCache) ||\r
+ XMLString::equals(name,Site) ||\r
+ XMLString::equals(name,_StorageService) ||\r
+ XMLString::equals(name,TCPListener) ||\r
+ XMLString::equals(name,TransportOption) ||\r
+ XMLString::equals(name,UnixListener))\r
+ return FILTER_REJECT;\r
+\r
+ return FILTER_ACCEPT;\r
+}\r
+\r
+void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log)\r
+{\r
+ const DOMElement* exts=XMLHelper::getFirstChildElement(e,_Extensions);\r
+ if (exts) {\r
+ exts=XMLHelper::getFirstChildElement(exts,Library);\r
+ while (exts) {\r
+ auto_ptr_char path(exts->getAttributeNS(NULL,_path));\r
+ try {\r
+ if (path.get()) {\r
+ if (!XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts))\r
+ throw ConfigurationException("XMLToolingConfig::load_library failed.");\r
+ log.debug("loaded %s extension library (%s)", label, path.get());\r
+ }\r
+ }\r
+ catch (exception& e) {\r
+ const XMLCh* fatal=exts->getAttributeNS(NULL,_fatal);\r
+ if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) {\r
+ log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what());\r
+ throw;\r
+ }\r
+ else {\r
+ log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what());\r
+ }\r
+ }\r
+ exts=XMLHelper::getNextSiblingElement(exts,Library);\r
+ }\r
+ }\r
+}\r
+\r
+XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)\r
+ : m_requestMapper(NULL), m_outer(outer), m_document(NULL)\r
+{\r
+#ifdef _DEBUG\r
+ xmltooling::NDC ndc("XMLConfigImpl");\r
+#endif\r
+\r
+ try {\r
+ SPConfig& conf=SPConfig::getConfig();\r
+#ifndef SHIBSP_LITE\r
+ SAMLConfig& samlConf=SAMLConfig::getConfig();\r
+#endif\r
+ XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();\r
+ const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);\r
+ const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess);\r
+\r
+ // Initialize log4cpp manually in order to redirect log messages as soon as possible.\r
+ if (conf.isEnabled(SPConfig::Logging)) {\r
+ const XMLCh* logconf=NULL;\r
+ if (conf.isEnabled(SPConfig::OutOfProcess))\r
+ logconf=SHAR->getAttributeNS(NULL,logger);\r
+ else if (conf.isEnabled(SPConfig::InProcess))\r
+ logconf=SHIRE->getAttributeNS(NULL,logger);\r
+ if (!logconf || !*logconf)\r
+ logconf=e->getAttributeNS(NULL,logger);\r
+ if (logconf && *logconf) {\r
+ auto_ptr_char logpath(logconf);\r
+ log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());\r
+ if (!XMLToolingConfig::getConfig().log_config(logpath.get()))\r
+ log.crit("failed to load new logging configuration from (%s)", logpath.get());\r
+ }\r
+\r
+#ifndef SHIBSP_LITE\r
+ if (first)\r
+ m_outer->m_tranLog = new TransactionLog();\r
+#endif\r
+ }\r
+\r
+ // Re-log library versions now that logging is set up.\r
+#ifndef SHIBSP_LITE\r
+ log.info(\r
+ "Library versions: Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",\r
+ XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, OPENSAML_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT\r
+ );\r
+#else\r
+ log.info(\r
+ "Library versions: Xerces-C %s, XMLTooling-C %s, Shibboleth %s",\r
+ XERCES_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT\r
+ );\r
+#endif\r
+\r
+ // First load any property sets.\r
+ load(e,NULL,this);\r
+\r
+ const DOMElement* child;\r
+ string plugtype;\r
+\r
+ // Much of the processing can only occur on the first instantiation.\r
+ if (first) {\r
+ // Set clock skew.\r
+ pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");\r
+ if (skew.first)\r
+ xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));\r
+\r
+ pair<bool,const char*> unsafe = getString("unsafeChars");\r
+ if (unsafe.first)\r
+ TemplateEngine::unsafe_chars = unsafe.second;\r
+\r
+ unsafe = getString("allowedSchemes");\r
+ if (unsafe.first) {\r
+ HTTPResponse::getAllowedSchemes().clear();\r
+ string schemes=unsafe.second;\r
+ unsigned int j_sch=0;\r
+ for (unsigned int i_sch=0; i_sch < schemes.length(); i_sch++) {\r
+ if (schemes.at(i_sch)==' ') {\r
+ HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, i_sch-j_sch));\r
+ j_sch = i_sch + 1;\r
+ }\r
+ }\r
+ HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, schemes.length()-j_sch));\r
+ }\r
+\r
+ // Extensions\r
+ doExtensions(e, "global", log);\r
+ if (conf.isEnabled(SPConfig::OutOfProcess))\r
+ doExtensions(SHAR, "out of process", log);\r
+\r
+ if (conf.isEnabled(SPConfig::InProcess))\r
+ doExtensions(SHIRE, "in process", log);\r
+\r
+ // Instantiate the ListenerService and SessionCache objects.\r
+ if (conf.isEnabled(SPConfig::Listener)) {\r
+ child=XMLHelper::getFirstChildElement(e,UnixListener);\r
+ if (child)\r
+ plugtype=UNIX_LISTENER_SERVICE;\r
+ else {\r
+ child=XMLHelper::getFirstChildElement(e,TCPListener);\r
+ if (child)\r
+ plugtype=TCP_LISTENER_SERVICE;\r
+ else {\r
+ child=XMLHelper::getFirstChildElement(e,Listener);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ if (type.get())\r
+ plugtype=type.get();\r
+ }\r
+ }\r
+ }\r
+ if (child) {\r
+ log.info("building ListenerService of type %s...", plugtype.c_str());\r
+ m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);\r
+ }\r
+ else {\r
+ log.fatal("can't build ListenerService, missing conf:Listener element?");\r
+ throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?");\r
+ }\r
+ }\r
+\r
+#ifndef SHIBSP_LITE\r
+ if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {\r
+ m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));\r
+ m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));\r
+ m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));\r
+ m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));\r
+ }\r
+#endif\r
+\r
+ if (conf.isEnabled(SPConfig::Caching)) {\r
+ if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+ // First build any StorageServices.\r
+ child=XMLHelper::getFirstChildElement(e,_StorageService);\r
+ while (child) {\r
+ auto_ptr_char id(child->getAttributeNS(NULL,_id));\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ try {\r
+ log.info("building StorageService (%s) of type %s...", id.get(), type.get());\r
+ m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child);\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what());\r
+ }\r
+ child=XMLHelper::getNextSiblingElement(child,_StorageService);\r
+ }\r
+\r
+ // Replay cache.\r
+ StorageService* replaySS=NULL;\r
+ child=XMLHelper::getFirstChildElement(e,_ReplayCache);\r
+ if (child) {\r
+ auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));\r
+ if (ssid.get() && *ssid.get()) {\r
+ if (m_outer->m_storage.count(ssid.get()))\r
+ replaySS = m_outer->m_storage[ssid.get()];\r
+ if (replaySS)\r
+ log.info("building ReplayCache on top of StorageService (%s)...", ssid.get());\r
+ else\r
+ log.warn("unable to locate StorageService (%s) for ReplayCache, using dedicated in-memory instance", ssid.get());\r
+ }\r
+ xmlConf.setReplayCache(new ReplayCache(replaySS));\r
+ }\r
+ else {\r
+ log.warn("no ReplayCache built, missing conf:ReplayCache element?");\r
+ }\r
+\r
+ // ArtifactMap\r
+ child=XMLHelper::getFirstChildElement(e,_ArtifactMap);\r
+ if (child) {\r
+ auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));\r
+ if (ssid.get() && *ssid.get() && m_outer->m_storage.count(ssid.get())) {\r
+ log.info("building ArtifactMap on top of StorageService (%s)...", ssid.get());\r
+ samlConf.setArtifactMap(new ArtifactMap(child, m_outer->m_storage[ssid.get()]));\r
+ }\r
+ }\r
+ if (samlConf.getArtifactMap()==NULL) {\r
+ log.info("building in-memory ArtifactMap...");\r
+ samlConf.setArtifactMap(new ArtifactMap(child));\r
+ }\r
+#endif\r
+ }\r
+ child=XMLHelper::getFirstChildElement(e,_SessionCache);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building SessionCache of type %s...",type.get());\r
+ m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(), child);\r
+ }\r
+ else {\r
+ log.fatal("can't build SessionCache, missing conf:SessionCache element?");\r
+ throw ConfigurationException("Can't build SessionCache, missing conf:SessionCache element?");\r
+ }\r
+ }\r
+ } // end of first-time-only stuff\r
+\r
+ // Back to the fully dynamic stuff...next up is the RequestMapper.\r
+ if (conf.isEnabled(SPConfig::RequestMapping)) {\r
+ child=XMLHelper::getFirstChildElement(e,_RequestMapper);\r
+ if (child) {\r
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+ log.info("building RequestMapper of type %s...",type.get());\r
+ m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);\r
+ }\r
+ else {\r
+ log.fatal("can't build RequestMapper, missing conf:RequestMapper element?");\r
+ throw ConfigurationException("Can't build RequestMapper, missing conf:RequestMapper element?");\r
+ }\r
+ }\r
+\r
+#ifndef SHIBSP_LITE\r
+ // Load security policies.\r
+ child = XMLHelper::getLastChildElement(e,SecurityPolicies);\r
+ if (child) {\r
+ PolicyNodeFilter filter;\r
+ child = XMLHelper::getFirstChildElement(child,Policy);\r
+ while (child) {\r
+ auto_ptr_char id(child->getAttributeNS(NULL,_id));\r
+ pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];\r
+ rules.first = NULL;\r
+ auto_ptr<DOMPropertySet> settings(new DOMPropertySet());\r
+ settings->load(child, NULL, &filter);\r
+ rules.first = settings.release();\r
+\r
+ // Process PolicyRule elements.\r
+ const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);\r
+ while (rule) {\r
+ auto_ptr_char type(rule->getAttributeNS(NULL,_type));\r
+ try {\r
+ rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+ }\r
+ rule = XMLHelper::getNextSiblingElement(rule,PolicyRule);\r
+ }\r
+\r
+ if (rules.second.size() == 0) {\r
+ // Process Rule elements.\r
+ log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");\r
+ rule = XMLHelper::getFirstChildElement(child,Rule);\r
+ while (rule) {\r
+ auto_ptr_char type(rule->getAttributeNS(NULL,_type));\r
+ try {\r
+ rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));\r
+ }\r
+ catch (exception& ex) {\r
+ log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+ }\r
+ rule = XMLHelper::getNextSiblingElement(rule,Rule);\r
+ }\r
+\r
+ // Manually add a basic Conditions rule.\r
+ log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());\r
+ rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL));\r
+ }\r
+\r
+ child = XMLHelper::getNextSiblingElement(child,Policy);\r
+ }\r
+ }\r
+\r
+ // Process TransportOption elements.\r
+ child = XMLHelper::getLastChildElement(e,TransportOption);\r
+ while (child) {\r
+ if (child->hasChildNodes()) {\r
+ auto_ptr_char provider(child->getAttributeNS(NULL,_provider));\r
+ auto_ptr_char option(child->getAttributeNS(NULL,_option));\r
+ auto_ptr_char value(child->getFirstChild()->getNodeValue());\r
+ if (provider.get() && *provider.get() && option.get() && *option.get() && value.get() && *value.get()) {\r
+ m_transportOptions.push_back(make_pair(string(provider.get()), make_pair(string(option.get()), string(value.get()))));\r
+ }\r
+ }\r
+ child = XMLHelper::getPreviousSiblingElement(child,TransportOption);\r
+ }\r
+#endif\r
+\r
+ // Load the default application. This actually has a fixed ID of "default". ;-)\r
+ child=XMLHelper::getLastChildElement(e,ApplicationDefaults);\r
+ if (!child) {\r
+ log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");\r
+ throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");\r
+ }\r
+ XMLApplication* defapp=new XMLApplication(m_outer,child);\r
+ m_appmap[defapp->getId()]=defapp;\r
+\r
+ // Load any overrides.\r
+ child = XMLHelper::getFirstChildElement(child,ApplicationOverride);\r
+ while (child) {\r
+ auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer,child,defapp));\r
+ if (m_appmap.count(iapp->getId()))\r
+ log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());\r
+ else {\r
+ const char* iappid=iapp->getId();\r
+ m_appmap[iappid]=iapp.release();\r
+ }\r
+\r
+ child = XMLHelper::getNextSiblingElement(child,ApplicationOverride);\r
+ }\r
+ }\r
+ catch (exception&) {\r
+ cleanup();\r
+ throw;\r
+ }\r
+}\r
+\r
+XMLConfigImpl::~XMLConfigImpl()\r
+{\r
+ cleanup();\r
+}\r
+\r
+void XMLConfigImpl::cleanup()\r
+{\r
+ for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());\r
+ m_appmap.clear();\r
+#ifndef SHIBSP_LITE\r
+ for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i=m_policyMap.begin(); i!=m_policyMap.end(); ++i) {\r
+ delete i->second.first;\r
+ for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());\r
+ }\r
+ m_policyMap.clear();\r
+#endif\r
+ delete m_requestMapper;\r
+ m_requestMapper = NULL;\r
+ if (m_document)\r
+ m_document->release();\r
+ m_document = NULL;\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+void XMLConfig::receive(DDF& in, ostream& out)\r
+{\r
+ if (!strcmp(in.name(), "get::RelayState")) {\r
+ const char* id = in["id"].string();\r
+ const char* key = in["key"].string();\r
+ if (!id || !key)\r
+ throw ListenerException("Required parameters missing for RelayState recovery.");\r
+\r
+ string relayState;\r
+ StorageService* storage = getStorageService(id);\r
+ if (storage) {\r
+ if (storage->readString("RelayState",key,&relayState)>0) {\r
+ if (in["clear"].integer())\r
+ storage->deleteString("RelayState",key);\r
+ }\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+ "Storage-backed RelayState with invalid StorageService ID (%s)", id\r
+ );\r
+ }\r
+\r
+ // Repack for return to caller.\r
+ DDF ret=DDF(NULL).unsafe_string(relayState.c_str());\r
+ DDFJanitor jret(ret);\r
+ out << ret;\r
+ }\r
+ else if (!strcmp(in.name(), "set::RelayState")) {\r
+ const char* id = in["id"].string();\r
+ const char* value = in["value"].string();\r
+ if (!id || !value)\r
+ throw ListenerException("Required parameters missing for RelayState creation.");\r
+\r
+ string rsKey;\r
+ StorageService* storage = getStorageService(id);\r
+ if (storage) {\r
+ SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+ rsKey = SAMLArtifact::toHex(rsKey);\r
+ storage->createString("RelayState", rsKey.c_str(), value, time(NULL) + 600);\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+ "Storage-backed RelayState with invalid StorageService ID (%s)", id\r
+ );\r
+ }\r
+\r
+ // Repack for return to caller.\r
+ DDF ret=DDF(NULL).string(rsKey.c_str());\r
+ DDFJanitor jret(ret);\r
+ out << ret;\r
+ }\r
+ else if (!strcmp(in.name(), "get::PostData")) {\r
+ const char* id = in["id"].string();\r
+ const char* key = in["key"].string();\r
+ if (!id || !key)\r
+ throw ListenerException("Required parameters missing for PostData recovery.");\r
+\r
+ string postData;\r
+ StorageService* storage = getStorageService(id);\r
+ if (storage) {\r
+ if (storage->readString("PostData",key,&postData) > 0) {\r
+ storage->deleteString("PostData",key);\r
+ }\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+ "Storage-backed PostData with invalid StorageService ID (%s)", id\r
+ );\r
+ }\r
+ // If the data's empty, we'll send nothing back.\r
+ // If not, we don't need to round trip it, just send back the serialized DDF list.\r
+ if (postData.empty()) {\r
+ DDF ret(NULL);\r
+ DDFJanitor jret(ret);\r
+ out << ret;\r
+ }\r
+ else {\r
+ out << postData;\r
+ }\r
+ }\r
+ else if (!strcmp(in.name(), "set::PostData")) {\r
+ const char* id = in["id"].string();\r
+ if (!id || !in["parameters"].islist())\r
+ throw ListenerException("Required parameters missing for PostData creation.");\r
+\r
+ string rsKey;\r
+ StorageService* storage = getStorageService(id);\r
+ if (storage) {\r
+ SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+ rsKey = SAMLArtifact::toHex(rsKey);\r
+ ostringstream params;\r
+ params << in["parameters"];\r
+ storage->createString("PostData", rsKey.c_str(), params.str().c_str(), time(NULL) + 600);\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+ "Storage-backed PostData with invalid StorageService ID (%s)", id\r
+ );\r
+ }\r
+\r
+ // Repack for return to caller.\r
+ DDF ret=DDF(NULL).string(rsKey.c_str());\r
+ DDFJanitor jret(ret);\r
+ out << ret;\r
+ }\r
+}\r
+#endif\r
+\r
+pair<bool,DOMElement*> XMLConfig::load()\r
+{\r
+ // Load from source using base class.\r
+ pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
+\r
+ // If we own it, wrap it.\r
+ XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
+\r
+ XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this,m_log);\r
+\r
+ // If we held the document, transfer it to the impl. If we didn't, it's a no-op.\r
+ impl->setDocument(docjanitor.release());\r
+\r
+ delete m_impl;\r
+ m_impl = impl;\r
+\r
+ return make_pair(false,(DOMElement*)NULL);\r
+}\r
}
}
+CommonDomainCookie::~CommonDomainCookie()
+{
+}
+
+const vector<string>& CommonDomainCookie::get() const
+{
+ return m_list;
+}
+
const char* CommonDomainCookie::set(const char* entityID)
{
// First scan the list for this IdP.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
CommonDomainCookie(const char* cookie);
- ~CommonDomainCookie() {}
+ ~CommonDomainCookie();
/**
* Returns list of IdPs stored in cookie.
*
* @return reference to vector of entityIDs
*/
- const std::vector<std::string>& get() const {
- return m_list;
- }
+ const std::vector<std::string>& get() const;
/**
* Adds/moves an IdP to the front of the list.
#ifndef __shibsp_xmlconstants_h__
#define __shibsp_xmlconstants_h__
-#include <xmltooling/util/XMLConstants.h>
+#include <shibsp/base.h>
+#include <xercesc/util/XercesDefs.hpp>
/**
* SAML related constants.
#include "internal.h"
#include "exceptions.h"
+#include "Application.h"
#include "ServiceProvider.h"
#include "metadata/MetadataProviderCriteria.h"
+#include <xercesc/framework/Wrapper4InputSource.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xsec/framework/XSECDefs.hpp>
#include <saml/version.h>
#include <saml/binding/SAMLArtifact.h>
#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/DynamicMetadataProvider.h>
-
#include <xmltooling/logging.h>
-#include <xmltooling/util/NDC.h>
+#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/security/Credential.h>
#include <xmltooling/security/CredentialCriteria.h>
#include <xmltooling/security/CredentialResolver.h>
#include <xmltooling/security/X509TrustEngine.h>
#include <xmltooling/soap/HTTPSOAPTransport.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/framework/Wrapper4InputSource.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling::logging;
name = temp.get();
}
else if (criteria.artifact) {
- throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");\r
+ throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");
}
// Establish networking properties based on calling application.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file shibsp/metadata/MetadataExt.h
*
- * XMLObjects representing Shibboleth metadata extensions
+ * XMLObjects representing Shibboleth metadata extensions.
*/
#ifndef __shibsp_metaext_h__
#define __shibsp_metaext_h__
#include <shibsp/util/SPConstants.h>
-#include <xmltooling/XMLObjectBuilder.h>
-#include <xmltooling/signature/KeyInfo.h>
-#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <xmltooling/AttributeExtensibleXMLObject.h>
+#include <xmltooling/ConcreteXMLObjectBuilder.h>
+#include <xmltooling/util/XMLObjectChildrenList.h>
#define DECL_SHIBOBJECTBUILDER(cname) \
DECL_XMLOBJECTBUILDER(SHIBSP_API,cname,shibspconstants::SHIBMD_NS,shibspconstants::SHIBMD_PREFIX)
+namespace xmlsignature {
+ class XMLTOOL_API KeyInfo;
+};
+
namespace shibsp {
BEGIN_XMLOBJECT(SHIBSP_API,Scope,xmltooling::XMLObject,Scope element);
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <xmltooling/impl/AnyElement.h>
#include <xmltooling/io/AbstractXMLObjectMarshaller.h>
#include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
+#include <xmltooling/signature/KeyInfo.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
/*
-* Copyright 2001-2007 Internet2
+* Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* MetadataExtSchemaValidators.cpp
*
- * Schema-based validators for Shibboleth metadata extension classes
+ * Schema-based validators for Shibboleth metadata extension classes.
*/
#include "internal.h"
#include <saml/SAMLConfig.h>
#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/validation/Validator.h>
#include <xmltooling/validation/ValidatorSuite.h>
using namespace shibsp;
--- /dev/null
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * MetadataProviderCriteria.cpp
+ *
+ * Extended criteria for metadata lookup for Shibboleth-aware metadata providers.
+ */
+
+#include "internal.h"
+#include "metadata/MetadataProviderCriteria.h"
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using opensaml::SAMLArtifact;
+using namespace xmltooling;
+
+MetadataProviderCriteria::MetadataProviderCriteria(const Application& app) : application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+ const Application& app, const XMLCh* id, const xmltooling::QName* q, const XMLCh* prot, bool valid
+ ) : MetadataProvider::Criteria(id, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+ const Application& app, const char* id, const xmltooling::QName* q, const XMLCh* prot, bool valid
+ ) : MetadataProvider::Criteria(id, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+ const Application& app, const SAMLArtifact* a, const xmltooling::QName* q, const XMLCh* prot, bool valid
+ ) : MetadataProvider::Criteria(a, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::~MetadataProviderCriteria()
+{
+}
/*
- * Copyright 2001-2008 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_metaprovcrit_h__
#define __shibsp_metaprovcrit_h__
-#include <shibsp/Application.h>
+#include <shibsp/base.h>
+
#include <saml/saml2/metadata/MetadataProvider.h>
namespace shibsp {
+ class SHIBSP_API Application;
+
/**
* Extended criteria for metadata lookup for Shibboleth-aware metadata providers.
*/
*
* @param app application performing the lookup
*/
- MetadataProviderCriteria(const Application& app) : application(app) {
- }
+ MetadataProviderCriteria(const Application& app);
/**
* Constructor.
* @param prot protocol support constant, if any
* @param valid true iff stale metadata should be ignored
*/
- MetadataProviderCriteria(const Application& app, const XMLCh* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
- : opensaml::saml2md::MetadataProvider::Criteria(id, q, prot, valid), application(app) {
- }
+ MetadataProviderCriteria(
+ const Application& app, const XMLCh* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+ );
/**
* Constructor.
* @param prot protocol support constant, if any
* @param valid true iff stale metadata should be ignored
*/
- MetadataProviderCriteria(const Application& app, const char* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
- : opensaml::saml2md::MetadataProvider::Criteria(id, q, prot, valid), application(app) {
- }
+ MetadataProviderCriteria(
+ const Application& app, const char* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+ );
/**
* Constructor.
* @param prot protocol support constant, if any
* @param valid true iff stale metadata should be ignored
*/
- MetadataProviderCriteria(const Application& app, const opensaml::SAMLArtifact* a, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
- : opensaml::saml2md::MetadataProvider::Criteria(a, q, prot, valid), application(app) {
- }
+ MetadataProviderCriteria(
+ const Application& app, const opensaml::SAMLArtifact* a, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+ );
+
+ ~MetadataProviderCriteria();
- /** Controls whether stale metadata is ignored. */
+ /** The application performing the lookup. */
const Application& application;
};
};
-/*\r
- * Copyright 2001-2009 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * @file shibsp/paths.h\r
- * \r
- * Default configuration paths.\r
- */\r
-\r
-#ifndef __shibsp_paths_h__\r
-#define __shibsp_paths_h__\r
-\r
-/** Default schema catalogs. */\r
-#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/usr/share/xml/opensaml/saml20-catalog.xml:/usr/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"\r
-\r
-/** Default name of SP configuration file. */\r
-#define SHIBSP_CONFIG "shibboleth2.xml"\r
-\r
-/** Default name of SP console tool logging file. */\r
-#define SHIBSP_LOGGING "console.logger"\r
-\r
-/** Default prefix for installation (used to resolve relative paths). */\r
-#define SHIBSP_PREFIX "/opt/shibboleth-sp"\r
-\r
-/** Library directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LIBDIR "/opt/shibboleth-sp/lib"\r
-\r
-/** Log directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LOGDIR "/opt/shibboleth-sp/var/log"\r
-\r
-/** Configuration directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_CFGDIR "/opt/shibboleth-sp/etc"\r
-\r
-/** Runtime state directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_RUNDIR "/opt/shibboleth-sp/var/run"\r
-\r
-/** XML directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_XMLDIR "/opt/shibboleth-sp/share/xml"\r
-\r
-#endif /* __shibsp_paths_h__ */\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/paths.h
+ *
+ * Default configuration paths.
+ */
+
+#ifndef __shibsp_paths_h__
+#define __shibsp_paths_h__
+
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/opt/shibboleth-sp/share/xml/opensaml/saml20-catalog.xml:/opt/shibboleth-sp/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"
+
+/** Default name of SP configuration file. */
+#define SHIBSP_CONFIG "shibboleth2.xml"
+
+/** Default name of SP console tool logging file. */
+#define SHIBSP_LOGGING "console.logger"
+
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX "/opt/shibboleth-sp"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR "/opt/shibboleth-sp/lib"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR "/opt/shibboleth-sp/var/log"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR "/opt/shibboleth-sp/etc"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR "/opt/shibboleth-sp/var/run"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR "/opt/shibboleth-sp/share/xml"
+
+#endif /* __shibsp_paths_h__ */
-/*\r
- * Copyright 2001-2009 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * @file shibsp/paths.h\r
- * \r
- * Default configuration paths.\r
- */\r
-\r
-#ifndef __shibsp_paths_h__\r
-#define __shibsp_paths_h__\r
-\r
-/** Default schema catalogs. */\r
-#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"\r
-\r
-/** Default name of SP configuration file. */\r
-#define SHIBSP_CONFIG "shibboleth2.xml"\r
-\r
-/** Default name of SP console tool logging file. */\r
-#define SHIBSP_LOGGING "console.logger"\r
-\r
-/** Default prefix for installation (used to resolve relative paths). */\r
-#define SHIBSP_PREFIX "@-PREFIX-@"\r
-\r
-/** Library directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LIBDIR "@-LIBDIR-@"\r
-\r
-/** Log directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LOGDIR "@-LOGDIR-@"\r
-\r
-/** Configuration directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_CFGDIR "@-SYSCONFDIR-@"\r
-\r
-/** Runtime state directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_RUNDIR "@-RUNDIR-@"\r
-\r
-/** XML directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_XMLDIR "@-XMLDIR-@"\r
-\r
-#endif /* __shibsp_paths_h__ */\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/paths.h
+ *
+ * Default configuration paths.
+ */
+
+#ifndef __shibsp_paths_h__
+#define __shibsp_paths_h__
+
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"
+
+/** Default name of SP configuration file. */
+#define SHIBSP_CONFIG "shibboleth2.xml"
+
+/** Default name of SP console tool logging file. */
+#define SHIBSP_LOGGING "console.logger"
+
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX "@-PREFIX-@"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR "@-LIBDIR-@"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR "@-LOGDIR-@"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR "@-SYSCONFDIR-@"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR "@-RUNDIR-@"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR "@-XMLDIR-@"
+
+#endif /* __shibsp_paths_h__ */
{
MAKE_NONCOPYABLE(Remoted);
protected:
- Remoted() {}
+ Remoted();
public:
- virtual ~Remoted() {}
+ virtual ~Remoted();
/**
* Remoted classes implement this method to process incoming messages.
*/
class SHIBSP_API ListenerService : public virtual Remoted
{
+ protected:
+ ListenerService();
public:
- virtual ~ListenerService() {}
+ virtual ~ListenerService();
/**
* Send a remoted message and return the response.
* @param force true iff remnant network state should be forcibly cleared
* @return true iff the service initialization was successful
*/
- virtual bool init(bool force) {
- return true;
- }
+ virtual bool init(bool force);
/**
* OutOfProcess servers can implement server-side transport handling by
/**
* OutOfProcess servers can implement server-side termination/cleanup.
*/
- virtual void term() {
- }
+ virtual void term();
private:
std::map<std::string,Remoted*> m_listenerMap;
public:
/// @cond OFF
// constructors
- DDF() : m_handle(NULL) {}
+ DDF();
DDF(const char* n);
DDF(const char* n, const char* val, bool safe=true);
DDF(const char* n, long val);
// destructive node conversion methods
DDF& empty();
- DDF& string(const char* val) {
- return string(const_cast<char*>(val), true);
- }
- DDF& unsafe_string(const char* val) {
- return string(const_cast<char*>(val), true, false);
- }
DDF& string(char* val, bool copyit=true, bool safe=true);
+ DDF& string(const char* val);
+ DDF& unsafe_string(const char* val);
DDF& string(long val);
DDF& string(double val);
DDF& integer(long val);
// indexed operators
DDF operator[](unsigned long index) const;
- DDF operator[](const char* path) const { return getmember(path); }
+ DDF operator[](const char* path) const;
// named member access/creation
DDF addmember(const char* path);
#endif
}
+Remoted::Remoted()
+{
+}
+
+Remoted::~Remoted()
+{
+}
+
+ListenerService::ListenerService()
+{
+}
+
+ListenerService::~ListenerService()
+{
+}
+
Remoted* ListenerService::regListener(const char* address, Remoted* listener)
{
Remoted* ret=NULL;
dest->receive(in, out);
}
+
+bool ListenerService::init(bool force)
+{
+ return true;
+}
+
+void ListenerService::term()
+{
+}
// library implementation
+DDF::DDF() : m_handle(NULL)
+{
+}
+
DDF::DDF(const char* n)
{
m_handle=new(nothrow) ddf_body_t;
return *this;
}
+DDF& DDF::string(const char* val)
+{
+ return string(const_cast<char*>(val), true);
+}
+
+DDF& DDF::unsafe_string(const char* val)
+{
+ return string(const_cast<char*>(val), true, false);
+}
+
DDF& DDF::string(long val)
{
char buf[20];
return p;
}
+DDF DDF::operator[](const char* path) const
+{
+ return getmember(path);
+}
+
DDF DDF::operator[](unsigned long index) const
{
DDF d;
}
else {
char* val = toUTF8(child->getNodeValue(), true); // use malloc
- if (val)
- obj.string(val, false); // don't re-copy the string
+ obj.string(val, false); // don't re-copy the string
}
}
}
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by shibsp.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 101\r
-#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1000\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by shibsp.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
#include <xmltooling/security/AbstractPKIXTrustEngine.h>
#include <xmltooling/security/KeyInfoResolver.h>
#include <xmltooling/security/X509Credential.h>
+#include <xmltooling/util/Threads.h>
using namespace shibsp;
using namespace opensaml::saml2md;
}
}
+SecurityPolicy::~SecurityPolicy()
+{
+}
+
opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProviderCriteria() const
{
if (!m_metadataCriteria)
m_metadataCriteria->reset();
return *m_metadataCriteria;
}
+
+const Application& SecurityPolicy::getApplication() const
+{
+ return m_application;
+}
*/
SecurityPolicy(const Application& application, const xmltooling::QName* role=NULL, bool validate=true, const char* policyId=NULL);
- virtual ~SecurityPolicy() {}
+ virtual ~SecurityPolicy();
opensaml::saml2md::MetadataProvider::Criteria& getMetadataProviderCriteria() const;
*
* @return the associated Application
*/
- const Application& getApplication() const {
- return m_application;
- }
+ const Application& getApplication() const;
private:
const Application& m_application;
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
LinkIncremental="2"\r
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
LinkIncremental="2"\r
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
LinkIncremental="1"\r
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
SubSystem="2"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
LinkIncremental="1"\r
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\attribute\NameIDAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\attribute\ScopedAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\attribute\SimpleAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\attribute\XMLAttribute.cpp"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="handler"\r
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 1,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 1,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
FILEFLAGSMASK 0x3fL\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
#else\r
VALUE "FileDescription", "Shibboleth SP Library\0"\r
#endif\r
- VALUE "FileVersion", "1, 2, 1, 0\0"\r
+ VALUE "FileVersion", "1, 3, 0, 0\0"\r
#ifdef SHIBSP_LITE\r
#ifdef _DEBUG\r
- VALUE "InternalName", "shibsp-lite1_2D\0"\r
+ VALUE "InternalName", "shibsp-lite1_3D\0"\r
#else\r
- VALUE "InternalName", "shibsp-lite1_2\0"\r
+ VALUE "InternalName", "shibsp-lite1_3\0"\r
#endif\r
#else\r
#ifdef _DEBUG\r
- VALUE "InternalName", "shibsp1_2D\0"\r
+ VALUE "InternalName", "shibsp1_3D\0"\r
#else\r
- VALUE "InternalName", "shibsp1_2\0"\r
+ VALUE "InternalName", "shibsp1_3\0"\r
#endif\r
#endif\r
VALUE "LegalCopyright", "Copyright © 2009 Internet2\0"\r
VALUE "LegalTrademarks", "\0"\r
#ifdef SHIBSP_LITE\r
#ifdef _DEBUG\r
- VALUE "OriginalFilename", "shibsp-lite1_2D.dll\0"\r
+ VALUE "OriginalFilename", "shibsp-lite1_3D.dll\0"\r
#else\r
- VALUE "OriginalFilename", "shibsp-lite1_2.dll\0"\r
+ VALUE "OriginalFilename", "shibsp-lite1_3.dll\0"\r
#endif\r
#else\r
#ifdef _DEBUG\r
- VALUE "OriginalFilename", "shibsp1_2D.dll\0"\r
+ VALUE "OriginalFilename", "shibsp1_3D.dll\0"\r
#else\r
- VALUE "OriginalFilename", "shibsp1_2.dll\0"\r
+ VALUE "OriginalFilename", "shibsp1_3.dll\0"\r
#endif\r
#endif\r
VALUE "PrivateBuild", "\0"\r
- VALUE "ProductName", "Shibboleth 2.2.1\0"\r
- VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+ VALUE "ProductName", "Shibboleth 2.3\0"\r
+ VALUE "ProductVersion", "2, 3, 0, 0\0"\r
VALUE "SpecialBuild", "\0"\r
END\r
END\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
LinkIncremental="2"\r
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
LinkIncremental="2"\r
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
LinkIncremental="1"\r
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
SubSystem="2"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
- OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+ OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
LinkIncremental="1"\r
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
GenerateDebugInformation="true"\r
RelativePath=".\metadata\MetadataExtSchemaValidators.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\metadata\MetadataProviderCriteria.cpp"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="remoting"\r
>\r
</File>\r
<File\r
+ RelativePath=".\attribute\NameIDAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\attribute\NameIDAttributeDecoder.cpp"\r
>\r
</File>\r
>\r
</File>\r
<File\r
+ RelativePath=".\attribute\ScopedAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\attribute\ScopedAttributeDecoder.cpp"\r
>\r
</File>\r
<File\r
+ RelativePath=".\attribute\SimpleAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\attribute\StringAttributeDecoder.cpp"\r
>\r
</File>\r
<File\r
+ RelativePath=".\attribute\XMLAttribute.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\attribute\XMLAttributeDecoder.cpp"\r
>\r
</File>\r
>\r
</File>\r
<File\r
+ RelativePath=".\attribute\filtering\impl\BasicFilteringContext.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\attribute\filtering\impl\ChainingAttributeFilter.cpp"\r
>\r
</File>\r
#include "util/CGIParser.h"
#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/io/HTTPRequest.h>
#include <xmltooling/util/URLEncoder.h>
using namespace shibsp;
#define __shibsp_cgi_h__
#include <shibsp/base.h>
-#include <xmltooling/io/HTTPRequest.h>
+
+#include <map>
+#include <string>
+
+namespace xmltooling {
+ class XMLTOOL_API HTTPRequest;
+};
namespace shibsp {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
using namespace xercesc;
using namespace std;
+PropertySet::PropertySet()
+{
+}
+
+PropertySet::~PropertySet()
+{
+}
+
+DOMPropertySet::DOMPropertySet() : m_parent(NULL), m_root(NULL)
+{
+}
+
DOMPropertySet::~DOMPropertySet()
{
for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
}
+const PropertySet* DOMPropertySet::getParent() const
+{
+ return m_parent;
+}
+
+void DOMPropertySet::setParent(const PropertySet* parent)
+{
+ m_parent = parent;
+}
+
+const DOMElement* DOMPropertySet::getElement() const
+{
+ return m_root;
+}
+
void DOMPropertySet::load(
const DOMElement* e,
Category* log,
if (remapper) {
remap=remapper->find(realname);
if (remap!=remapper->end()) {
- log->warn("remapping property (%s) to (%s)",realname,remap->second.c_str());
+ log->warn("deprecation - remapping property (%s) to (%s)",realname,remap->second.c_str());
realname=remap->second.c_str();
}
}
if (remapper) {
remap=remapper->find(realname);
if (remap!=remapper->end()) {
- log->warn("remapping property set (%s) to (%s)",realname,remap->second.c_str());
+ log->warn("deprecation - remapping nested property set (%s) to (%s)",realname,remap->second.c_str());
realname=remap->second.c_str();
}
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define __shibsp_dompropset_h__
#include <shibsp/util/PropertySet.h>
+
#include <xmltooling/logging.h>
namespace shibsp {
class SHIBSP_API DOMPropertySet : public virtual PropertySet
{
public:
- DOMPropertySet() : m_parent(NULL), m_root(NULL) {}
+ DOMPropertySet();
virtual ~DOMPropertySet();
- const PropertySet* getParent() const {
- return m_parent;
- }
-
- void setParent(const PropertySet* parent) {
- m_parent = parent;
- }
-
+ const PropertySet* getParent() const;
+ void setParent(const PropertySet* parent);
std::pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
std::pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const;
std::pair<bool,int> getInt(const char* name, const char* ns=NULL) const;
void getAll(std::map<std::string,const char*>& properties) const;
const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
-
- const xercesc::DOMElement* getElement() const {
- return m_root;
- }
+ const xercesc::DOMElement* getElement() const;
/**
* Loads the property set from a DOM element.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define __shibsp_propset_h__
#include <shibsp/util/SPConstants.h>
+
#include <map>
+#include <string>
#include <xercesc/dom/DOM.hpp>
namespace shibsp {
{
MAKE_NONCOPYABLE(PropertySet);
protected:
- PropertySet() {}
+ PropertySet();
public:
- virtual ~PropertySet() {}
+ virtual ~PropertySet();
/**
* Returns parent of this PropertySet, if any.
-/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * SPConstants.cpp\r
- * \r
- * SP XML namespace constants \r
- */\r
-\r
-#include "internal.h"\r
-#include "util/SPConstants.h"\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibspconstants;\r
-\r
-const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,\r
- chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);\r
-\r
-const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,\r
- chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon,\r
- chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,\r
- chLatin_m, chLatin_a, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,\r
- chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
- chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
- chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_1, chPeriod, chDigit_0, chColon,\r
- chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,\r
- chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_u, chLatin_r, chLatin_i, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_1, chPeriod, chDigit_0, chColon,\r
- chLatin_n, chLatin_a, chLatin_m, chLatin_e,\r
- chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
- chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
- chDigit_1, chPeriod, chDigit_0, chColon,\r
- chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,\r
- chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,\r
- chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull\r
-};\r
-\r
-const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";\r
-\r
-const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";\r
-\r
-const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";\r
+/*
+ * Copyright 2001-2007 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SPConstants.cpp
+ *
+ * SP XML namespace constants
+ */
+
+#include "internal.h"
+#include "util/SPConstants.h"
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibspconstants;
+
+const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,
+ chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);
+
+const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,
+ chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon,
+ chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,
+ chLatin_m, chLatin_a, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,
+ chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+ chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+ chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_1, chPeriod, chDigit_0, chColon,
+ chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+ chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_u, chLatin_r, chLatin_i, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_1, chPeriod, chDigit_0, chColon,
+ chLatin_n, chLatin_a, chLatin_m, chLatin_e,
+ chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+ chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+ chDigit_1, chPeriod, chDigit_0, chColon,
+ chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,
+ chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,
+ chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull
+};
+
+const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";
+
+const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";
+
+const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define __shibsp_constants_h__
#include <shibsp/base.h>
-#ifndef SHIBSP_LITE
-# include <saml/util/SAMLConstants.h>
-#else
-# include <shibsp/lite/SAMLConstants.h>
-#endif
+#include <xercesc/util/XercesDefs.hpp>
/**
* Shibboleth SP XML constants.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
+#include "util/PropertySet.h"
#include "util/TemplateParameters.h"
#include <ctime>
using namespace xmltooling;
using namespace std;
+TemplateParameters::TemplateParameters(const exception* e, const PropertySet* props)
+ : m_exception(e), m_toolingException(dynamic_cast<const XMLToolingException*>(e))
+{
+ setPropertySet(props);
+}
+
+TemplateParameters::~TemplateParameters()
+{
+}
+
void TemplateParameters::setPropertySet(const PropertySet* props)
{
m_props = props;
#endif
}
+const XMLToolingException* TemplateParameters::getRichException() const
+{
+ return m_toolingException;
+}
+
const char* TemplateParameters::getParameter(const char* name) const
{
if (m_exception) {
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __shibsp_tempparams_h__
#define __shibsp_tempparams_h__
-#include <shibsp/util/PropertySet.h>
+#include <shibsp/base.h>
+
#include <xmltooling/util/TemplateEngine.h>
namespace shibsp {
+ class SHIBSP_API PropertySet;
+
/**
* Supplies xmltooling TemplateEngine with additional parameters from a PropertySet.
*/
* @param e an exception to supply additional parameters
* @param props a PropertySet to supply additional parameters
*/
- TemplateParameters(const std::exception* e=NULL, const PropertySet* props=NULL)
- : m_exception(e), m_toolingException(dynamic_cast<const xmltooling::XMLToolingException*>(e)) {
- setPropertySet(props);
- }
+ TemplateParameters(const std::exception* e=NULL, const PropertySet* props=NULL);
- virtual ~TemplateParameters() {}
+ virtual ~TemplateParameters();
/**
* Sets a PropertySet to supply additional parameters.
*
* @return an exception, or NULL
*/
- const xmltooling::XMLToolingException* getRichException() const {
- return m_toolingException;
- }
+ const xmltooling::XMLToolingException* getRichException() const;
const char* getParameter(const char* name) const;
*/
#define SHIBSP_VERSION_MAJOR 1
-#define SHIBSP_VERSION_MINOR 2
-#define SHIBSP_VERSION_REVISION 1
+#define SHIBSP_VERSION_MINOR 3
+#define SHIBSP_VERSION_REVISION 0
/** DO NOT MODIFY BELOW THIS LINE */
AMTAR = @AMTAR@
APR1_CONFIG = @APR1_CONFIG@
APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
APXS = @APXS@
APXS2 = @APXS2@
APXS22 = @APXS22@
-/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * mdquery.cpp\r
- * \r
- * SAML Metadata Query tool layered on SP configuration\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/Application.h>\r
-#include <shibsp/exceptions.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/metadata/MetadataProviderCriteria.h>\r
-#include <shibsp/util/SPConstants.h>\r
-#include <saml/saml2/metadata/Metadata.h>\r
-#include <xmltooling/logging.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml2md;\r
-using namespace opensaml;\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-void usage()\r
-{\r
- cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;\r
- cerr << " mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;\r
-}\r
-\r
-int main(int argc,char* argv[])\r
-{\r
- char* entityID = NULL;\r
- char* appID = "default";\r
- bool strict = true;\r
- char* prot = NULL;\r
- const XMLCh* protocol = NULL;\r
- char* rname = NULL;\r
- char* rns = NULL;\r
-\r
- for (int i=1; i<argc; i++) {\r
- if (!strcmp(argv[i],"-e") && i+1<argc)\r
- entityID=argv[++i];\r
- else if (!strcmp(argv[i],"-a") && i+1<argc)\r
- appID=argv[++i];\r
- else if (!strcmp(argv[i],"-p") && i+1<argc)\r
- prot=argv[++i];\r
- else if (!strcmp(argv[i],"-r") && i+1<argc)\r
- rname=argv[++i];\r
- else if (!strcmp(argv[i],"-ns") && i+1<argc)\r
- rns=argv[++i];\r
- else if (!strcmp(argv[i],"-saml10"))\r
- protocol=samlconstants::SAML10_PROTOCOL_ENUM;\r
- else if (!strcmp(argv[i],"-saml11"))\r
- protocol=samlconstants::SAML11_PROTOCOL_ENUM;\r
- else if (!strcmp(argv[i],"-saml2"))\r
- protocol=samlconstants::SAML20P_NS;\r
- else if (!strcmp(argv[i],"-idp"))\r
- rname="IDPSSODescriptor";\r
- else if (!strcmp(argv[i],"-aa"))\r
- rname="AttributeAuthorityDescriptor";\r
- else if (!strcmp(argv[i],"-pdp"))\r
- rname="PDPDescriptor";\r
- else if (!strcmp(argv[i],"-sp"))\r
- rname="SPSSODescriptor";\r
- else if (!strcmp(argv[i],"-nostrict"))\r
- strict = false;\r
- }\r
-\r
- if (!entityID) {\r
- usage();\r
- return -10;\r
- }\r
-\r
- if (rname) {\r
- if (!protocol) {\r
- if (prot)\r
- protocol = XMLString::transcode(prot);\r
- }\r
- if (!protocol) {\r
- usage();\r
- return -10;\r
- }\r
- }\r
-\r
- SPConfig& conf=SPConfig::getConfig();\r
- conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);\r
- if (!conf.init())\r
- return -1;\r
- if (!conf.instantiate()) {\r
- conf.term();\r
- return -2;\r
- }\r
-\r
- ServiceProvider* sp=conf.getServiceProvider();\r
- sp->lock();\r
-\r
- Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");\r
-\r
- const Application* app = sp->getApplication(appID);\r
- if (!app) {\r
- log.error("unknown application ID (%s)", appID);\r
- sp->unlock();\r
- conf.term();\r
- return -3;\r
- }\r
-\r
- app->getMetadataProvider()->lock();\r
- MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);\r
- if (rname) {\r
- const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;\r
- auto_ptr_XMLCh n(rname);\r
- QName q(ns, n.get());\r
- mc.role = &q;\r
- mc.protocol = protocol;\r
- const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;\r
- if (role)\r
- XMLHelper::serialize(role->marshall(), cout, true);\r
- else\r
- log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);\r
- }\r
- else {\r
- const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;\r
- if (entity)\r
- XMLHelper::serialize(entity->marshall(), cout, true);\r
- else\r
- log.error("no metadata found for (%s)", entityID);\r
- }\r
-\r
- app->getMetadataProvider()->unlock();\r
-\r
- sp->unlock();\r
- conf.term();\r
- return 0;\r
-}\r
+/*
+ * Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * mdquery.cpp
+ *
+ * SAML Metadata Query tool layered on SP configuration
+ */
+
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <shibsp/Application.h>
+#include <shibsp/exceptions.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/metadata/MetadataProviderCriteria.h>
+#include <shibsp/util/SPConstants.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <xmltooling/logging.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+using xercesc::XMLString;
+
+void usage()
+{
+ cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;
+ cerr << " mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;
+}
+
+int main(int argc,char* argv[])
+{
+ char* entityID = NULL;
+ char* appID = "default";
+ bool strict = true;
+ char* prot = NULL;
+ const XMLCh* protocol = NULL;
+ char* rname = NULL;
+ char* rns = NULL;
+
+ for (int i=1; i<argc; i++) {
+ if (!strcmp(argv[i],"-e") && i+1<argc)
+ entityID=argv[++i];
+ else if (!strcmp(argv[i],"-a") && i+1<argc)
+ appID=argv[++i];
+ else if (!strcmp(argv[i],"-p") && i+1<argc)
+ prot=argv[++i];
+ else if (!strcmp(argv[i],"-r") && i+1<argc)
+ rname=argv[++i];
+ else if (!strcmp(argv[i],"-ns") && i+1<argc)
+ rns=argv[++i];
+ else if (!strcmp(argv[i],"-saml10"))
+ protocol=samlconstants::SAML10_PROTOCOL_ENUM;
+ else if (!strcmp(argv[i],"-saml11"))
+ protocol=samlconstants::SAML11_PROTOCOL_ENUM;
+ else if (!strcmp(argv[i],"-saml2"))
+ protocol=samlconstants::SAML20P_NS;
+ else if (!strcmp(argv[i],"-idp"))
+ rname="IDPSSODescriptor";
+ else if (!strcmp(argv[i],"-aa"))
+ rname="AttributeAuthorityDescriptor";
+ else if (!strcmp(argv[i],"-pdp"))
+ rname="PDPDescriptor";
+ else if (!strcmp(argv[i],"-sp"))
+ rname="SPSSODescriptor";
+ else if (!strcmp(argv[i],"-nostrict"))
+ strict = false;
+ }
+
+ if (!entityID) {
+ usage();
+ return -10;
+ }
+
+ if (rname) {
+ if (!protocol) {
+ if (prot)
+ protocol = XMLString::transcode(prot);
+ }
+ if (!protocol) {
+ usage();
+ return -10;
+ }
+ }
+
+ SPConfig& conf=SPConfig::getConfig();
+ conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);
+ if (!conf.init())
+ return -1;
+ if (!conf.instantiate()) {
+ conf.term();
+ return -2;
+ }
+
+ ServiceProvider* sp=conf.getServiceProvider();
+ sp->lock();
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");
+
+ const Application* app = sp->getApplication(appID);
+ if (!app) {
+ log.error("unknown application ID (%s)", appID);
+ sp->unlock();
+ conf.term();
+ return -3;
+ }
+
+ app->getMetadataProvider()->lock();
+ MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);
+ if (rname) {
+ const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;
+ auto_ptr_XMLCh n(rname);
+ QName q(ns, n.get());
+ mc.role = &q;
+ mc.protocol = protocol;
+ const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;
+ if (role)
+ XMLHelper::serialize(role->marshall(), cout, true);
+ else
+ log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);
+ }
+ else {
+ const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;
+ if (entity)
+ XMLHelper::serialize(entity->marshall(), cout, true);
+ else
+ log.error("no metadata found for (%s)", entityID);
+ }
+
+ app->getMetadataProvider()->unlock();
+
+ sp->unlock();
+ conf.term();
+ return 0;
+}
#endif
#include <shibsp/Application.h>
-#include <shibsp/exceptions.h>
#include <shibsp/SPConfig.h>
#include <shibsp/ServiceProvider.h>
#include <shibsp/attribute/Attribute.h>
#include <shibsp/metadata/MetadataProviderCriteria.h>
#include <shibsp/util/SPConstants.h>
+#include <saml/exceptions.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/ParserPool.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
SPConfig::Trust |
SPConfig::AttributeResolution |
SPConfig::Credentials |
- SPConfig::OutOfProcess
+ SPConfig::OutOfProcess |
+ SPConfig::Caching
);
if (!conf.init())
return -1;