From 2b8daf0f4fd3e5035ab3babdc76fe676e8823f93 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 10 Nov 2009 14:59:40 -0800 Subject: [PATCH] Imported Upstream version 2.3+dfsg --- Makefile.in | 2 + Portfile | 2 +- adfs/Makefile.am | 50 +- adfs/Makefile.in | 2 + adfs/adfs.cpp | 70 +- adfs/adfs.rc | 10 +- adfs/resource.h | 30 +- apache/Makefile.in | 2 + apache/mod_apache.cpp | 3 + apache/mod_shib20.vcproj | 16 +- apache/mod_shib22.vcproj | 12 +- apache/mod_shib_13.rc | 10 +- apache/mod_shib_20.rc | 10 +- apache/mod_shib_22.rc | 10 +- config.guess | 614 ++-- config.h.in | 3 + config.sub | 185 +- config_win32.h | 6 +- configs/Makefile.am | 3 +- configs/Makefile.in | 3 + configs/accessError.html | 8 +- configs/apache.config.in | 21 +- configs/apache2.config.in | 21 +- configs/apache22.config.in | 21 +- configs/globalLogout.html | 19 +- configs/keygen.bat | 196 +- configs/keygen.sh | 5 +- configs/localLogout.html | 2 +- configs/metadataError.html | 2 +- configs/partialLogout.html | 22 + configs/sessionError.html | 6 +- configs/shibboleth2.xml | 34 +- configs/shibd-debian.in | 3 + configs/shibd-redhat.in | 15 +- configs/shibd-suse.in | 3 + configs/sslError.html | 9 +- configure | 293 +- configure.ac | 66 +- doc/CREDITS.txt | 0 doc/Makefile.in | 2 + doc/README.txt | 2 +- doc/RELEASE.txt | 4 +- fastcgi/Makefile.am | 60 +- fastcgi/Makefile.in | 2 + fastcgi/resource.h | 30 +- fastcgi/shibauthorizer.cpp | 854 ++--- fastcgi/shibauthorizer.rc | 10 +- fastcgi/shibresponder.cpp | 798 ++--- fastcgi/shibresponder.rc | 10 +- isapi_shib/isapi_shib.cpp | 45 +- isapi_shib/isapi_shib.cpp.mine | 993 ------ isapi_shib/isapi_shib.cpp.r3059 | 950 ------ isapi_shib/isapi_shib.cpp.r3097 | 1008 ------ isapi_shib/isapi_shib.rc | 10 +- ltmain.sh | 1402 +++++--- memcache-store/Makefile.am | 40 +- memcache-store/Makefile.in | 2 + memcache-store/memcache-store.cpp | 1578 ++++----- memcache-store/memcache-store.rc | 10 +- memcache-store/resource.h | 28 +- nsapi_shib/Makefile.in | 2 + nsapi_shib/nsapi_shib.cpp | 14 +- nsapi_shib/nsapi_shib.rc | 10 +- odbc-store/Makefile.in | 2 + odbc-store/odbc-store.cpp | 5 +- odbc-store/odbc-store.rc | 10 +- odbc-store/resource.h | 28 +- pkginfo | 2 +- postinstall | 1 + schemas/Makefile.am | 2 +- schemas/Makefile.in | 2 + schemas/shibboleth-2.0-afp.xsd | 26 +- schemas/shibboleth-2.0-attribute-map.xsd | 82 +- schemas/shibboleth-2.0-native-sp-config.xsd | 52 +- selinux/Makefile.am | 2 +- selinux/Makefile.in | 2 + shibboleth.spec | 68 +- shibboleth.spec.in | 66 +- shibd/Makefile.am | 2 +- shibd/Makefile.in | 2 + shibd/shibd.cpp | 806 ++--- shibd/shibd.rc | 10 +- shibd/shibd_win32.cpp | 1058 +++--- shibsp/AbstractSPRequest.cpp | 31 +- shibsp/AbstractSPRequest.h | 30 +- shibsp/AccessControl.h | 4 +- shibsp/Application.cpp | 13 +- shibsp/Application.h | 33 +- shibsp/Makefile.am | 10 +- shibsp/Makefile.in | 108 +- shibsp/RequestMapper.h | 11 +- shibsp/SPConfig.cpp | 68 +- shibsp/SPConfig.h | 34 +- shibsp/SPRequest.h | 15 +- shibsp/ServiceProvider.cpp | 41 +- shibsp/ServiceProvider.h | 21 +- shibsp/SessionCache.h | 37 +- shibsp/SessionCacheEx.h | 6 +- shibsp/TransactionLog.h | 25 +- shibsp/attribute/Attribute.cpp | 170 +- shibsp/attribute/Attribute.h | 67 +- shibsp/attribute/AttributeDecoder.h | 24 +- shibsp/attribute/DOMAttributeDecoder.cpp | 452 +-- shibsp/attribute/ExtensibleAttribute.cpp | 64 + shibsp/attribute/ExtensibleAttribute.h | 58 +- shibsp/attribute/KeyInfoAttributeDecoder.cpp | 326 +- shibsp/attribute/NameIDAttribute.cpp | 153 + shibsp/attribute/NameIDAttribute.h | 115 +- shibsp/attribute/NameIDAttributeDecoder.cpp | 468 +-- shibsp/attribute/ScopedAttribute.cpp | 113 + shibsp/attribute/ScopedAttribute.h | 77 +- shibsp/attribute/ScopedAttributeDecoder.cpp | 24 +- shibsp/attribute/SimpleAttribute.cpp | 69 + shibsp/attribute/SimpleAttribute.h | 32 +- shibsp/attribute/StringAttributeDecoder.cpp | 296 +- shibsp/attribute/XMLAttribute.cpp | 122 + shibsp/attribute/XMLAttribute.h | 53 +- shibsp/attribute/XMLAttributeDecoder.cpp | 276 +- shibsp/attribute/filtering/AttributeFilter.h | 12 +- shibsp/attribute/filtering/BasicFilteringContext.h | 46 +- shibsp/attribute/filtering/FilterPolicyContext.h | 15 +- shibsp/attribute/filtering/FilteringContext.h | 15 +- shibsp/attribute/filtering/MatchFunctor.h | 6 +- .../attribute/filtering/impl/AndMatchFunctor.cpp | 3 +- .../attribute/filtering/impl/AnyMatchFunctor.cpp | 3 +- .../attribute/filtering/impl/AttributeFilter.cpp | 10 +- .../impl/AttributeIssuerInEntityGroupFunctor.cpp | 5 +- .../filtering/impl/AttributeIssuerRegexFunctor.cpp | 3 +- .../impl/AttributeIssuerStringFunctor.cpp | 3 +- .../AttributeRequesterInEntityGroupFunctor.cpp | 9 +- .../impl/AttributeRequesterRegexFunctor.cpp | 3 +- .../impl/AttributeRequesterStringFunctor.cpp | 3 +- .../AttributeScopeMatchesShibMDScopeFunctor.cpp | 4 +- .../filtering/impl/AttributeScopeRegexFunctor.cpp | 3 +- .../filtering/impl/AttributeScopeStringFunctor.cpp | 3 +- .../filtering/impl/AttributeValueRegexFunctor.cpp | 3 +- .../filtering/impl/AttributeValueStringFunctor.cpp | 3 +- .../impl/AuthenticationMethodRegexFunctor.cpp | 3 +- .../impl/AuthenticationMethodStringFunctor.cpp | 3 +- .../filtering/impl/BasicFilteringContext.cpp | 98 + shibsp/attribute/filtering/impl/MatchFunctor.cpp | 24 +- .../attribute/filtering/impl/NotMatchFunctor.cpp | 3 +- .../impl/NumberOfAttributeValuesFunctor.cpp | 3 +- shibsp/attribute/filtering/impl/OrMatchFunctor.cpp | 3 +- .../filtering/impl/XMLAttributeFilter.cpp | 5 +- shibsp/attribute/resolver/AttributeExtractor.h | 18 +- shibsp/attribute/resolver/AttributeResolver.h | 18 +- shibsp/attribute/resolver/ResolutionContext.h | 12 +- .../resolver/impl/ChainingAttributeExtractor.cpp | 8 + .../resolver/impl/ChainingAttributeResolver.cpp | 17 + .../resolver/impl/DelegationAttributeExtractor.cpp | 49 +- .../impl/KeyDescriptorAttributeExtractor.cpp | 12 +- .../resolver/impl/QueryAttributeResolver.cpp | 5 +- .../impl/SimpleAggregationAttributeResolver.cpp | 7 +- .../resolver/impl/XMLAttributeExtractor.cpp | 7 + shibsp/binding/ArtifactResolver.h | 6 +- shibsp/binding/SOAPClient.h | 10 +- shibsp/binding/impl/ArtifactResolver.cpp | 13 +- shibsp/binding/impl/SOAPClient.cpp | 13 +- shibsp/exceptions.h | 10 +- shibsp/handler/AbstractHandler.h | 27 +- shibsp/handler/AssertionConsumerService.h | 39 +- shibsp/handler/Handler.h | 19 +- shibsp/handler/LogoutHandler.h | 23 +- shibsp/handler/RemotedHandler.h | 10 +- shibsp/handler/SessionInitiator.h | 14 +- shibsp/handler/impl/AbstractHandler.cpp | 1330 ++++---- shibsp/handler/impl/AssertionConsumerService.cpp | 15 +- shibsp/handler/impl/AssertionLookup.cpp | 13 +- shibsp/handler/impl/LocalLogoutInitiator.cpp | 14 +- shibsp/handler/impl/LogoutHandler.cpp | 58 +- shibsp/handler/impl/MetadataGenerator.cpp | 20 +- shibsp/handler/impl/RemotedHandler.cpp | 5 + shibsp/handler/impl/SAML1Consumer.cpp | 6 +- shibsp/handler/impl/SAML2ArtifactResolution.cpp | 8 +- shibsp/handler/impl/SAML2Consumer.cpp | 6 +- shibsp/handler/impl/SAML2Logout.cpp | 14 +- shibsp/handler/impl/SAML2LogoutInitiator.cpp | 42 +- shibsp/handler/impl/SAML2NameIDMgmt.cpp | 5 +- shibsp/handler/impl/SAML2SessionInitiator.cpp | 58 +- shibsp/handler/impl/SAMLDSSessionInitiator.cpp | 14 +- shibsp/handler/impl/SessionInitiator.cpp | 21 +- shibsp/handler/impl/Shib1SessionInitiator.cpp | 19 +- shibsp/handler/impl/StatusHandler.cpp | 4 + shibsp/handler/impl/WAYFSessionInitiator.cpp | 34 +- shibsp/impl/ChainingAccessControl.cpp | 282 +- shibsp/impl/StorageServiceSessionCache.cpp | 36 +- shibsp/impl/XMLAccessControl.cpp | 888 ++--- shibsp/impl/XMLRequestMapper.cpp | 13 +- shibsp/impl/XMLServiceProvider.cpp | 3386 ++++++++++---------- shibsp/lite/CommonDomainCookie.cpp | 9 + shibsp/lite/CommonDomainCookie.h | 8 +- shibsp/lite/SAMLConstants.h | 3 +- shibsp/metadata/DynamicMetadataProvider.cpp | 14 +- shibsp/metadata/MetadataExt.h | 15 +- shibsp/metadata/MetadataExtImpl.cpp | 3 +- shibsp/metadata/MetadataExtSchemaValidators.cpp | 5 +- shibsp/metadata/MetadataProviderCriteria.cpp | 55 + shibsp/metadata/MetadataProviderCriteria.h | 32 +- shibsp/paths.h | 106 +- shibsp/paths.h.in | 106 +- shibsp/remoting/ListenerService.h | 15 +- shibsp/remoting/ddf.h | 12 +- shibsp/remoting/impl/ListenerService.cpp | 25 + shibsp/remoting/impl/ddf.cpp | 22 +- shibsp/resource.h | 30 +- shibsp/security/PKIXTrustEngine.cpp | 1 + shibsp/security/SecurityPolicy.cpp | 9 + shibsp/security/SecurityPolicy.h | 6 +- shibsp/shibsp-lite.vcproj | 24 +- shibsp/shibsp.rc | 26 +- shibsp/shibsp.vcproj | 32 +- shibsp/util/CGIParser.cpp | 1 + shibsp/util/CGIParser.h | 8 +- shibsp/util/DOMPropertySet.cpp | 33 +- shibsp/util/DOMPropertySet.h | 20 +- shibsp/util/PropertySet.h | 8 +- shibsp/util/SPConstants.cpp | 232 +- shibsp/util/SPConstants.h | 8 +- shibsp/util/TemplateParameters.cpp | 18 +- shibsp/util/TemplateParameters.h | 18 +- shibsp/version.h | 4 +- util/Makefile.in | 2 + util/mdquery.cpp | 322 +- util/resolvertest.cpp | 7 +- 225 files changed, 11358 insertions(+), 12130 deletions(-) create mode 100644 configs/partialLogout.html mode change 100755 => 100644 doc/CREDITS.txt delete mode 100644 isapi_shib/isapi_shib.cpp.mine delete mode 100644 isapi_shib/isapi_shib.cpp.r3059 delete mode 100644 isapi_shib/isapi_shib.cpp.r3097 create mode 100644 shibsp/attribute/NameIDAttribute.cpp create mode 100644 shibsp/attribute/ScopedAttribute.cpp create mode 100644 shibsp/attribute/SimpleAttribute.cpp create mode 100644 shibsp/attribute/XMLAttribute.cpp create mode 100644 shibsp/attribute/filtering/impl/BasicFilteringContext.cpp create mode 100644 shibsp/metadata/MetadataProviderCriteria.cpp diff --git a/Makefile.in b/Makefile.in index b296c95..5763f79 100644 --- a/Makefile.in +++ b/Makefile.in @@ -110,6 +110,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/Portfile b/Portfile index 50c87a1..6a37645 100644 --- a/Portfile +++ b/Portfile @@ -1,7 +1,7 @@ PortSystem 1.0 name shibboleth -version 2.2.1 +version 2.3 categories security www shibboleth maintainers scantor snc description Shibboleth Native Service Provider diff --git a/adfs/Makefile.am b/adfs/Makefile.am index 82913b5..196504b 100644 --- a/adfs/Makefile.am +++ b/adfs/Makefile.am @@ -1,25 +1,25 @@ -AUTOMAKE_OPTIONS = foreign - -plugindir = $(libdir)/@PACKAGE@ -plugin_LTLIBRARIES = adfs.la adfs-lite.la - -adfs_la_LIBADD = \ - $(top_builddir)/shibsp/libshibsp.la - -adfs_la_SOURCES = \ - adfs.cpp - -adfs_lite_la_LIBADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -adfs_lite_la_SOURCES = \ - adfs.cpp - -adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) -adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS) -adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE - -install-exec-hook: - for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done - -EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc +AUTOMAKE_OPTIONS = foreign + +plugindir = $(libdir)/@PACKAGE@ +plugin_LTLIBRARIES = adfs.la adfs-lite.la + +adfs_la_LIBADD = \ + $(top_builddir)/shibsp/libshibsp.la + +adfs_la_SOURCES = \ + adfs.cpp + +adfs_lite_la_LIBADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +adfs_lite_la_SOURCES = \ + adfs.cpp + +adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) +adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS) +adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE + +install-exec-hook: + for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done + +EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc diff --git a/adfs/Makefile.in b/adfs/Makefile.in index 602bba9..85861e1 100644 --- a/adfs/Makefile.in +++ b/adfs/Makefile.in @@ -84,6 +84,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index bc84c2f..41c78e6 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -34,34 +34,36 @@ # define ADFS_EXPORTS #endif -#include - #include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include -#include +#include #ifndef SHIBSP_LITE # include # include # include +# include +# include # include -# include # include # include # include -# include +# include # include +# include # include using namespace opensaml::saml2md; # ifndef min @@ -112,7 +114,7 @@ namespace { { 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 loc = getString("Location"); if (loc.first) { @@ -334,7 +336,7 @@ pair ADFSSessionInitiator::run(SPRequest& request, string& entityID, 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"); @@ -361,30 +363,36 @@ pair ADFSSessionInitiator::run(SPRequest& request, string& entityID, acClass = getString("authnContextClassRef"); } - // Since we're not passing by index, we need to fully compute the return URL. if (!ACS) { - pair index = getUnsignedInt("defaultACSIndex"); + pair 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& 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 ACSbinding = ACS ? ACS->getXMLString("Binding") : pair(false,NULL); + pair 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 loc=ACS ? ACS->getString("Location") : pair(false,NULL); + pair loc=ACS->getString("Location"); if (loc.first) ACSloc+=loc.second; if (isHandler) { @@ -619,30 +627,29 @@ void ADFSConsumer::implementProtocol( // Extract message and issuer details from assertion. extractMessageDetails(*token, m_protocol.get(), policy); + // Populate recipient as audience. + const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast(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(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(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()) @@ -679,9 +686,7 @@ void ADFSConsumer::implementProtocol( 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()) @@ -875,7 +880,7 @@ pair ADFSLogoutInitiator::doRequest( 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 @@ -903,7 +908,8 @@ pair ADFSLogoutInitiator::doRequest( ).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()) ); } @@ -982,5 +988,5 @@ pair ADFSLogout::run(SPRequest& request, bool isHandler) const if (param) return make_pair(true, request.sendRedirect(param)); - return sendLogoutPage(app, request, request, false, "Logout complete."); + return sendLogoutPage(app, request, request, "global"); } diff --git a/adfs/adfs.rc b/adfs/adfs.rc index 7db3d05..9e46d04 100644 --- a/adfs/adfs.rc +++ b/adfs/adfs.rc @@ -54,8 +54,8 @@ 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 @@ -73,7 +73,7 @@ BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "Internet2\0" VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0" - VALUE "FileVersion", "2, 2, 1, 0\0" + VALUE "FileVersion", "2, 3, 0, 0\0" #ifdef SHIBSP_LITE VALUE "InternalName", "adfs-lite\0" #else @@ -87,8 +87,8 @@ BEGIN VALUE "OriginalFilename", "adfs.so\0" #endif 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 diff --git a/adfs/resource.h b/adfs/resource.h index 95f2c63..3ba1cce 100644 --- a/adfs/resource.h +++ b/adfs/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by adfs.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by adfs.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/apache/Makefile.in b/apache/Makefile.in index 8d3aece..f493949 100644 --- a/apache/Makefile.in +++ b/apache/Makefile.in @@ -106,6 +106,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/apache/mod_apache.cpp b/apache/mod_apache.cpp index 661b448..efe531e 100644 --- a/apache/mod_apache.cpp +++ b/apache/mod_apache.cpp @@ -69,6 +69,7 @@ #include #endif +#include #include #include #include @@ -523,6 +524,7 @@ public: 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 @@ -552,6 +554,7 @@ public: return DONE; } long sendRedirect(const char* url) { + HTTPResponse::sendRedirect(url); ap_table_set(m_req->headers_out, "Location", url); return REDIRECT; } diff --git a/apache/mod_shib20.vcproj b/apache/mod_shib20.vcproj index 91d85c5..f767d76 100644 --- a/apache/mod_shib20.vcproj +++ b/apache/mod_shib20.vcproj @@ -52,7 +52,7 @@ 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" @@ -80,7 +80,7 @@ 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" @@ -142,7 +142,7 @@ 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" @@ -170,7 +170,7 @@ 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" @@ -232,7 +232,7 @@ . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. @@ -55,7 +53,7 @@ version="\ 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 @@ -68,11 +66,11 @@ Try \`$me --help' for more information." 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. @@ -125,7 +123,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in ;; ,,*) 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) @@ -138,6 +136,13 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown 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 @@ -198,29 +203,50 @@ 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 @@ -258,49 +284,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in "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 @@ -308,32 +327,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in 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*) @@ -342,10 +361,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in 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 @@ -357,10 +376,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in 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 @@ -371,40 +390,37 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # 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 @@ -428,33 +444,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in 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` @@ -470,29 +485,29 @@ EOF 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` @@ -500,7 +515,7 @@ EOF 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 @@ -515,18 +530,14 @@ EOF 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 @@ -540,28 +551,28 @@ EOF 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 @@ -623,19 +634,9 @@ EOF 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 @@ -643,11 +644,11 @@ EOF 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 @@ -675,166 +676,150 @@ EOF 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 + #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 @@ -852,7 +837,7 @@ EOF #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 @@ -871,14 +856,14 @@ EOF #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 ;; @@ -892,7 +877,7 @@ EOF 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 @@ -900,25 +885,25 @@ EOF 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 @@ -936,15 +921,15 @@ EOF ;; 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 @@ -967,23 +952,17 @@ EOF 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... @@ -991,27 +970,24 @@ EOF # 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 @@ -1019,16 +995,15 @@ EOF 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' /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` @@ -1120,73 +1095,68 @@ EOF else echo ns32k-sni-sysv fi - exit ;; + exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 - exit ;; + exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 @@ -1194,25 +1164,22 @@ EOF 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 @@ -1223,44 +1190,28 @@ EOF 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 @@ -1292,7 +1243,7 @@ main () #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) @@ -1381,12 +1332,11 @@ main () } 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) @@ -1395,22 +1345,22 @@ then 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 @@ -1421,9 +1371,7 @@ This script, last modified $timestamp, has failed to recognize 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 diff --git a/config.h.in b/config.h.in index e74571c..1126858 100644 --- a/config.h.in +++ b/config.h.in @@ -79,6 +79,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define if xmltooling library was found */ +#undef HAVE_XMLTOOLING + /* Name of package */ #undef PACKAGE diff --git a/config.sub b/config.sub index 1c366df..6b2ff9f 100755 --- a/config.sub +++ b/config.sub @@ -1,9 +1,9 @@ #! /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 @@ -21,15 +21,14 @@ timestamp='2005-07-08' # # 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 . Submit a context # diff and a properly formatted ChangeLog entry. # @@ -71,7 +70,7 @@ Report bugs and patches to ." 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 @@ -84,11 +83,11 @@ Try \`$me --help' for more information." 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. @@ -100,7 +99,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit ;; + exit 0;; * ) break ;; @@ -119,8 +118,7 @@ esac # 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/'` ;; @@ -146,7 +144,7 @@ case $os in -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 ;; @@ -230,16 +228,14 @@ case $basic_machine in | 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 \ @@ -248,37 +244,31 @@ case $basic_machine in | 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 @@ -306,19 +296,19 @@ case $basic_machine in | 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-* \ @@ -327,40 +317,34 @@ case $basic_machine in | 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) @@ -377,9 +361,6 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) - basic_machine=abacus-unknown - ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -397,9 +378,6 @@ case $basic_machine in amd64) basic_machine=x86_64-pc ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -459,27 +437,12 @@ case $basic_machine in 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 ;; @@ -502,10 +465,6 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx @@ -684,6 +643,10 @@ case $basic_machine in 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 @@ -764,6 +727,10 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -771,12 +738,9 @@ case $basic_machine in 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 @@ -869,12 +833,6 @@ case $basic_machine in 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 @@ -998,10 +956,6 @@ case $basic_machine in tower | tower-32) basic_machine=m68k-ncr ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; udi29k) basic_machine=a29k-amd os=-udi @@ -1045,10 +999,6 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; xps | xps100) basic_machine=xps100-honeywell ;; @@ -1079,9 +1029,6 @@ case $basic_machine in romp) basic_machine=romp-ibm ;; - mmix) - basic_machine=mmix-knuth - ;; rs6000) basic_machine=rs6000-ibm ;; @@ -1098,9 +1045,12 @@ case $basic_machine in 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 ;; @@ -1174,21 +1124,19 @@ case $os in | -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*) @@ -1206,15 +1154,12 @@ case $os in 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|'` ;; @@ -1227,9 +1172,6 @@ case $os in -opened*) os=-openedition ;; - -os400*) - os=-os400 - ;; -wince*) os=-wince ;; @@ -1251,9 +1193,6 @@ case $os in -atheos*) os=-atheos ;; - -syllable*) - os=-syllable - ;; -386bsd) os=-bsd ;; @@ -1276,9 +1215,6 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) - os=-tpf - ;; -triton*) os=-sysv3 ;; @@ -1315,9 +1251,6 @@ case $os in -kaos*) os=-kaos ;; - -zvmoe) - os=-zvmoe - ;; -none) ;; *) @@ -1349,9 +1282,9 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff - ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 @@ -1395,15 +1328,9 @@ case $basic_machine in *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; - *-knuth) - os=-mmixware - ;; *-wec) os=-proelf ;; @@ -1536,15 +1463,9 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; - -os400*) - vendor=ibm - ;; -ptx*) vendor=sequent ;; - -tpf*) - vendor=ibm - ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; @@ -1569,7 +1490,7 @@ case $basic_machine in esac echo $basic_machine$os -exit +exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/config_win32.h b/config_win32.h index 04b4dd2..9778d65 100644 --- a/config_win32.h +++ b/config_win32.h @@ -117,13 +117,13 @@ #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. */ @@ -136,7 +136,7 @@ /* #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 */ diff --git a/configs/Makefile.am b/configs/Makefile.am index cd01d03..5a18b62 100644 --- a/configs/Makefile.am +++ b/configs/Makefile.am @@ -1,4 +1,4 @@ -## $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 @@ -46,6 +46,7 @@ CONFIGFILES = \ postTemplate.html \ localLogout.html \ globalLogout.html \ + partialLogout.html \ sslError.html # diff --git a/configs/Makefile.in b/configs/Makefile.in index 40939a8..e621f3c 100644 --- a/configs/Makefile.in +++ b/configs/Makefile.in @@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ @@ -302,6 +304,7 @@ CONFIGFILES = \ postTemplate.html \ localLogout.html \ globalLogout.html \ + partialLogout.html \ sslError.html CLEANFILES = \ diff --git a/configs/accessError.html b/configs/accessError.html index 546ea4f..ee25974 100644 --- a/configs/accessError.html +++ b/configs/accessError.html @@ -5,7 +5,7 @@ - + Authorization Failed @@ -15,13 +15,15 @@ Logo

Authorization Failed

+

Based on the information provided to this application about you, you are not authorized to access the resource at "" +

-

- +

Please contact the administrator of this service or application if you believe this to be an error at +

diff --git a/configs/apache.config.in b/configs/apache.config.in index bce4a7e..4eaa51f 100644 --- a/configs/apache.config.in +++ b/configs/apache.config.in @@ -1,11 +1,11 @@ +# 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. @@ -20,7 +20,7 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_13.so SetHandler shib-handler -# + # Another way of addressing this is to apply Shibboleth # globally to the site in "lazy" session mode: # @@ -37,16 +37,15 @@ SetHandler shib-handler # -# 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". # AuthType shibboleth - ShibRequireSession On + ShibRequestSetting requireSession 1 require valid-user diff --git a/configs/apache2.config.in b/configs/apache2.config.in index 7ea0bb7..ec3df49 100644 --- a/configs/apache2.config.in +++ b/configs/apache2.config.in @@ -1,14 +1,14 @@ +# 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 @@ -24,16 +24,15 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_20.so # -# 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". # AuthType shibboleth - ShibRequireSession On + ShibRequestSetting requireSession 1 require valid-user diff --git a/configs/apache22.config.in b/configs/apache22.config.in index 6823db5..853dd42 100644 --- a/configs/apache22.config.in +++ b/configs/apache22.config.in @@ -1,14 +1,14 @@ +# 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 @@ -24,16 +24,15 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_22.so # -# 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". # AuthType shibboleth - ShibRequireSession On + ShibRequestSetting requireSession 1 require valid-user diff --git a/configs/globalLogout.html b/configs/globalLogout.html index bbdf64e..64b3bdc 100644 --- a/configs/globalLogout.html +++ b/configs/globalLogout.html @@ -5,7 +5,7 @@ - + Global Logout @@ -17,24 +17,11 @@

Status of Global Logout:

- -

Error from your identity provider:

-
- Status:
- - Sub-Status:
-
- - Message:
-
-
-
-

If the message above indicates success, you have been logged out of all the applications and systems that support the logout mechanism.

-

It is still strongly advised that you close your browser to complete the -logout process.

+

Regardless of the outcome, it is strongly advised that you close your browser +to ensure that you complete the logout process.

diff --git a/configs/keygen.bat b/configs/keygen.bat index 401269c..501942b 100644 --- a/configs/keygen.bat +++ b/configs/keygen.bat @@ -1,98 +1,98 @@ -@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 +@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 diff --git a/configs/keygen.sh b/configs/keygen.sh index 0729fe3..5ae60db 100755 --- a/configs/keygen.sh +++ b/configs/keygen.sh @@ -66,5 +66,8 @@ else 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 diff --git a/configs/localLogout.html b/configs/localLogout.html index 1bcb1d1..5d749a9 100644 --- a/configs/localLogout.html +++ b/configs/localLogout.html @@ -5,7 +5,7 @@ - + Local Logout diff --git a/configs/metadataError.html b/configs/metadataError.html index d0e667a..3144e1c 100644 --- a/configs/metadataError.html +++ b/configs/metadataError.html @@ -5,7 +5,7 @@ - + Unknown Identity Provider diff --git a/configs/partialLogout.html b/configs/partialLogout.html new file mode 100644 index 0000000..daafda6 --- /dev/null +++ b/configs/partialLogout.html @@ -0,0 +1,22 @@ + + + + + + + + Partial Logout + + + + +Logo +

Partial Logout

+ +

You remain logged into one or more applications accessed during your session. +To complete the logout process, please close/exit your browser completely.

+ + + diff --git a/configs/sessionError.html b/configs/sessionError.html index 2273174..fbfe9e5 100644 --- a/configs/sessionError.html +++ b/configs/sessionError.html @@ -5,7 +5,7 @@ - + <shibmlp errorType/> @@ -31,10 +31,10 @@
Status:
- Sub-Status:
+ Sub-Status:
- Message:
+ Message:
diff --git a/configs/shibboleth2.xml b/configs/shibboleth2.xml index d02da4c..d935c7f 100644 --- a/configs/shibboleth2.xml +++ b/configs/shibboleth2.xml @@ -108,21 +108,21 @@ - - + + - - - + + + - - + + @@ -190,18 +190,10 @@ - @@ -232,13 +224,13 @@ - + - + @@ -267,4 +259,4 @@ - \ No newline at end of file + diff --git a/configs/shibd-debian.in b/configs/shibd-debian.in index 13e8240..59f0995 100644 --- a/configs/shibd-debian.in +++ b/configs/shibd-debian.in @@ -39,6 +39,9 @@ DAEMON_OPTS="$DAEMON_OPTS -c $SHIBSP_CONFIG" # 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 diff --git a/configs/shibd-redhat.in b/configs/shibd-redhat.in index 02e3426..fd80ee5 100644 --- a/configs/shibd-redhat.in +++ b/configs/shibd-redhat.in @@ -14,6 +14,7 @@ shibd="@-PREFIX-@/sbin/shibd" SHIBD_USER=root pidfile=@-PKGRUNDIR-@/shibd.pid prog=shibd +VER=`cat /etc/redhat-release | awk '{print $3}' | awk -F . '{print $1}'` RETVAL=0 start() { @@ -24,7 +25,7 @@ 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 @@ -36,7 +37,11 @@ start() { 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 @@ -46,10 +51,10 @@ start() { 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=$? @@ -66,7 +71,7 @@ case "$1" in stop ;; status) - status $shibd + status $shibd RETVAL=$? ;; restart) diff --git a/configs/shibd-suse.in b/configs/shibd-suse.in index 1dceeda..62a1619 100644 --- a/configs/shibd-suse.in +++ b/configs/shibd-suse.in @@ -32,6 +32,9 @@ DAEMON_OPTS="$DAEMON_OPTS -c $SHIB_CONFIG" # 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 diff --git a/configs/sslError.html b/configs/sslError.html index 2d25f3c..350d45a 100644 --- a/configs/sslError.html +++ b/configs/sslError.html @@ -5,7 +5,7 @@ - + POST Failed @@ -15,14 +15,17 @@ Logo

POST Failed

- +

You have attemped to submit information without the protection -of SSL to this site.
+of SSL to this site.
+

+

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 https:// and report this problem to +

diff --git a/configure b/configure index cd4b0c2..1471e1e 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /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 . # @@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # 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. @@ -464,7 +464,7 @@ ac_includes_default="\ # include #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. @@ -957,7 +957,7 @@ if test "$ac_init_help" = "long"; then # 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]... @@ -1023,7 +1023,7 @@ fi 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 @@ -1078,8 +1078,10 @@ Optional Packages: --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: @@ -1197,7 +1199,7 @@ fi 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. @@ -1211,7 +1213,7 @@ cat >&5 <<_ACEOF 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 $@ @@ -1856,7 +1858,7 @@ fi # Define the identity of the package. PACKAGE=shibboleth - VERSION=2.2.1 + VERSION=2.3 cat >>confdefs.h <<_ACEOF @@ -6100,7 +6102,7 @@ ia64-*-hpux*) ;; *-*-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=$? @@ -7208,7 +7210,7 @@ fi # 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 &5\"") >&5 @@ -8246,11 +8248,11 @@ else -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 @@ -8479,11 +8481,11 @@ else -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 @@ -8539,11 +8541,11 @@ else -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 @@ -9873,7 +9875,7 @@ linux*) 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=$? @@ -10744,7 +10746,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&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 @@ -13085,11 +13087,11 @@ else -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 @@ -13596,7 +13598,7 @@ linux*) 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=$? @@ -14467,7 +14469,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&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 @@ -15452,11 +15454,11 @@ else -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 @@ -16766,7 +16768,7 @@ linux*) 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=$? @@ -17511,11 +17513,11 @@ else -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 @@ -17744,11 +17746,11 @@ else -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 @@ -17804,11 +17806,11 @@ else -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 @@ -19138,7 +19140,7 @@ linux*) 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=$? @@ -20009,7 +20011,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +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 @@ -25427,6 +25490,7 @@ fi # --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 @@ -25646,9 +25710,77 @@ echo "$as_me: error: Unable to locate apr-config, may need --with-apr option." > { (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 @@ -25660,6 +25792,7 @@ 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 @@ -25879,9 +26012,77 @@ echo "$as_me: error: Unable to locate apr-1-config, may need --with-apr1 option. { (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 @@ -26891,7 +27092,7 @@ _ASBOX } >&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 @@ -26954,7 +27155,7 @@ _ACEOF 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'`\\" @@ -27318,10 +27519,12 @@ s,@APXS_CFLAGS@,$APXS_CFLAGS,;t t 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 diff --git a/configure.ac b/configure.ac index fd07125..7265638 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ 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) @@ -258,6 +258,20 @@ LITE_LIBS="-lxmltooling-lite" 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::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="" @@ -618,6 +632,7 @@ AC_SUBST(APXS_INCLUDE) # --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]), @@ -695,9 +710,30 @@ if test "$WANT_APACHE_20" = "yes" ; then 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 @@ -709,6 +745,7 @@ AC_SUBST(APXS2_INCLUDE) # --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]), @@ -786,9 +823,30 @@ if test "$WANT_APACHE_22" = "yes" ; then 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 diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt old mode 100755 new mode 100644 diff --git a/doc/Makefile.in b/doc/Makefile.in index ab75e34..ca27df3 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/doc/README.txt b/doc/README.txt index 6443108..e21e018 100644 --- a/doc/README.txt +++ b/doc/README.txt @@ -1,4 +1,4 @@ -Version 2.2.1 +Version 2.3 Welcome to Internet2's Shibboleth diff --git a/doc/RELEASE.txt b/doc/RELEASE.txt index 66ee2a7..51a97cc 100644 --- a/doc/RELEASE.txt +++ b/doc/RELEASE.txt @@ -1,14 +1,14 @@ Release Notes Shibboleth Native SP -2.2.1 +2.3 NOTE: The shibboleth2.xml configuration format in this release is fully compatible with the 2.1 release, but there are some small changes required to eliminate various warnings about deprecated options. List of issues addressed by this release: -https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC +https://bugs.internet2.edu/jira/browse/SSPCPP/fixforversion/10261 Fully Supported diff --git a/fastcgi/Makefile.am b/fastcgi/Makefile.am index f0bec65..1c4ba8c 100644 --- a/fastcgi/Makefile.am +++ b/fastcgi/Makefile.am @@ -1,30 +1,30 @@ -AUTOMAKE_OPTIONS = foreign - -if BUILD_FASTCGI - -fastcgidir = $(libdir)/@PACKAGE@ - -fastcgi_PROGRAMS = shibauthorizer shibresponder - -shibauthorizer_SOURCES = shibauthorizer.cpp -shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE) -shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) -shibauthorizer_LDADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -shibresponder_SOURCES = shibresponder.cpp -shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE) -shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) -shibresponder_LDADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -endif - -EXTRA_DIST = \ - shibauthorizer.cpp \ - shibauthorizer.vcproj \ - shibauthorizer.rc \ - shibresponder.cpp \ - shibresponder.vcproj \ - shibresponder.rc \ - resource.h +AUTOMAKE_OPTIONS = foreign + +if BUILD_FASTCGI + +fastcgidir = $(libdir)/@PACKAGE@ + +fastcgi_PROGRAMS = shibauthorizer shibresponder + +shibauthorizer_SOURCES = shibauthorizer.cpp +shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE) +shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) +shibauthorizer_LDADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +shibresponder_SOURCES = shibresponder.cpp +shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE) +shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) +shibresponder_LDADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +endif + +EXTRA_DIST = \ + shibauthorizer.cpp \ + shibauthorizer.vcproj \ + shibauthorizer.rc \ + shibresponder.cpp \ + shibresponder.vcproj \ + shibresponder.rc \ + resource.h diff --git a/fastcgi/Makefile.in b/fastcgi/Makefile.in index a9af072..7e93df4 100644 --- a/fastcgi/Makefile.in +++ b/fastcgi/Makefile.in @@ -87,6 +87,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/fastcgi/resource.h b/fastcgi/resource.h index 55162af..f3772c1 100644 --- a/fastcgi/resource.h +++ b/fastcgi/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by isapi_shib.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by isapi_shib.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/fastcgi/shibauthorizer.cpp b/fastcgi/shibauthorizer.cpp index 59f4417..b7babb5 100644 --- a/fastcgi/shibauthorizer.cpp +++ b/fastcgi/shibauthorizer.cpp @@ -1,426 +1,428 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer - - Andre Cruz -*/ - -#define SHIBSP_LITE -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 -#define _SCL_SECURE_NO_WARNINGS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef HAVE_UNISTD_H -# include -# include -#endif -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace xercesc; -using namespace std; - -static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); -static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); - -typedef enum { - SHIB_RETURN_OK, - SHIB_RETURN_KO, - SHIB_RETURN_DONE -} shib_return_t; - -class ShibTargetFCGIAuth : public AbstractSPRequest -{ - FCGX_Request* m_req; - int m_port; - string m_scheme,m_hostname; - multimap m_response_headers; -public: - map m_request_headers; - - ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0) - : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) { - const char* server_name_str = hostname; - if (!server_name_str || !*server_name_str) - server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); - m_hostname = server_name_str; - - m_port = port; - if (!m_port) { - char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); - m_port = strtol(server_port_str, &server_port_str, 10); - if (*server_port_str) { - cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; - throw runtime_error("Unable to determine server port."); - } - } - - const char* server_scheme_str = scheme; - if (!server_scheme_str || !*server_scheme_str) - server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; - m_scheme = server_scheme_str; - - setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); - } - - ~ShibTargetFCGIAuth() { } - - const char* getScheme() const { - return m_scheme.c_str(); - } - const char* getHostname() const { - return m_hostname.c_str(); - } - int getPort() const { - return m_port; - } - const char* getMethod() const { - return FCGX_GetParam("REQUEST_METHOD", m_req->envp); - } - string getContentType() const { - const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); - return s ? s : ""; - } - long getContentLength() const { - const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); - return s ? atol(s) : 0; - } - string getRemoteAddr() const { - string ret = AbstractSPRequest::getRemoteAddr(); - if (!ret.empty()) - return ret; - const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); - return s ? s : ""; - } - void log(SPLogLevel level, const string& msg) const { - AbstractSPRequest::log(level,msg); - if (level >= SPError) - cerr << "shib: " << msg; - } - void clearHeader(const char* rawname, const char* cginame) { - // No need, since we use environment variables. - } - void setHeader(const char* name, const char* value) { - if (value) - m_request_headers[name] = value; - else - m_request_headers.erase(name); - } - string getHeader(const char* name) const { - // Look in the local map first. - map::const_iterator i = m_request_headers.find(name); - if (i != m_request_headers.end()) - return i->second; - // Nothing set locally and this isn't a "secure" call, so check the request. - string hdr("HTTP_"); - for (; *name; ++name) { - if (*name=='-') - hdr += '_'; - else - hdr += toupper(*name); - } - char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); - return s ? s : ""; - } - string getSecureHeader(const char* name) const { - // Look in the local map only. - map::const_iterator i = m_request_headers.find(name); - if (i != m_request_headers.end()) - return i->second; - return ""; - } - void setRemoteUser(const char* user) { - if (user) - m_request_headers["REMOTE_USER"] = user; - else - m_request_headers.erase("REMOTE_USER"); - } - string getRemoteUser() const { - map::const_iterator i = m_request_headers.find("REMOTE_USER"); - if (i != m_request_headers.end()) - return i->second; - else { - char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp); - if (remote_user) - return remote_user; - } - return ""; - } - void setAuthType(const char* authtype) { - if (authtype) - m_request_headers["AUTH_TYPE"] = authtype; - else - m_request_headers.erase("AUTH_TYPE"); - } - string getAuthType() const { - map::const_iterator i = m_request_headers.find("AUTH_TYPE"); - if (i != m_request_headers.end()) - return i->second; - else { - char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp); - if (auth_type) - return auth_type; - } - return ""; - } - void setResponseHeader(const char* name, const char* value) { - // Set for later. - if (value) - m_response_headers.insert(make_pair(name,value)); - else - m_response_headers.erase(name); - } - const char* getQueryString() const { - return FCGX_GetParam("QUERY_STRING", m_req->envp); - } - const char* getRequestBody() const { - throw runtime_error("getRequestBody not implemented by FastCGI authorizer."); - } - - long sendResponse(istream& in, long status) { - string hdr = string("Connection: close\r\n"); - for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - - // We can't return 200 OK here or else the filter is bypassed - // so custom Shib errors will get turned into a generic page. - const char* codestr="Status: 500 Server Error"; - switch (status) { - case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; - case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; - case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; - } - cout << codestr << "\r\n" << hdr << "\r\n"; - char buf[1024]; - while (in) { - in.read(buf,1024); - cout.write(buf, in.gcount()); - } - return SHIB_RETURN_DONE; - } - - long sendRedirect(const char* url) { - string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 40\r\n" - "Expires: 01-Jan-1997 12:00:00 GMT\r\n" - "Cache-Control: private,no-store,no-cache\r\n"; - for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - hdr += "\r\n"; - - cout << hdr << "Redirecting..."; - return SHIB_RETURN_DONE; - } - - long returnDecline() { - return SHIB_RETURN_KO; - } - - long returnOK() { - return SHIB_RETURN_OK; - } - - const vector& getClientCertificates() const { - static vector g_NoCerts; - return g_NoCerts; - } -}; - -static void print_ok(const map& headers) -{ - cout << "Status: 200 OK" << "\r\n"; - for (map::const_iterator iter = headers.begin(); iter != headers.end(); iter++) { - cout << "Variable-" << iter->first << ": " << iter->second << "\r\n"; - } - cout << "\r\n"; -} - -static void print_error(const char* msg) -{ - cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; -} - -int main(void) -{ - SPConfig* g_Config=&SPConfig::getConfig(); - g_Config->setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::RequestMapping | - SPConfig::InProcess | - SPConfig::Logging | - SPConfig::Handlers - ); - if (!g_Config->init()) { - cerr << "failed to initialize Shibboleth libraries" << endl; - exit(1); - } - - try { - if (!g_Config->instantiate(NULL, true)) - throw runtime_error("unknown error"); - } - catch (exception& ex) { - g_Config->term(); - cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; - exit(1); - } - - string g_ServerScheme; - string g_ServerName; - int g_ServerPort=0; - - // Load "authoritative" URL fields. - char* var = getenv("SHIBSP_SERVER_NAME"); - if (var) - g_ServerName = var; - var = getenv("SHIBSP_SERVER_SCHEME"); - if (var) - g_ServerScheme = var; - var = getenv("SHIBSP_SERVER_PORT"); - if (var) - g_ServerPort = atoi(var); - - streambuf* cout_streambuf = cout.rdbuf(); - streambuf* cerr_streambuf = cerr.rdbuf(); - - FCGX_Request request; - - FCGX_Init(); - FCGX_InitRequest(&request, 0, 0); - - cout << "Shibboleth initialization complete. Starting request loop." << endl; - while (FCGX_Accept_r(&request) == 0) - { - // Note that the default bufsize (0) will cause the use of iostream - // methods that require positioning (such as peek(), seek(), - // unget() and putback()) to fail (in favour of more efficient IO). - fcgi_streambuf cout_fcgi_streambuf(request.out); - fcgi_streambuf cerr_fcgi_streambuf(request.err); - - cout.rdbuf(&cout_fcgi_streambuf); - cerr.rdbuf(&cerr_fcgi_streambuf); - - try { - xmltooling::NDC ndc("FastCGI shibauthorizer"); - ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); - - pair res = sta.getServiceProvider().doAuthentication(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - res = sta.getServiceProvider().doExport(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doExport handled request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doExport returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - res = sta.getServiceProvider().doAuthorization(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - print_ok(sta.m_request_headers); - - } - catch (exception& e) { - cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl; - print_error("FastCGI Shibboleth authorizer caught an exception, check log for details."); - } - - // If the output streambufs had non-zero bufsizes and - // were constructed outside of the accept loop (i.e. - // their destructor won't be called here), they would - // have to be flushed here. - } - cout << "Request loop ended." << endl; - - cout.rdbuf(cout_streambuf); - cerr.rdbuf(cerr_streambuf); - - if (g_Config) - g_Config->term(); - - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer + + Andre Cruz +*/ + +#define SHIBSP_LITE +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _SCL_SECURE_NO_WARNINGS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_UNISTD_H +# include +# include +#endif +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); +static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); + +typedef enum { + SHIB_RETURN_OK, + SHIB_RETURN_KO, + SHIB_RETURN_DONE +} shib_return_t; + +class ShibTargetFCGIAuth : public AbstractSPRequest +{ + FCGX_Request* m_req; + int m_port; + string m_scheme,m_hostname; + multimap m_response_headers; +public: + map m_request_headers; + + ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0) + : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) { + const char* server_name_str = hostname; + if (!server_name_str || !*server_name_str) + server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); + m_hostname = server_name_str; + + m_port = port; + if (!m_port) { + char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); + m_port = strtol(server_port_str, &server_port_str, 10); + if (*server_port_str) { + cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; + throw runtime_error("Unable to determine server port."); + } + } + + const char* server_scheme_str = scheme; + if (!server_scheme_str || !*server_scheme_str) + server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; + m_scheme = server_scheme_str; + + setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); + } + + ~ShibTargetFCGIAuth() { } + + const char* getScheme() const { + return m_scheme.c_str(); + } + const char* getHostname() const { + return m_hostname.c_str(); + } + int getPort() const { + return m_port; + } + const char* getMethod() const { + return FCGX_GetParam("REQUEST_METHOD", m_req->envp); + } + string getContentType() const { + const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); + return s ? s : ""; + } + long getContentLength() const { + const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); + return s ? atol(s) : 0; + } + string getRemoteAddr() const { + string ret = AbstractSPRequest::getRemoteAddr(); + if (!ret.empty()) + return ret; + const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); + return s ? s : ""; + } + void log(SPLogLevel level, const string& msg) const { + AbstractSPRequest::log(level,msg); + if (level >= SPError) + cerr << "shib: " << msg; + } + void clearHeader(const char* rawname, const char* cginame) { + // No need, since we use environment variables. + } + void setHeader(const char* name, const char* value) { + if (value) + m_request_headers[name] = value; + else + m_request_headers.erase(name); + } + string getHeader(const char* name) const { + // Look in the local map first. + map::const_iterator i = m_request_headers.find(name); + if (i != m_request_headers.end()) + return i->second; + // Nothing set locally and this isn't a "secure" call, so check the request. + string hdr("HTTP_"); + for (; *name; ++name) { + if (*name=='-') + hdr += '_'; + else + hdr += toupper(*name); + } + char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); + return s ? s : ""; + } + string getSecureHeader(const char* name) const { + // Look in the local map only. + map::const_iterator i = m_request_headers.find(name); + if (i != m_request_headers.end()) + return i->second; + return ""; + } + void setRemoteUser(const char* user) { + if (user) + m_request_headers["REMOTE_USER"] = user; + else + m_request_headers.erase("REMOTE_USER"); + } + string getRemoteUser() const { + map::const_iterator i = m_request_headers.find("REMOTE_USER"); + if (i != m_request_headers.end()) + return i->second; + else { + char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp); + if (remote_user) + return remote_user; + } + return ""; + } + void setAuthType(const char* authtype) { + if (authtype) + m_request_headers["AUTH_TYPE"] = authtype; + else + m_request_headers.erase("AUTH_TYPE"); + } + string getAuthType() const { + map::const_iterator i = m_request_headers.find("AUTH_TYPE"); + if (i != m_request_headers.end()) + return i->second; + else { + char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp); + if (auth_type) + return auth_type; + } + return ""; + } + void setResponseHeader(const char* name, const char* value) { + 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::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::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + hdr += "\r\n"; + + cout << hdr << "Redirecting..."; + return SHIB_RETURN_DONE; + } + + long returnDecline() { + return SHIB_RETURN_KO; + } + + long returnOK() { + return SHIB_RETURN_OK; + } + + const vector& getClientCertificates() const { + static vector g_NoCerts; + return g_NoCerts; + } +}; + +static void print_ok(const map& headers) +{ + cout << "Status: 200 OK" << "\r\n"; + for (map::const_iterator iter = headers.begin(); iter != headers.end(); iter++) { + cout << "Variable-" << iter->first << ": " << iter->second << "\r\n"; + } + cout << "\r\n"; +} + +static void print_error(const char* msg) +{ + cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; +} + +int main(void) +{ + SPConfig* g_Config=&SPConfig::getConfig(); + g_Config->setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::RequestMapping | + SPConfig::InProcess | + SPConfig::Logging | + SPConfig::Handlers + ); + if (!g_Config->init()) { + cerr << "failed to initialize Shibboleth libraries" << endl; + exit(1); + } + + try { + if (!g_Config->instantiate(NULL, true)) + throw runtime_error("unknown error"); + } + catch (exception& ex) { + g_Config->term(); + cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; + exit(1); + } + + string g_ServerScheme; + string g_ServerName; + int g_ServerPort=0; + + // Load "authoritative" URL fields. + char* var = getenv("SHIBSP_SERVER_NAME"); + if (var) + g_ServerName = var; + var = getenv("SHIBSP_SERVER_SCHEME"); + if (var) + g_ServerScheme = var; + var = getenv("SHIBSP_SERVER_PORT"); + if (var) + g_ServerPort = atoi(var); + + streambuf* cout_streambuf = cout.rdbuf(); + streambuf* cerr_streambuf = cerr.rdbuf(); + + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + cout << "Shibboleth initialization complete. Starting request loop." << endl; + while (FCGX_Accept_r(&request) == 0) + { + // Note that the default bufsize (0) will cause the use of iostream + // methods that require positioning (such as peek(), seek(), + // unget() and putback()) to fail (in favour of more efficient IO). + fcgi_streambuf cout_fcgi_streambuf(request.out); + fcgi_streambuf cerr_fcgi_streambuf(request.err); + + cout.rdbuf(&cout_fcgi_streambuf); + cerr.rdbuf(&cerr_fcgi_streambuf); + + try { + xmltooling::NDC ndc("FastCGI shibauthorizer"); + ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); + + pair res = sta.getServiceProvider().doAuthentication(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + res = sta.getServiceProvider().doExport(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doExport handled request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doExport returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + res = sta.getServiceProvider().doAuthorization(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + print_ok(sta.m_request_headers); + + } + catch (exception& e) { + cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl; + print_error("FastCGI Shibboleth authorizer caught an exception, check log for details."); + } + + // If the output streambufs had non-zero bufsizes and + // were constructed outside of the accept loop (i.e. + // their destructor won't be called here), they would + // have to be flushed here. + } + cout << "Request loop ended." << endl; + + cout.rdbuf(cout_streambuf); + cerr.rdbuf(cerr_streambuf); + + if (g_Config) + g_Config->term(); + + return 0; +} diff --git a/fastcgi/shibauthorizer.rc b/fastcgi/shibauthorizer.rc index c9b4c1d..37258c9 100644 --- a/fastcgi/shibauthorizer.rc +++ b/fastcgi/shibauthorizer.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // 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 @@ -47,14 +47,14 @@ BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "Internet2\0" VALUE "FileDescription", "Shibboleth FastCGI Authorizer\0" - VALUE "FileVersion", "2, 2, 1, 0\0" + VALUE "FileVersion", "2, 3, 0, 0\0" VALUE "InternalName", "shibauthorizer\0" VALUE "LegalCopyright", "Copyright © 2009 Internet2\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "shibauthorizer.exe\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 diff --git a/fastcgi/shibresponder.cpp b/fastcgi/shibresponder.cpp index 1537e33..c99d945 100644 --- a/fastcgi/shibresponder.cpp +++ b/fastcgi/shibresponder.cpp @@ -1,398 +1,400 @@ -/* - * 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. - */ - -/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler - - Andre Cruz -*/ - -#define SHIBSP_LITE -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 -#define _SCL_SECURE_NO_WARNINGS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef HAVE_UNISTD_H -# include -# include -#endif -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace xercesc; -using namespace std; - -static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); -static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); - -typedef enum { - SHIB_RETURN_OK, - SHIB_RETURN_KO, - SHIB_RETURN_DONE -} shib_return_t; - -class ShibTargetFCGI : public AbstractSPRequest -{ - FCGX_Request* m_req; - const char* m_body; - multimap m_headers; - int m_port; - string m_scheme,m_hostname; - -public: - ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0) - : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) { - - const char* server_name_str = hostname; - if (!server_name_str || !*server_name_str) - server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); - m_hostname = server_name_str; - - m_port = port; - if (!m_port) { - char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); - m_port = strtol(server_port_str, &server_port_str, 10); - if (*server_port_str) { - cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; - throw runtime_error("Unable to determine server port."); - } - } - - const char* server_scheme_str = scheme; - if (!server_scheme_str || !*server_scheme_str) - server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; - m_scheme = server_scheme_str; - - setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); - } - - ~ShibTargetFCGI() { } - - const char* getScheme() const { - return m_scheme.c_str(); - } - const char* getHostname() const { - return m_hostname.c_str(); - } - int getPort() const { - return m_port; - } - const char* getMethod() const { - return FCGX_GetParam("REQUEST_METHOD", m_req->envp); - } - string getContentType() const { - const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); - return s ? s : ""; - } - long getContentLength() const { - const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); - return s ? atol(s) : 0; - } - string getRemoteUser() const { - const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp); - return s ? s : ""; - } - string getRemoteAddr() const { - string ret = AbstractSPRequest::getRemoteAddr(); - if (!ret.empty()) - return ret; - const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); - return s ? s : ""; - } - void log(SPLogLevel level, const string& msg) const { - AbstractSPRequest::log(level,msg); - if (level >= SPError) - cerr << "shib: " << msg; - } - - string getHeader(const char* name) const { - string hdr("HTTP_"); - for (; *name; ++name) { - if (*name=='-') - hdr += '_'; - else - hdr += toupper(*name); - } - char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); - return s ? s : ""; - } - - void setResponseHeader(const char* name, const char* value) { - // Set for later. - if (value) - m_headers.insert(make_pair(name,value)); - else - m_headers.erase(name); - } - - const char* getQueryString() const { - return FCGX_GetParam("QUERY_STRING", m_req->envp); - } - - const char* getRequestBody() const { - return m_body; - } - - long sendResponse(istream& in, long status) { - string hdr = string("Connection: close\r\n"); - for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - - const char* codestr="Status: 200 OK"; - switch (status) { - case XMLTOOLING_HTTP_STATUS_ERROR: codestr="Status: 500 Server Error"; break; - case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; - case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; - case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; - } - cout << codestr << "\r\n" << hdr << "\r\n"; - char buf[1024]; - while (in) { - in.read(buf,1024); - cout.write(buf, in.gcount()); - } - return SHIB_RETURN_DONE; - } - - long sendRedirect(const char* url) { - string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 40\r\n" - "Expires: 01-Jan-1997 12:00:00 GMT\r\n" - "Cache-Control: private,no-store,no-cache\r\n"; - for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - hdr += "\r\n"; - - cout << hdr << "Redirecting..."; - return SHIB_RETURN_DONE; - } - - long returnDecline() { - return SHIB_RETURN_KO; - } - long returnOK() { - return SHIB_RETURN_OK; - } - - const vector& getClientCertificates() const { - static vector g_NoCerts; - return g_NoCerts; - } - - // Not used in the extension. - - virtual void clearHeader(const char* rawname, const char* cginame) { - throw runtime_error("clearHeader not implemented by FastCGI responder."); - } - - virtual void setHeader(const char* name, const char* value) { - throw runtime_error("setHeader not implemented by FastCGI responder."); - } - - virtual void setRemoteUser(const char* user) { - throw runtime_error("setRemoteUser not implemented by FastCGI responder."); - } -}; - -// Maximum number of bytes allowed to be read from stdin -static const unsigned long STDIN_MAX = 1000000; - -static long gstdin(FCGX_Request* request, char** content) -{ - char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp); - unsigned long clen = STDIN_MAX; - - if (clenstr) { - clen = strtol(clenstr, &clenstr, 10); - if (*clenstr) { - cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl; - clen = STDIN_MAX; - } - - // *always* put a cap on the amount of data that will be read - if (clen > STDIN_MAX) - clen = STDIN_MAX; - - *content = new char[clen]; - - cin.read(*content, clen); - clen = cin.gcount(); - } - else { - // *never* read stdin when CONTENT_LENGTH is missing or unparsable - *content = 0; - clen = 0; - } - - // Chew up any remaining stdin - this shouldn't be necessary - // but is because mod_fastcgi doesn't handle it correctly. - - // ignore() doesn't set the eof bit in some versions of glibc++ - // so use gcount() instead of eof()... - do cin.ignore(1024); while (cin.gcount() == 1024); - - return clen; -} - -static void print_ok() { - cout << "Status: 200 OK" << "\r\n\r\n"; -} - -static void print_error(const char* msg) { - cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; -} - -int main(void) -{ - SPConfig* g_Config=&SPConfig::getConfig(); - g_Config->setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::RequestMapping | - SPConfig::InProcess | - SPConfig::Logging | - SPConfig::Handlers - ); - if (!g_Config->init()) { - cerr << "failed to initialize Shibboleth libraries" << endl; - exit(1); - } - - try { - if (!g_Config->instantiate(NULL, true)) - throw runtime_error("unknown error"); - } - catch (exception& ex) { - g_Config->term(); - cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; - exit(1); - } - - string g_ServerScheme; - string g_ServerName; - int g_ServerPort=0; - - // Load "authoritative" URL fields. - char* var = getenv("SHIBSP_SERVER_NAME"); - if (var) - g_ServerName = var; - var = getenv("SHIBSP_SERVER_SCHEME"); - if (var) - g_ServerScheme = var; - var = getenv("SHIBSP_SERVER_PORT"); - if (var) - g_ServerPort = atoi(var); - - streambuf* cin_streambuf = cin.rdbuf(); - streambuf* cout_streambuf = cout.rdbuf(); - streambuf* cerr_streambuf = cerr.rdbuf(); - - FCGX_Request request; - - FCGX_Init(); - FCGX_InitRequest(&request, 0, 0); - - cout << "Shibboleth initialization complete. Starting request loop." << endl; - while (FCGX_Accept_r(&request) == 0) { - // Note that the default bufsize (0) will cause the use of iostream - // methods that require positioning (such as peek(), seek(), - // unget() and putback()) to fail (in favour of more efficient IO). - fcgi_streambuf cin_fcgi_streambuf(request.in); - fcgi_streambuf cout_fcgi_streambuf(request.out); - fcgi_streambuf cerr_fcgi_streambuf(request.err); - - cin.rdbuf(&cin_fcgi_streambuf); - cout.rdbuf(&cout_fcgi_streambuf); - cerr.rdbuf(&cerr_fcgi_streambuf); - - // Although FastCGI supports writing before reading, - // many http clients (browsers) don't support it (so - // the connection deadlocks until a timeout expires!). - char* content; - gstdin(&request, &content); - - try { - xmltooling::NDC ndc("FastCGI shibresponder"); - ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); - - pair res = stf.getServiceProvider().doHandler(stf); - if (res.first) { - stf.log(SPRequest::SPDebug, "shib: doHandler handled the request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(); - break; - - case SHIB_RETURN_KO: - cerr << "shib: doHandler failed to handle the request" << endl; - print_error("FastCGI Shibboleth responder should only be used for Shibboleth protocol requests."); - break; - - case SHIB_RETURN_DONE: - // response already handled - break; - - default: - cerr << "shib: doHandler returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth responder returned an unexpected result."); - break; - } - } - else { - cerr << "shib: doHandler failed to handle request." << endl; - print_error("FastCGI Shibboleth responder failed to process request."); - } - - } - catch (exception& e) { - cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl; - print_error("FastCGI Shibboleth responder caught an exception, check log for details."); - } - - delete[] content; - - // If the output streambufs had non-zero bufsizes and - // were constructed outside of the accept loop (i.e. - // their destructor won't be called here), they would - // have to be flushed here. - } - - cout << "Request loop ended." << endl; - - cin.rdbuf(cin_streambuf); - cout.rdbuf(cout_streambuf); - cerr.rdbuf(cerr_streambuf); - - if (g_Config) - g_Config->term(); - - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler + + Andre Cruz +*/ + +#define SHIBSP_LITE +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _SCL_SECURE_NO_WARNINGS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_UNISTD_H +# include +# include +#endif +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); +static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); + +typedef enum { + SHIB_RETURN_OK, + SHIB_RETURN_KO, + SHIB_RETURN_DONE +} shib_return_t; + +class ShibTargetFCGI : public AbstractSPRequest +{ + FCGX_Request* m_req; + const char* m_body; + multimap m_headers; + int m_port; + string m_scheme,m_hostname; + +public: + ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0) + : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) { + + const char* server_name_str = hostname; + if (!server_name_str || !*server_name_str) + server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); + m_hostname = server_name_str; + + m_port = port; + if (!m_port) { + char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); + m_port = strtol(server_port_str, &server_port_str, 10); + if (*server_port_str) { + cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; + throw runtime_error("Unable to determine server port."); + } + } + + const char* server_scheme_str = scheme; + if (!server_scheme_str || !*server_scheme_str) + server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; + m_scheme = server_scheme_str; + + setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); + } + + ~ShibTargetFCGI() { } + + const char* getScheme() const { + return m_scheme.c_str(); + } + const char* getHostname() const { + return m_hostname.c_str(); + } + int getPort() const { + return m_port; + } + const char* getMethod() const { + return FCGX_GetParam("REQUEST_METHOD", m_req->envp); + } + string getContentType() const { + const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); + return s ? s : ""; + } + long getContentLength() const { + const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); + return s ? atol(s) : 0; + } + string getRemoteUser() const { + const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp); + return s ? s : ""; + } + string getRemoteAddr() const { + string ret = AbstractSPRequest::getRemoteAddr(); + if (!ret.empty()) + return ret; + const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); + return s ? s : ""; + } + void log(SPLogLevel level, const string& msg) const { + AbstractSPRequest::log(level,msg); + if (level >= SPError) + cerr << "shib: " << msg; + } + + string getHeader(const char* name) const { + string hdr("HTTP_"); + for (; *name; ++name) { + if (*name=='-') + hdr += '_'; + else + hdr += toupper(*name); + } + char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); + return s ? s : ""; + } + + void setResponseHeader(const char* name, const char* value) { + 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::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::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + hdr += "\r\n"; + + cout << hdr << "Redirecting..."; + return SHIB_RETURN_DONE; + } + + long returnDecline() { + return SHIB_RETURN_KO; + } + long returnOK() { + return SHIB_RETURN_OK; + } + + const vector& getClientCertificates() const { + static vector g_NoCerts; + return g_NoCerts; + } + + // Not used in the extension. + + virtual void clearHeader(const char* rawname, const char* cginame) { + throw runtime_error("clearHeader not implemented by FastCGI responder."); + } + + virtual void setHeader(const char* name, const char* value) { + throw runtime_error("setHeader not implemented by FastCGI responder."); + } + + virtual void setRemoteUser(const char* user) { + throw runtime_error("setRemoteUser not implemented by FastCGI responder."); + } +}; + +// Maximum number of bytes allowed to be read from stdin +static const unsigned long STDIN_MAX = 1000000; + +static long gstdin(FCGX_Request* request, char** content) +{ + char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp); + unsigned long clen = STDIN_MAX; + + if (clenstr) { + clen = strtol(clenstr, &clenstr, 10); + if (*clenstr) { + cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl; + clen = STDIN_MAX; + } + + // *always* put a cap on the amount of data that will be read + if (clen > STDIN_MAX) + clen = STDIN_MAX; + + *content = new char[clen]; + + cin.read(*content, clen); + clen = cin.gcount(); + } + else { + // *never* read stdin when CONTENT_LENGTH is missing or unparsable + *content = 0; + clen = 0; + } + + // Chew up any remaining stdin - this shouldn't be necessary + // but is because mod_fastcgi doesn't handle it correctly. + + // ignore() doesn't set the eof bit in some versions of glibc++ + // so use gcount() instead of eof()... + do cin.ignore(1024); while (cin.gcount() == 1024); + + return clen; +} + +static void print_ok() { + cout << "Status: 200 OK" << "\r\n\r\n"; +} + +static void print_error(const char* msg) { + cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; +} + +int main(void) +{ + SPConfig* g_Config=&SPConfig::getConfig(); + g_Config->setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::RequestMapping | + SPConfig::InProcess | + SPConfig::Logging | + SPConfig::Handlers + ); + if (!g_Config->init()) { + cerr << "failed to initialize Shibboleth libraries" << endl; + exit(1); + } + + try { + if (!g_Config->instantiate(NULL, true)) + throw runtime_error("unknown error"); + } + catch (exception& ex) { + g_Config->term(); + cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; + exit(1); + } + + string g_ServerScheme; + string g_ServerName; + int g_ServerPort=0; + + // Load "authoritative" URL fields. + char* var = getenv("SHIBSP_SERVER_NAME"); + if (var) + g_ServerName = var; + var = getenv("SHIBSP_SERVER_SCHEME"); + if (var) + g_ServerScheme = var; + var = getenv("SHIBSP_SERVER_PORT"); + if (var) + g_ServerPort = atoi(var); + + streambuf* cin_streambuf = cin.rdbuf(); + streambuf* cout_streambuf = cout.rdbuf(); + streambuf* cerr_streambuf = cerr.rdbuf(); + + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + cout << "Shibboleth initialization complete. Starting request loop." << endl; + while (FCGX_Accept_r(&request) == 0) { + // Note that the default bufsize (0) will cause the use of iostream + // methods that require positioning (such as peek(), seek(), + // unget() and putback()) to fail (in favour of more efficient IO). + fcgi_streambuf cin_fcgi_streambuf(request.in); + fcgi_streambuf cout_fcgi_streambuf(request.out); + fcgi_streambuf cerr_fcgi_streambuf(request.err); + + cin.rdbuf(&cin_fcgi_streambuf); + cout.rdbuf(&cout_fcgi_streambuf); + cerr.rdbuf(&cerr_fcgi_streambuf); + + // Although FastCGI supports writing before reading, + // many http clients (browsers) don't support it (so + // the connection deadlocks until a timeout expires!). + char* content; + gstdin(&request, &content); + + try { + xmltooling::NDC ndc("FastCGI shibresponder"); + ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); + + pair res = stf.getServiceProvider().doHandler(stf); + if (res.first) { + stf.log(SPRequest::SPDebug, "shib: doHandler handled the request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(); + break; + + case SHIB_RETURN_KO: + cerr << "shib: doHandler failed to handle the request" << endl; + print_error("FastCGI Shibboleth responder should only be used for Shibboleth protocol requests."); + break; + + case SHIB_RETURN_DONE: + // response already handled + break; + + default: + cerr << "shib: doHandler returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth responder returned an unexpected result."); + break; + } + } + else { + cerr << "shib: doHandler failed to handle request." << endl; + print_error("FastCGI Shibboleth responder failed to process request."); + } + + } + catch (exception& e) { + cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl; + print_error("FastCGI Shibboleth responder caught an exception, check log for details."); + } + + delete[] content; + + // If the output streambufs had non-zero bufsizes and + // were constructed outside of the accept loop (i.e. + // their destructor won't be called here), they would + // have to be flushed here. + } + + cout << "Request loop ended." << endl; + + cin.rdbuf(cin_streambuf); + cout.rdbuf(cout_streambuf); + cerr.rdbuf(cerr_streambuf); + + if (g_Config) + g_Config->term(); + + return 0; +} diff --git a/fastcgi/shibresponder.rc b/fastcgi/shibresponder.rc index 4bccb0f..f95c347 100644 --- a/fastcgi/shibresponder.rc +++ b/fastcgi/shibresponder.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // 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 @@ -47,14 +47,14 @@ BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "Internet2\0" VALUE "FileDescription", "Shibboleth FastCGI Responder\0" - VALUE "FileVersion", "2, 2, 1, 0\0" + VALUE "FileVersion", "2, 3, 0, 0\0" VALUE "InternalName", "shibresponder\0" VALUE "LegalCopyright", "Copyright © 2009 Internet2\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "shibresponder.exe\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 diff --git a/isapi_shib/isapi_shib.cpp b/isapi_shib/isapi_shib.cpp index 148a079..73fdcce 100644 --- a/isapi_shib/isapi_shib.cpp +++ b/isapi_shib/isapi_shib.cpp @@ -27,9 +27,16 @@ #define _CRT_SECURE_NO_DEPRECATE 1 #define _CRT_RAND_S +#include #include #include #include + +#include +#include +#include +#include +#include #include #include #include @@ -38,12 +45,6 @@ #include #include -#include -#include -#include -#include -#include - #include #include #include @@ -202,32 +203,6 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer) flag=props->getBool("catchAll"); g_catchAll = flag.first && flag.second; -<<<<<<< .mine - pair 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 unsetValue=props->getString("unsetHeaderValue"); if (unsetValue.first) g_unsetHeaderValue = unsetValue.second; @@ -256,7 +231,6 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer) } } ->>>>>>> .r3097 props = props->getPropertySet("ISAPI"); if (props) { flag = props->getBool("normalizeRequest"); @@ -560,6 +534,7 @@ public: 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)); @@ -588,7 +563,7 @@ public: 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" @@ -869,6 +844,7 @@ public: 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)); @@ -930,6 +906,7 @@ public: 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" diff --git a/isapi_shib/isapi_shib.cpp.mine b/isapi_shib/isapi_shib.cpp.mine deleted file mode 100644 index 9d2278e..0000000 --- a/isapi_shib/isapi_shib.cpp.mine +++ /dev/null @@ -1,993 +0,0 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -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 m_aliases; - }; - - HINSTANCE g_hinstDLL; - SPConfig* g_Config = NULL; - map g_Sites; - bool g_bNormalizeRequest = true; - string g_unsetHeaderValue,g_spoofKey; - bool g_checkSpoofing = true; - bool g_catchAll = false; - bool g_bSafeHeaderNames = false; - vector 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 flag=props->getBool("checkSpoofing"); - g_checkSpoofing = !flag.first || flag.second; - flag=props->getBool("catchAll"); - g_catchAll = flag.first && flag.second; - - pair 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; - } - } - } - - 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(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 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(hdr.c_str()), const_cast(g_unsetHeaderValue.c_str())); - } - else if (!strcmp(rawname,"REMOTE_USER")) { - m_pn->SetHeader(m_pfc, "remote-user:", const_cast(g_unsetHeaderValue.c_str())); - m_pn->SetHeader(m_pfc, "remote_user:", const_cast(g_unsetHeaderValue.c_str())); - } - else { - string hdr = string(rawname) + ':'; - m_pn->SetHeader(m_pfc, const_cast(hdr.c_str()), const_cast(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(hdr.c_str()), const_cast(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(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(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(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::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::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="Redirecting..."; - 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& 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="Shibboleth Filter Error" - "

Shibboleth Filter Error

"; - 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=""; - 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(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::const_iterator map_i=g_Sites.find(static_cast(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 res = stf.getServiceProvider().doAuthentication(stf); - if (!g_spoofKey.empty()) - pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast(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="Shibboleth Error

Shibboleth Error

"; - 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=""; - 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 m_headers; - mutable vector 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(port)[10]=0; - } - else { - strncpy(port,site.m_port.c_str(),10); - static_cast(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(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(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(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::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::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="Redirecting..."; - 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& 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(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen); - m_certs.push_back(reinterpret_cast(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::const_iterator map_i=g_Sites.find(static_cast(buf)); - if (map_i==g_Sites.end()) - return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check mappings in configuration)."); - - ShibTargetIsapiE ste(lpECB, map_i->second); - pair 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; -} diff --git a/isapi_shib/isapi_shib.cpp.r3059 b/isapi_shib/isapi_shib.cpp.r3059 deleted file mode 100644 index 73fb7a0..0000000 --- a/isapi_shib/isapi_shib.cpp.r3059 +++ /dev/null @@ -1,950 +0,0 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -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 m_aliases; - }; - - struct context_t { - char* m_user; - bool m_checked; - }; - - HINSTANCE g_hinstDLL; - SPConfig* g_Config = NULL; - map g_Sites; - bool g_bNormalizeRequest = true; - string g_unsetHeaderValue; - bool g_checkSpoofing = true; - bool g_catchAll = false; - vector 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 unsetValue=props->getString("unsetHeaderValue"); - if (unsetValue.first) - g_unsetHeaderValue = unsetValue.second; - pair 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(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 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(pfc->pFilterContext)) { - static_cast(pfc->pFilterContext)->m_user = NULL; - static_cast(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(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(hdr.c_str()), const_cast(g_unsetHeaderValue.c_str())); - } - void setHeader(const char* name, const char* value) { - string hdr(name); - hdr += ':'; - m_pn->SetHeader(m_pfc, const_cast(hdr.c_str()), const_cast(value)); - } - string getHeader(const char* name) const { - string hdr(name); - hdr += ':'; - dynabuf buf(256); - GetHeader(m_pn, m_pfc, const_cast(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(m_pfc->pFilterContext)->m_user = NULL; - else if (static_cast(m_pfc->pFilterContext)->m_user = (char*)m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL)) - strcpy(static_cast(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::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::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="Redirecting..."; - 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& 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="Shibboleth Filter Error" - "

Shibboleth Filter Error

"; - 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=""; - 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(pfc->pFilterContext)->m_user) - ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=static_cast(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::const_iterator map_i=g_Sites.find(static_cast(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 res = stf.getServiceProvider().doAuthentication(stf); - if (pfc->pFilterContext) - static_cast(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="Shibboleth Error

Shibboleth Error

"; - 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=""; - 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 m_headers; - mutable vector 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(port)[10]=0; - } - else { - strncpy(port,site.m_port.c_str(),10); - static_cast(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(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(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(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::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::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="Redirecting..."; - 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& 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(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen); - m_certs.push_back(reinterpret_cast(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::const_iterator map_i=g_Sites.find(static_cast(buf)); - if (map_i==g_Sites.end()) - return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check mappings in configuration)."); - - ShibTargetIsapiE ste(lpECB, map_i->second); - pair 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; -} diff --git a/isapi_shib/isapi_shib.cpp.r3097 b/isapi_shib/isapi_shib.cpp.r3097 deleted file mode 100644 index 2a1130d..0000000 --- a/isapi_shib/isapi_shib.cpp.r3097 +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -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 m_aliases; - }; - - HINSTANCE g_hinstDLL; - SPConfig* g_Config = NULL; - map g_Sites; - bool g_bNormalizeRequest = true; - string g_unsetHeaderValue,g_spoofKey; - bool g_checkSpoofing = true; - bool g_catchAll = false; - bool g_bSafeHeaderNames = false; - vector 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 flag=props->getBool("checkSpoofing"); - g_checkSpoofing = !flag.first || flag.second; - flag=props->getBool("catchAll"); - g_catchAll = flag.first && flag.second; - - pair 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(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 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(hdr.c_str()), const_cast(g_unsetHeaderValue.c_str())); - } - else if (!strcmp(rawname,"REMOTE_USER")) { - m_pn->SetHeader(m_pfc, "remote-user:", const_cast(g_unsetHeaderValue.c_str())); - m_pn->SetHeader(m_pfc, "remote_user:", const_cast(g_unsetHeaderValue.c_str())); - } - else { - string hdr = string(rawname) + ':'; - m_pn->SetHeader(m_pfc, const_cast(hdr.c_str()), const_cast(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(hdr.c_str()), const_cast(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(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(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(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::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::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="Redirecting..."; - 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& 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="Shibboleth Filter Error" - "

Shibboleth Filter Error

"; - 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=""; - 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(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::const_iterator map_i=g_Sites.find(static_cast(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 res = stf.getServiceProvider().doAuthentication(stf); - if (!g_spoofKey.empty()) - pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast(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="Shibboleth Error

Shibboleth Error

"; - 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=""; - 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 m_headers; - mutable vector 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(port)[10]=0; - } - else { - strncpy(port,site.m_port.c_str(),10); - static_cast(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(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(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(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::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::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="Redirecting..."; - 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& 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(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen); - m_certs.push_back(reinterpret_cast(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::const_iterator map_i=g_Sites.find(static_cast(buf)); - if (map_i==g_Sites.end()) - return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check mappings in configuration)."); - - ShibTargetIsapiE ste(lpECB, map_i->second); - pair 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; -} diff --git a/isapi_shib/isapi_shib.rc b/isapi_shib/isapi_shib.rc index 4a6f709..116438f 100644 --- a/isapi_shib/isapi_shib.rc +++ b/isapi_shib/isapi_shib.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // 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 @@ -47,14 +47,14 @@ BEGIN 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 diff --git a/ltmain.sh b/ltmain.sh index 23f82e3..0223495 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -1,7 +1,7 @@ # 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 , 1996 # @@ -17,7 +17,7 @@ # # 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 @@ -33,9 +33,6 @@ basename="s,^.*/,,g" # 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" @@ -46,9 +43,20 @@ EXIT_FAILURE=1 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 @@ -86,14 +94,15 @@ rm="rm -f" 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 @@ -102,16 +111,19 @@ 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 @@ -128,20 +140,62 @@ run= 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 @@ -152,12 +206,11 @@ func_win32_libid () { 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*) @@ -181,7 +234,8 @@ func_win32_libid () { # 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 @@ -238,12 +292,126 @@ func_infer_tag () { 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 @@ -308,10 +476,10 @@ 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) @@ -320,7 +488,7 @@ do 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) @@ -345,7 +513,7 @@ do else $echo "disable static libraries" fi - exit $EXIT_SUCCESS + exit $? ;; --finish) mode="finish" ;; @@ -360,7 +528,11 @@ do 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 @@ -392,6 +564,18 @@ if test -n "$prevopt"; then 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. @@ -402,7 +586,7 @@ if test -z "$show_help"; then # 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 @@ -468,7 +652,7 @@ if test -z "$show_help"; then for arg do - case "$arg_mode" in + case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" @@ -550,7 +734,10 @@ if test -z "$show_help"; then 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\"" ;; @@ -591,6 +778,7 @@ if test -z "$show_help"; then *.f90) xform=f90 ;; *.for) xform=for ;; *.java) xform=java ;; + *.obj) xform=obj ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` @@ -624,6 +812,14 @@ if test -z "$show_help"; then 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 @@ -696,12 +892,17 @@ compiler." $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" @@ -723,18 +924,18 @@ EOF 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 @@ -806,9 +1007,9 @@ EOF 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" @@ -937,6 +1138,7 @@ EOF 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 @@ -957,22 +1159,32 @@ EOF 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 @@ -1147,6 +1359,11 @@ EOF 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. @@ -1230,6 +1447,13 @@ EOF 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= @@ -1288,6 +1512,18 @@ EOF 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 @@ -1314,7 +1550,8 @@ EOF 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" ;; @@ -1328,10 +1565,15 @@ EOF 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 @@ -1340,15 +1582,15 @@ EOF -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 ;; @@ -1356,10 +1598,19 @@ EOF # 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 ;; @@ -1369,8 +1620,20 @@ EOF 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 ;; @@ -1379,13 +1642,19 @@ EOF 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"` @@ -1396,9 +1665,7 @@ EOF 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 ;; @@ -1475,7 +1742,7 @@ EOF 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 @@ -1636,6 +1903,11 @@ EOF 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. @@ -1741,9 +2013,9 @@ EOF 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 @@ -1806,7 +2078,6 @@ EOF 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" @@ -1858,7 +2129,7 @@ EOF compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else - deplibs="$deplib $deplibs" + compiler_flags="$compiler_flags $deplib" fi continue ;; @@ -1867,10 +2138,6 @@ EOF $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 @@ -1981,7 +2248,22 @@ EOF 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" @@ -2031,7 +2313,7 @@ EOF 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 @@ -2055,6 +2337,8 @@ EOF # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no + avoidtemprpath= + # Read the .la file case $lib in @@ -2153,11 +2437,19 @@ EOF 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//'` @@ -2228,14 +2520,16 @@ EOF 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 @@ -2272,8 +2566,12 @@ EOF 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 @@ -2386,11 +2684,15 @@ EOF 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 @@ -2421,7 +2723,7 @@ EOF 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" ;; @@ -2494,7 +2796,7 @@ EOF 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" ;; @@ -2555,8 +2857,6 @@ EOF fi fi else - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi @@ -2674,12 +2974,12 @@ EOF *) 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 @@ -2918,7 +3218,7 @@ EOF # 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" @@ -2944,27 +3244,27 @@ EOF # 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 ;; @@ -2990,7 +3290,7 @@ EOF 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) @@ -3142,11 +3442,11 @@ EOF 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. @@ -3196,9 +3496,14 @@ EOF *-*-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. @@ -3242,13 +3547,12 @@ EOF 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 "*) @@ -3283,13 +3587,11 @@ EOF # 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 @@ -3321,7 +3623,7 @@ EOF 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 @@ -3335,7 +3637,7 @@ EOF 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 @@ -3404,7 +3706,7 @@ EOF 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 @@ -3534,6 +3836,35 @@ EOF 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= @@ -3617,6 +3948,7 @@ EOF fi lib="$output_objdir/$realname" + linknames= for link do linknames="$linknames $link" @@ -3645,6 +3977,9 @@ EOF # 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" @@ -3678,67 +4013,13 @@ EOF 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" @@ -3768,7 +4049,8 @@ EOF 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 @@ -3787,6 +4069,7 @@ EOF 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. @@ -3796,13 +4079,13 @@ EOF 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 @@ -3816,9 +4099,9 @@ EOF # 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 @@ -3838,13 +4121,13 @@ EOF 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" @@ -3892,13 +4175,30 @@ EOF 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 @@ -3968,72 +4268,20 @@ EOF 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 @@ -4134,6 +4382,35 @@ EOF ;; 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" @@ -4178,10 +4455,15 @@ EOF 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 @@ -4295,13 +4577,25 @@ extern \"C\" { # 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 @@ -4352,7 +4646,26 @@ extern \"C\" { #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; } @@ -4399,16 +4712,29 @@ static const void *lt_preloaded_setup() { 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 @@ -4421,19 +4747,19 @@ static const void *lt_preloaded_setup() { # 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 @@ -4441,7 +4767,7 @@ static const void *lt_preloaded_setup() { $run $rm "$output_objdir/${outputname}S.${objext}" fi - exit $status + exit $exit_status fi if test -n "$shlibpath_var"; then @@ -4514,7 +4840,7 @@ static const void *lt_preloaded_setup() { 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= @@ -4551,7 +4877,7 @@ static const void *lt_preloaded_setup() { 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. @@ -4581,10 +4907,12 @@ static const void *lt_preloaded_setup() { 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 < #include #include +#include +#include +#include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX @@ -4619,15 +4950,19 @@ EOF #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 @@ -4637,17 +4972,32 @@ EOF (((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, ...); @@ -4657,29 +5007,51 @@ main (int argc, char *argv[]) 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 <> $cwrappersource <> $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> $cwrappersource <> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + cat >> $cwrappersource <<"EOF" + return 127; } void * @@ -4699,48 +5071,148 @@ xstrdup (const char *string) ; } -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 * @@ -4784,16 +5256,16 @@ lt_fatal (const char *message, ...) 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 @@ -4812,9 +5284,21 @@ EOF 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\" @@ -4943,23 +5427,23 @@ else # 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 @@ -4991,71 +5475,73 @@ fi\ 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" : ".*"` && @@ -5069,20 +5555,7 @@ fi\ 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 @@ -5093,7 +5566,7 @@ fi\ 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 @@ -5151,7 +5624,7 @@ fi\ 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 @@ -5290,11 +5763,11 @@ relink_command=\"$relink_command\"" # 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 @@ -5303,14 +5776,14 @@ relink_command=\"$relink_command\"" 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 @@ -5328,28 +5801,31 @@ relink_command=\"$relink_command\"" 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 ;; @@ -5358,7 +5834,7 @@ relink_command=\"$relink_command\"" # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5493,9 +5969,9 @@ relink_command=\"$relink_command\"" 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 @@ -5527,11 +6003,14 @@ relink_command=\"$relink_command\"" 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 @@ -5544,7 +6023,16 @@ relink_command=\"$relink_command\"" 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 @@ -5638,17 +6126,15 @@ relink_command=\"$relink_command\"" 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. @@ -5676,38 +6162,25 @@ relink_command=\"$relink_command\"" 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 : @@ -5727,7 +6200,7 @@ relink_command=\"$relink_command\"" 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 @@ -5827,7 +6300,7 @@ relink_command=\"$relink_command\"" # 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" @@ -5860,7 +6333,7 @@ relink_command=\"$relink_command\"" $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 ;; @@ -5983,12 +6456,15 @@ relink_command=\"$relink_command\"" 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" @@ -6077,9 +6553,17 @@ relink_command=\"$relink_command\"" 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 @@ -6112,7 +6596,8 @@ relink_command=\"$relink_command\"" IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. - fi + ;; + esac fi ;; @@ -6336,9 +6821,9 @@ The following components of LINK-COMMAND are treated specially: -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 @@ -6352,9 +6837,11 @@ The following components of LINK-COMMAND are treated specially: -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. @@ -6397,7 +6884,7 @@ esac $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 @@ -6411,12 +6898,11 @@ exit $EXIT_SUCCESS # 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: diff --git a/memcache-store/Makefile.am b/memcache-store/Makefile.am index 9d46119..fa11fd8 100644 --- a/memcache-store/Makefile.am +++ b/memcache-store/Makefile.am @@ -1,20 +1,20 @@ -AUTOMAKE_OPTIONS = foreign - -plugindir = $(libdir)/@PACKAGE@ -plugin_LTLIBRARIES = memcache-store.la - -AM_CFLAGS = $(MEMCACHED_CFLAGS) -AM_CXXFLAGS = $(MEMCACHED_CFLAGS) - -memcache_store_la_LIBADD = \ - $(MEMCACHED_LIBS) - -memcache_store_la_SOURCES = \ - memcache-store.cpp - -memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) - -install-exec-hook: - for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done - -EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h +AUTOMAKE_OPTIONS = foreign + +plugindir = $(libdir)/@PACKAGE@ +plugin_LTLIBRARIES = memcache-store.la + +AM_CFLAGS = $(MEMCACHED_CFLAGS) +AM_CXXFLAGS = $(MEMCACHED_CFLAGS) + +memcache_store_la_LIBADD = \ + $(MEMCACHED_LIBS) + +memcache_store_la_SOURCES = \ + memcache-store.cpp + +memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) + +install-exec-hook: + for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done + +EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h diff --git a/memcache-store/Makefile.in b/memcache-store/Makefile.in index 105883a..1c5d4a4 100644 --- a/memcache-store/Makefile.in +++ b/memcache-store/Makefile.in @@ -82,6 +82,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/memcache-store/memcache-store.cpp b/memcache-store/memcache-store.cpp index c208108..49d238d 100644 --- a/memcache-store/memcache-store.cpp +++ b/memcache-store/memcache-store.cpp @@ -1,770 +1,808 @@ -/* - * Copyright 2001-2008 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * memcache-store.cpp - * - * Storage Service using memcache (pre memcache tags) - */ - -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -# define MCEXT_EXPORTS __declspec(dllexport) -#else -# define MCEXT_EXPORTS -#endif - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -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); - - class mc_record { - public: - string value; - time_t expiration; - mc_record(){}; - mc_record(string _v, time_t _e) : - value(_v), expiration(_e) - {} - }; - - class MemcacheBase { - public: - MemcacheBase(const DOMElement* e); - ~MemcacheBase(); - - bool addMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool setMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool replaceMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool getMemcache(const char *key, - string &dest, - uint32_t *flags, - bool use_prefix = true); - bool deleteMemcache(const char *key, - time_t timeout, - bool use_prefix = true); - - void serialize(mc_record &source, string &dest); - void serialize(list &source, string &dest); - void deserialize(string &source, mc_record &dest); - void deserialize(string &source, list &dest); - - bool addSessionToUser(string &key, string &user); - bool addLock(string what, bool use_prefix = true); - void deleteLock(string what, bool use_prefix = true); - - protected: - const DOMElement* m_root; // can only use this during initialization - Category& log; - memcached_st *memc; - string m_memcacheHosts; - string m_prefix; - Mutex* m_lock; - }; - - class MemcacheStorageService : public StorageService, public MemcacheBase { - - public: - MemcacheStorageService(const DOMElement* e); - ~MemcacheStorageService(); - - bool createString(const char* context, const char* key, const char* value, time_t expiration); - int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0); - int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0); - bool deleteString(const char* context, const char* key); - - bool createText(const char* context, const char* key, const char* value, time_t expiration) { - return createString(context, key, value, expiration); - } - int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) { - return readString(context, key, pvalue, pexpiration, version); - } - int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) { - return updateString(context, key, value, expiration, version); - } - bool deleteText(const char* context, const char* key) { - return deleteString(context, key); - } - - void reap(const char* context) {} - - void updateContext(const char* context, time_t expiration); - void deleteContext(const char* context); - - private: - - Category& m_log; - bool m_buildMap; - - - }; - - StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) { - return new MemcacheStorageService(e); - } - -}; - -bool MemcacheBase::addLock(string what, bool use_prefix) { - string lock_name = what + ":LOCK"; - string set_val = "1"; - unsigned tries = 5; - while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) { - if (tries-- == 0) { - log.debug("Unable to get lock %s... FAILED.", lock_name.c_str()); - return false; - } - log.debug("Unable to get lock %s... Retrying.", lock_name.c_str()); - - // sleep 100ms -#ifdef WIN32 - Sleep(100); -#else - struct timeval tv = { 0, 100000 }; - select(0, 0, 0, 0, &tv); -#endif - } - return true; -} - -void MemcacheBase::deleteLock(string what, bool use_prefix) { - - string lock_name = what + ":LOCK"; - deleteMemcache(lock_name.c_str(), 0, use_prefix); - return; - -} - -void MemcacheBase::deserialize(string &source, mc_record &dest) { - istringstream is(source, stringstream::in | stringstream::out); - is >> dest.expiration; - is.ignore(1); // ignore delimiter - dest.value = is.str().c_str() + is.tellg(); -} - -void MemcacheBase::deserialize(string &source, list &dest) { - istringstream is(source, stringstream::in | stringstream::out); - while (!is.eof()) { - string s; - is >> s; - dest.push_back(s); - } -} - -void MemcacheBase::serialize(mc_record &source, string &dest) { - ostringstream os(stringstream::in | stringstream::out); - os << source.expiration; - os << "-"; // delimiter - os << source.value; - dest = os.str(); -} - -void MemcacheBase::serialize(list &source, string &dest) { - ostringstream os(stringstream::in | stringstream::out); - for(list::iterator iter = source.begin(); iter != source.end(); iter++) { - if (iter != source.begin()) { - os << endl; - } - os << *iter; - } - dest = os.str(); -} - -bool MemcacheBase::addSessionToUser(string &key, string &user) { - - if (! addLock(user, false)) { - return false; - } - - // Aquired lock - - string sessid = m_prefix + key; // add specific prefix to session - string delimiter = ";"; - string user_key = "UDATA:"; - user_key += user; - string user_val; - uint32_t flags; - bool result = getMemcache(user_key.c_str(), user_val, &flags, false); - - if (result) { - bool already_there = false; - // skip delimiters at beginning. - string::size_type lastPos = user_val.find_first_not_of(delimiter, 0); - - // find first "non-delimiter". - string::size_type pos = user_val.find_first_of(delimiter, lastPos); - - while (string::npos != pos || string::npos != lastPos) { - // found a token, add it to the vector. - string session = user_val.substr(lastPos, pos - lastPos); - if (strcmp(session.c_str(), sessid.c_str()) == 0) { - already_there = true; - break; - } - - // skip delimiters. Note the "not_of" - lastPos = user_val.find_first_not_of(delimiter, pos); - - // find next "non-delimiter" - pos = user_val.find_first_of(delimiter, lastPos); - } - - if (!already_there) { - user_val += delimiter + sessid; - replaceMemcache(user_key.c_str(), user_val, 0, 0, false); - } - } else { - addMemcache(user_key.c_str(), sessid, 0, 0, false); - } - - deleteLock(user, false); - return true; - -} - -bool MemcacheBase::deleteMemcache(const char *key, - time_t timeout, - bool use_prefix) { - memcached_return rv; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - success = true; - } else if (rv == MEMCACHED_NOTFOUND) { - // Key wasn't there... No biggie. - success = false; - } else if (rv == MEMCACHED_ERRNO) { - // System error - log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno))); - success = false; - } else { - log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv)); - // shouldn't be here - success = false; - } - - 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 - log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno))); - success = false; - } else { - log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv)); - success = false; - } - - 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 - log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno))); - success = false; - } else { - // shouldn't be here - log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv)); - success = false; - } - - 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 - log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno))); - success = false; - } else { - // shouldn't be here - log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv)); - success = false; - } - - 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 - log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno))); - success = false; - } else { - // shouldn't be here - log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv)); - success = false; - } - - return success; -} - -MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_memcacheHosts(""), 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(); - } - - // 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()); - m_memcacheHosts = h.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 timeout = 1000000; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout); - - int32_t poll_timeout = 1000; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout); - - int32_t fail_limit = 5; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit); - - int32_t retry_timeout = 30; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout); - - memcached_server_st *servers; - servers = memcached_servers_parse((char *)m_memcacheHosts.c_str()); - log.debug("Got %u hosts.", memcached_server_list_count(servers)); - if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) { - throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed"); - } - memcached_server_list_free(servers); - - log.debug("Memcache object initialized"); -} - -MemcacheBase::~MemcacheBase() { - memcached_free(memc); - delete m_lock; - log.debug("Base object destroyed"); -} - -MemcacheStorageService::MemcacheStorageService(const DOMElement* e) - : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) { - - const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL; - if (tag && *tag && XMLString::parseInt(tag) != 0) { - m_buildMap = true; - m_log.debug("Cache built with buildMap ON"); - } - -} - -MemcacheStorageService::~MemcacheStorageService() { - - -} - -bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) { - - log.debug("createString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - - mc_record rec(value, expiration); - string final_value; - serialize(rec, final_value); - - bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version - - if (result && m_buildMap) { - log.debug("Got result, updating map"); - - string map_name = context; - // we need to update the context map - if (! addLock(map_name)) { - log.error("Unable to get lock for context %s!", context); - deleteMemcache(final_key.c_str(), 0); - return false; - } - - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - log.debug("value = " + *iter); - } - - } else { - log.debug("New context: %s", map_name.c_str()); - - } - - contents.push_back(key); - serialize(contents, ser_arr); - setMemcache(map_name.c_str(), ser_arr, expiration, 0); - - deleteLock(map_name); - } - - return result; - -} - -int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) { - - log.debug("readString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - uint32_t rec_version; - string value; - - if (m_buildMap) { - log.debug("Checking context"); - - string map_name = context; - string ser_arr; - uint32_t flags; - bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags); - - if (!ctx_found) { - return 0; - } - } - - bool found = getMemcache(final_key.c_str(), value, &rec_version); - if (!found) { - return 0; - } - - if (version && rec_version <= (uint32_t)version) { - return version; - } - - if (pexpiration || pvalue) { - mc_record rec; - deserialize(value, rec); - - if (pexpiration) { - *pexpiration = rec.expiration; - } - - if (pvalue) { - *pvalue = rec.value; - } - } - - return rec_version; - -} - -int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) { - - log.debug("updateString ctx: %s - key: %s", context, key); - - time_t final_exp = expiration; - time_t *want_expiration = NULL; - if (! final_exp) { - want_expiration = &final_exp; - } - - int read_res = readString(context, key, NULL, want_expiration, version); - - if (!read_res) { - // not found - return read_res; - } - - if (version && version != read_res) { - // version incorrect - return -1; - } - - // Proceding with update - string final_key = string(context) + ":" + string(key); - mc_record rec(value, final_exp); - string final_value; - serialize(rec, final_value); - - replaceMemcache(final_key.c_str(), final_value, final_exp, ++version); - return version; - -} - -bool MemcacheStorageService::deleteString(const char* context, const char* key) { - - log.debug("deleteString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - - // Not updating context map, if there is one. There is no need. - - return deleteMemcache(final_key.c_str(), 0); - -} - -void MemcacheStorageService::updateContext(const char* context, time_t expiration) { - - log.debug("updateContext ctx: %s", context); - - if (!m_buildMap) { - log.error("updateContext invoked on a Storage with no context map built!"); - return; - } - - string map_name = context; - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - - // Update expiration times - string value; - int read_res = readString(context, iter->c_str(), &value, NULL, 0); - - if (!read_res) { - // not found - continue; - } - - updateString(context, iter->c_str(), value.c_str(), expiration, read_res); - } - replaceMemcache(map_name.c_str(), ser_arr, expiration, flags); - } - -} - -void MemcacheStorageService::deleteContext(const char* context) { - - log.debug("deleteContext ctx: %s", context); - - if (!m_buildMap) { - log.error("deleteContext invoked on a Storage with no context map built!"); - return; - } - - string map_name = context; - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - string final_key = map_name + *iter; - deleteMemcache(final_key.c_str(), 0); - } - - deleteMemcache(map_name.c_str(), 0); - } - -} - -extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) { - // Register this SS type - XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory); - return 0; -} - -extern "C" void MCEXT_EXPORTS xmltooling_extension_term() { - XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE"); -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * memcache-store.cpp + * + * Storage Service using memcache (pre memcache tags) + */ + +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +# define MCEXT_EXPORTS __declspec(dllexport) +#else +# define MCEXT_EXPORTS +#endif + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +namespace xmltooling { + static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s); + static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x); + static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p); + static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t); + static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t); + static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t); + static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t); + static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t); + + class mc_record { + public: + string value; + time_t expiration; + mc_record(){}; + mc_record(string _v, time_t _e) : + value(_v), expiration(_e) + {} + }; + + class MemcacheBase { + public: + MemcacheBase(const DOMElement* e); + ~MemcacheBase(); + + bool addMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool setMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool replaceMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool getMemcache(const char *key, + string &dest, + uint32_t *flags, + bool use_prefix = true); + bool deleteMemcache(const char *key, + time_t timeout, + bool use_prefix = true); + + void serialize(mc_record &source, string &dest); + void serialize(list &source, string &dest); + void deserialize(string &source, mc_record &dest); + void deserialize(string &source, list &dest); + + bool addSessionToUser(string &key, string &user); + bool addLock(string what, bool use_prefix = true); + void deleteLock(string what, bool use_prefix = true); + + protected: + const DOMElement* m_root; // can only use this during initialization + Category& log; + memcached_st *memc; + string m_prefix; + Mutex* m_lock; + }; + + class MemcacheStorageService : public StorageService, public MemcacheBase { + + public: + MemcacheStorageService(const DOMElement* e); + ~MemcacheStorageService(); + + bool createString(const char* context, const char* key, const char* value, time_t expiration); + int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0); + int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0); + bool deleteString(const char* context, const char* key); + + bool createText(const char* context, const char* key, const char* value, time_t expiration) { + return createString(context, key, value, expiration); + } + int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) { + return readString(context, key, pvalue, pexpiration, version); + } + int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) { + return updateString(context, key, value, expiration, version); + } + bool deleteText(const char* context, const char* key) { + return deleteString(context, key); + } + + void reap(const char* context) {} + + void updateContext(const char* context, time_t expiration); + void deleteContext(const char* context); + + private: + + Category& m_log; + bool m_buildMap; + + + }; + + StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) { + return new MemcacheStorageService(e); + } + +}; + +bool MemcacheBase::addLock(string what, bool use_prefix) { + string lock_name = what + ":LOCK"; + string set_val = "1"; + unsigned tries = 5; + while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) { + if (tries-- == 0) { + log.debug("Unable to get lock %s... FAILED.", lock_name.c_str()); + return false; + } + log.debug("Unable to get lock %s... Retrying.", lock_name.c_str()); + + // sleep 100ms +#ifdef WIN32 + Sleep(100); +#else + struct timeval tv = { 0, 100000 }; + select(0, 0, 0, 0, &tv); +#endif + } + return true; +} + +void MemcacheBase::deleteLock(string what, bool use_prefix) { + + string lock_name = what + ":LOCK"; + deleteMemcache(lock_name.c_str(), 0, use_prefix); + return; + +} + +void MemcacheBase::deserialize(string &source, mc_record &dest) { + istringstream is(source, stringstream::in | stringstream::out); + is >> dest.expiration; + is.ignore(1); // ignore delimiter + dest.value = is.str().c_str() + is.tellg(); +} + +void MemcacheBase::deserialize(string &source, list &dest) { + istringstream is(source, stringstream::in | stringstream::out); + while (!is.eof()) { + string s; + is >> s; + dest.push_back(s); + } +} + +void MemcacheBase::serialize(mc_record &source, string &dest) { + ostringstream os(stringstream::in | stringstream::out); + os << source.expiration; + os << "-"; // delimiter + os << source.value; + dest = os.str(); +} + +void MemcacheBase::serialize(list &source, string &dest) { + ostringstream os(stringstream::in | stringstream::out); + for(list::iterator iter = source.begin(); iter != source.end(); iter++) { + if (iter != source.begin()) { + os << endl; + } + os << *iter; + } + dest = os.str(); +} + +bool MemcacheBase::addSessionToUser(string &key, string &user) { + + if (! addLock(user, false)) { + return false; + } + + // Aquired lock + + string sessid = m_prefix + key; // add specific prefix to session + string delimiter = ";"; + string user_key = "UDATA:"; + user_key += user; + string user_val; + uint32_t flags; + bool result = getMemcache(user_key.c_str(), user_val, &flags, false); + + if (result) { + bool already_there = false; + // skip delimiters at beginning. + string::size_type lastPos = user_val.find_first_not_of(delimiter, 0); + + // find first "non-delimiter". + string::size_type pos = user_val.find_first_of(delimiter, lastPos); + + while (string::npos != pos || string::npos != lastPos) { + // found a token, add it to the vector. + string session = user_val.substr(lastPos, pos - lastPos); + if (strcmp(session.c_str(), sessid.c_str()) == 0) { + already_there = true; + break; + } + + // skip delimiters. Note the "not_of" + lastPos = user_val.find_first_not_of(delimiter, pos); + + // find next "non-delimiter" + pos = user_val.find_first_of(delimiter, lastPos); + } + + if (!already_there) { + user_val += delimiter + sessid; + replaceMemcache(user_key.c_str(), user_val, 0, 0, false); + } + } else { + addMemcache(user_key.c_str(), sessid, 0, 0, false); + } + + deleteLock(user, false); + return true; + +} + +bool MemcacheBase::deleteMemcache(const char *key, + time_t timeout, + bool use_prefix) { + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTFOUND) { + // Key wasn't there... No biggie. + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::getMemcache(const char *key, + string &dest, + uint32_t *flags, + bool use_prefix) { + memcached_return rv; + size_t len; + char *result; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + dest = result; + free(result); + success = true; + } else if (rv == MEMCACHED_NOTFOUND) { + log.debug("Key %s not found in memcache...", key); + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::addMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTSTORED) { + // already there + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::setMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::replaceMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTSTORED) { + // not there + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") { + + auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL); + if (p.get() && *p.get()) { + log.debug("INIT: GOT key prefix: %s", p.get()); + m_prefix = p.get(); + } + + m_lock = Mutex::create(); + log.debug("Lock created"); + + memc = memcached_create(NULL); + if (memc == NULL) { + throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed"); + } + + log.debug("Memcache created"); + + unsigned int hash = MEMCACHED_HASH_CRC; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash); + log.debug("CRC hash set"); + + int32_t send_timeout = 1000000; + const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; + if (tag && *tag) { + send_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout); + + int32_t recv_timeout = 1000000; + tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; + if (tag && *tag) { + recv_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout); + + int32_t poll_timeout = 1000; + tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL; + if (tag && *tag) { + poll_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout); + + int32_t fail_limit = 5; + tag = e ? e->getAttributeNS(NULL, failLimit) : NULL; + if (tag && *tag) { + fail_limit = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit); + + int32_t retry_timeout = 30; + tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL; + if (tag && *tag) { + retry_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout); + + // Grab hosts from the configuration. + e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL; + if (!e || !e->hasChildNodes()) { + throw XMLToolingException("Memcache StorageService requires Hosts element in configuration."); + } + auto_ptr_char h(e->getFirstChild()->getNodeValue()); + log.debug("INIT: GOT Hosts: %s", h.get()); + memcached_server_st *servers; + servers = memcached_servers_parse(const_cast(h.get())); + log.debug("Got %u hosts.", memcached_server_list_count(servers)); + if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) { + throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed"); + } + memcached_server_list_free(servers); + + log.debug("Memcache object initialized"); +} + +MemcacheBase::~MemcacheBase() { + memcached_free(memc); + delete m_lock; + log.debug("Base object destroyed"); +} + +MemcacheStorageService::MemcacheStorageService(const DOMElement* e) + : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) { + + const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL; + if (tag && *tag && XMLString::parseInt(tag) != 0) { + m_buildMap = true; + m_log.debug("Cache built with buildMap ON"); + } + +} + +MemcacheStorageService::~MemcacheStorageService() { + + +} + +bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) { + + log.debug("createString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + + mc_record rec(value, expiration); + string final_value; + serialize(rec, final_value); + + bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version + + if (result && m_buildMap) { + log.debug("Got result, updating map"); + + string map_name = context; + // we need to update the context map + if (! addLock(map_name)) { + log.error("Unable to get lock for context %s!", context); + deleteMemcache(final_key.c_str(), 0); + return false; + } + + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + log.debug("value = " + *iter); + } + + } else { + log.debug("New context: %s", map_name.c_str()); + + } + + contents.push_back(key); + serialize(contents, ser_arr); + setMemcache(map_name.c_str(), ser_arr, expiration, 0); + + deleteLock(map_name); + } + + return result; + +} + +int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) { + + log.debug("readString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + uint32_t rec_version; + string value; + + if (m_buildMap) { + log.debug("Checking context"); + + string map_name = context; + string ser_arr; + uint32_t flags; + bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags); + + if (!ctx_found) { + return 0; + } + } + + bool found = getMemcache(final_key.c_str(), value, &rec_version); + if (!found) { + return 0; + } + + if (version && rec_version <= (uint32_t)version) { + return version; + } + + if (pexpiration || pvalue) { + mc_record rec; + deserialize(value, rec); + + if (pexpiration) { + *pexpiration = rec.expiration; + } + + if (pvalue) { + *pvalue = rec.value; + } + } + + return rec_version; + +} + +int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) { + + log.debug("updateString ctx: %s - key: %s", context, key); + + time_t final_exp = expiration; + time_t *want_expiration = NULL; + if (! final_exp) { + want_expiration = &final_exp; + } + + int read_res = readString(context, key, NULL, want_expiration, version); + + if (!read_res) { + // not found + return read_res; + } + + if (version && version != read_res) { + // version incorrect + return -1; + } + + // Proceding with update + string final_key = string(context) + ":" + string(key); + mc_record rec(value, final_exp); + string final_value; + serialize(rec, final_value); + + replaceMemcache(final_key.c_str(), final_value, final_exp, ++version); + return version; + +} + +bool MemcacheStorageService::deleteString(const char* context, const char* key) { + + log.debug("deleteString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + + // Not updating context map, if there is one. There is no need. + + return deleteMemcache(final_key.c_str(), 0); + +} + +void MemcacheStorageService::updateContext(const char* context, time_t expiration) { + + log.debug("updateContext ctx: %s", context); + + if (!m_buildMap) { + log.error("updateContext invoked on a Storage with no context map built!"); + return; + } + + string map_name = context; + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + + // Update expiration times + string value; + int read_res = readString(context, iter->c_str(), &value, NULL, 0); + + if (!read_res) { + // not found + continue; + } + + updateString(context, iter->c_str(), value.c_str(), expiration, read_res); + } + replaceMemcache(map_name.c_str(), ser_arr, expiration, flags); + } + +} + +void MemcacheStorageService::deleteContext(const char* context) { + + log.debug("deleteContext ctx: %s", context); + + if (!m_buildMap) { + log.error("deleteContext invoked on a Storage with no context map built!"); + return; + } + + string map_name = context; + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + string final_key = map_name + *iter; + deleteMemcache(final_key.c_str(), 0); + } + + deleteMemcache(map_name.c_str(), 0); + } + +} + +extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) { + // Register this SS type + XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory); + return 0; +} + +extern "C" void MCEXT_EXPORTS xmltooling_extension_term() { + XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE"); +} diff --git a/memcache-store/memcache-store.rc b/memcache-store/memcache-store.rc index ffd78ff..5edb5b1 100644 --- a/memcache-store/memcache-store.rc +++ b/memcache-store/memcache-store.rc @@ -53,8 +53,8 @@ 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 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,12 +71,12 @@ BEGIN 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" diff --git a/memcache-store/resource.h b/memcache-store/resource.h index 42c4d44..bd4e56a 100644 --- a/memcache-store/resource.h +++ b/memcache-store/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by memcache-store.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by memcache-store.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/nsapi_shib/Makefile.in b/nsapi_shib/Makefile.in index 0af2484..ee81186 100644 --- a/nsapi_shib/Makefile.in +++ b/nsapi_shib/Makefile.in @@ -85,6 +85,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp index 960409d..8914e7e 100644 --- a/nsapi_shib/nsapi_shib.cpp +++ b/nsapi_shib/nsapi_shib.cpp @@ -34,10 +34,17 @@ # define _CRT_RAND_S #endif +#include #include #include #include #include + +#include +#include +#include +#include +#include #include #include #include @@ -45,11 +52,6 @@ #include #include -#include -#include -#include -#include - #ifdef WIN32 # include # define XP_WIN32 @@ -420,6 +422,7 @@ public: setResponseHeader("Content-Type", type); } void setResponseHeader(const char* name, const char* value) { + HTTPResponse::setResponseHeader(name, value); pblock_nvinsert(name, value, m_rq->srvhdrs); } @@ -438,6 +441,7 @@ public: 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); diff --git a/nsapi_shib/nsapi_shib.rc b/nsapi_shib/nsapi_shib.rc index ba31800..a551403 100644 --- a/nsapi_shib/nsapi_shib.rc +++ b/nsapi_shib/nsapi_shib.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // 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 @@ -47,14 +47,14 @@ BEGIN 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 diff --git a/odbc-store/Makefile.in b/odbc-store/Makefile.in index aa61b65..6c1228d 100644 --- a/odbc-store/Makefile.in +++ b/odbc-store/Makefile.in @@ -82,6 +82,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/odbc-store/odbc-store.cpp b/odbc-store/odbc-store.cpp index 8bb7989..546eefc 100644 --- a/odbc-store/odbc-store.cpp +++ b/odbc-store/odbc-store.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -17,7 +17,7 @@ /** * odbc-store.cpp * - * Storage Service using ODBC + * Storage Service using ODBC. */ #if defined (_MSC_VER) || defined(__BORLANDC__) @@ -39,6 +39,7 @@ #include #include +#include #include #include #include diff --git a/odbc-store/odbc-store.rc b/odbc-store/odbc-store.rc index 1a9eb39..0190222 100644 --- a/odbc-store/odbc-store.rc +++ b/odbc-store/odbc-store.rc @@ -53,8 +53,8 @@ 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 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,12 +71,12 @@ BEGIN 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" diff --git a/odbc-store/resource.h b/odbc-store/resource.h index 7a79a45..625d6ee 100644 --- a/odbc-store/resource.h +++ b/odbc-store/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by odbc-store.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by odbc-store.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/pkginfo b/pkginfo index cd040c3..6184208 100644 --- a/pkginfo +++ b/pkginfo @@ -1,5 +1,5 @@ PKG=SHIBsp -VERSION=2.2.1 +VERSION=2.3 BASEDIR=/ NAME=shibboleth-sp CATEGORY=application,security diff --git a/postinstall b/postinstall index 790f33f..a4d5110 100644 --- a/postinstall +++ b/postinstall @@ -15,6 +15,7 @@ CONFIGFILES=" \ discoveryTemplate.html \ localLogout.html \ globalLogout.html \ + partialLogout.html \ attribute-map.xml \ attribute-policy.xml \ example-metadata.xml \ diff --git a/schemas/Makefile.am b/schemas/Makefile.am index 1e73766..561e87f 100644 --- a/schemas/Makefile.am +++ b/schemas/Makefile.am @@ -1,4 +1,4 @@ -## $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 diff --git a/schemas/Makefile.in b/schemas/Makefile.in index a0771af..45a831c 100644 --- a/schemas/Makefile.in +++ b/schemas/Makefile.in @@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/schemas/shibboleth-2.0-afp.xsd b/schemas/shibboleth-2.0-afp.xsd index 675f41f..ded4423 100644 --- a/schemas/shibboleth-2.0-afp.xsd +++ b/schemas/shibboleth-2.0-afp.xsd @@ -4,10 +4,10 @@ xmlns="http://www.w3.org/2001/XMLSchema" xmlns:afp="urn:mace:shibboleth:2.0:afp" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" - elementFormDefault="qualified"> - - - + elementFormDefault="qualified"> + + + Schema for the attribute filter policies. @@ -51,7 +51,7 @@ Defines an attribute rule that may be reused across multiple filter policies. - + @@ -67,10 +67,10 @@ such as a federation site, should be signed. - - + + - + @@ -120,13 +120,13 @@ - - + + A rule that describes how values of an attribute will be filtered. - + @@ -158,7 +158,7 @@ - + @@ -202,4 +202,4 @@ - \ No newline at end of file + diff --git a/schemas/shibboleth-2.0-attribute-map.xsd b/schemas/shibboleth-2.0-attribute-map.xsd index caf5e1e..4fa9883 100644 --- a/schemas/shibboleth-2.0-attribute-map.xsd +++ b/schemas/shibboleth-2.0-attribute-map.xsd @@ -3,7 +3,7 @@ xmlns="http://www.w3.org/2001/XMLSchema" xmlns:am="urn:mace:shibboleth:2.0:attribute-map" elementFormDefault="qualified" - version="2.2"> + version="2.3"> @@ -97,6 +97,14 @@ Flag controlling whether the resulting attribute should be exported for CGI use. + + + + Crypto-provider-specific name of hash algorithm to use, + turning the decoded result into a simple string. + + + @@ -189,4 +197,74 @@ - \ No newline at end of file + + + + Decoder for attributes with ds:KeyInfo values. + + + + + + + + + + + Flag controlling whether to hash keys before base64-encoding them. + + + + + + + Crypto-provider-specific name of hash algorithm to use. + + + + + + + + + + + Decoder for directly serializing XML values. + + + + + + + + + + + Decoder for extracting information from XML values. + + + + + + + + Optional transform to turn qualified XML names into string names. + + + + + + + + + + + The pattern used to generate strings from the XML. + + + + + + + + diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd index 88befab..411b037 100644 --- a/schemas/shibboleth-2.0-native-sp-config.xsd +++ b/schemas/shibboleth-2.0-native-sp-config.xsd @@ -8,7 +8,7 @@ elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="substitution" - version="2.2"> + version="2.3"> @@ -46,10 +46,10 @@ - + - + @@ -83,11 +83,12 @@ - + - + + @@ -101,11 +102,11 @@ - + - + @@ -121,11 +122,11 @@ - + - + @@ -139,11 +140,11 @@ - + - + @@ -287,10 +288,13 @@ + + + @@ -530,11 +534,11 @@ - + - + @@ -576,7 +580,7 @@ - + @@ -589,13 +593,16 @@ - + + + + - + @@ -609,14 +616,14 @@ - + - + @@ -628,7 +635,7 @@ - + @@ -637,10 +644,11 @@ + - + @@ -672,7 +680,7 @@ - + @@ -693,7 +701,7 @@ - + diff --git a/selinux/Makefile.am b/selinux/Makefile.am index 40c68f5..936a875 100644 --- a/selinux/Makefile.am +++ b/selinux/Makefile.am @@ -1,4 +1,4 @@ -## $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 diff --git a/selinux/Makefile.in b/selinux/Makefile.in index 0f6d823..d2ac12e 100644 --- a/selinux/Makefile.in +++ b/selinux/Makefile.in @@ -66,6 +66,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/shibboleth.spec b/shibboleth.spec index 393507a..b5bb7c8 100644 --- a/shibboleth.spec +++ b/shibboleth.spec @@ -1,6 +1,6 @@ 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 @@ -8,18 +8,20 @@ License: Apache 2.0 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 @@ -30,6 +32,7 @@ BuildRequires: zlib-devel %{?_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} @@ -56,15 +59,15 @@ Requires: %{name} = %{version} %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 @@ -122,9 +125,12 @@ fi %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 @@ -149,17 +155,13 @@ sh ./keygen.sh -b 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 @@ -167,18 +169,26 @@ sh ./keygen.sh -b 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 @@ -212,7 +222,10 @@ sh ./keygen.sh -b %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 @@ -231,6 +244,11 @@ sh ./keygen.sh -b %doc %{pkgdocdir}/api %changelog +* Wed Aug 19 2009 Scott Cantor - 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 - 2.2.1-1 - Doc handling changes - SuSE init script diff --git a/shibboleth.spec.in b/shibboleth.spec.in index b6f89d8..a6c612f 100644 --- a/shibboleth.spec.in +++ b/shibboleth.spec.in @@ -1,6 +1,6 @@ Name: @PACKAGE@ Version: @PACKAGE_VERSION@ -Release: 1 +Release: 2 Summary: Open source system for attribute-based Web SSO Group: System Environment/Libraries Vendor: Internet2 @@ -8,18 +8,20 @@ License: Apache 2.0 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 @@ -30,6 +32,7 @@ BuildRequires: zlib-devel %{?_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} @@ -56,15 +59,15 @@ Requires: %{name} = %{version} %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 @@ -122,9 +125,12 @@ fi %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 @@ -149,17 +155,13 @@ sh ./keygen.sh -b 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 @@ -167,18 +169,26 @@ sh ./keygen.sh -b 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 @@ -212,7 +222,10 @@ sh ./keygen.sh -b %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 @@ -231,6 +244,11 @@ sh ./keygen.sh -b %doc %{pkgdocdir}/api %changelog +* Wed Aug 19 2009 Scott Cantor - 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 - 2.2.1-1 - Doc handling changes - SuSE init script diff --git a/shibd/Makefile.am b/shibd/Makefile.am index b545cdc..1e3d276 100644 --- a/shibd/Makefile.am +++ b/shibd/Makefile.am @@ -1,4 +1,4 @@ -## $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 diff --git a/shibd/Makefile.in b/shibd/Makefile.in index eb59ce5..9d29d2d 100644 --- a/shibd/Makefile.in +++ b/shibd/Makefile.in @@ -76,6 +76,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/shibd/shibd.cpp b/shibd/shibd.cpp index 4c86dae..2ac256d 100644 --- a/shibd/shibd.cpp +++ b/shibd/shibd.cpp @@ -1,403 +1,403 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shar.cpp -- the shibd "main" code. All the functionality is elsewhere - * - * Created By: Derek Atkins - * - * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $ - */ - - -// eventually we might be able to support autoconf via cygwin... -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -#include - -#ifdef HAVE_UNISTD_H -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -bool shibd_shutdown = false; -const char* shar_config = NULL; -const char* shar_schemadir = NULL; -const char* shar_prefix = NULL; -bool shar_checkonly = false; -bool shar_version = false; -static bool unlink_socket = false; -const char* pidfile = NULL; - -#ifdef WIN32 - -//#include - -#define nNoMansLandSize 4 -typedef struct _CrtMemBlockHeader -{ - struct _CrtMemBlockHeader * pBlockHeaderNext; - struct _CrtMemBlockHeader * pBlockHeaderPrev; - char * szFileName; - int nLine; - size_t nDataSize; - int nBlockUse; - long lRequest; - unsigned char gap[nNoMansLandSize]; - /* followed by: - * unsigned char data[nDataSize]; - * unsigned char anotherGap[nNoMansLandSize]; - */ -} _CrtMemBlockHeader; - -/* -int MyAllocHook(int nAllocType, void *pvData, - size_t nSize, int nBlockUse, long lRequest, - const unsigned char * szFileName, int nLine) -{ - if ( nBlockUse == _CRT_BLOCK ) - return( TRUE ); - if (nAllocType == _HOOK_FREE) { - _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1); - if (ptr->nDataSize == 8192) - fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize); - } - else if (nAllocType == _HOOK_ALLOC && nSize == 8192) - fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize); - return (TRUE); -} -*/ - -int real_main(int preinit) -{ - SPConfig& conf=SPConfig::getConfig(); - if (preinit) { - - // Initialize the SP library. - conf.setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::Metadata | - SPConfig::Trust | - SPConfig::Credentials | - SPConfig::AttributeResolution | - SPConfig::Handlers | - SPConfig::OutOfProcess | - (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) - ); - if (!conf.init(shar_schemadir, shar_prefix)) { - fprintf(stderr, "configuration is invalid, see console for specific problems\n"); - return -1; - } - - if (!conf.instantiate(shar_config)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - conf.term(); - return -2; - } - - // If just a test run, bail. - if (shar_checkonly) { - fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n"); - return 0; - } - } - else { - - //_CrtSetAllocHook(MyAllocHook); - - if (!shar_checkonly) { - // Run the listener. - ListenerService* listener = conf.getServiceProvider()->getListenerService(); - if (!listener->init(unlink_socket)) { - fprintf(stderr, "listener failed to initialize\n"); - conf.term(); - return -3; - } - else if (!listener->run(&shibd_shutdown)) { - fprintf(stderr, "listener failed during service\n"); - listener->term(); - conf.term(); - return -3; - } - listener->term(); - } - - conf.term(); - } - return 0; -} - -#else - -int daemon_wait = 3; -bool shibd_running = false; -bool daemonize = true; - -static void term_handler(int arg) -{ - shibd_shutdown = true; -} - -static void run_handler(int arg) -{ - shibd_running = true; -} - -static void child_handler(int arg) -{ - // Terminate the parent's wait/sleep if the newly born daemon dies early. -} - -static int setup_signals(void) -{ - struct sigaction sa; - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = SIG_IGN; - sa.sa_flags = SA_RESTART; - - if (sigaction(SIGPIPE, &sa, NULL) < 0) { - return -1; - } - - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = term_handler; - sa.sa_flags = SA_RESTART; - - if (sigaction(SIGHUP, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGINT, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGQUIT, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGTERM, &sa, NULL) < 0) { - return -1; - } - - if (daemonize) { - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = run_handler; - - if (sigaction(SIGUSR1, &sa, NULL) < 0) { - return -1; - } - - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = child_handler; - - if (sigaction(SIGCHLD, &sa, NULL) < 0) { - return -1; - } - } - - return 0; -} - -static void usage(char* whoami) -{ - fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami); - fprintf(stderr, " -d\tinstallation prefix to use.\n"); - fprintf(stderr, " -c\tconfig file to use.\n"); - fprintf(stderr, " -x\tXML schema catalogs to use.\n"); - fprintf(stderr, " -t\ttest configuration file for problems.\n"); - fprintf(stderr, " -f\tforce removal of listener socket.\n"); - fprintf(stderr, " -F\tstay in the foreground.\n"); - fprintf(stderr, " -p\tpid file to use.\n"); - fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n"); - fprintf(stderr, " -v\tprint software version.\n"); - fprintf(stderr, " -h\tprint this help message.\n"); - exit(1); -} - -static int parse_args(int argc, char* argv[]) -{ - int opt; - - while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) { - switch (opt) { - case 'd': - shar_prefix=optarg; - break; - case 'c': - shar_config=optarg; - break; - case 'x': - shar_schemadir=optarg; - break; - case 'f': - unlink_socket = true; - break; - case 'F': - daemonize = false; - break; - case 't': - shar_checkonly=true; - daemonize=false; - break; - case 'v': - shar_version=true; - break; - case 'p': - pidfile=optarg; - break; - case 'w': - if (optarg) - daemon_wait = atoi(optarg); - if (daemon_wait <= 0) - daemon_wait = 3; - break; - default: - return -1; - } - } - return 0; -} - -int main(int argc, char *argv[]) -{ - if (parse_args(argc, argv) != 0) - usage(argv[0]); - else if (shar_version) { - fprintf(stdout, PACKAGE_STRING"\n"); - return 0; - } - - if (setup_signals() != 0) - return -1; - - // initialize the shib-target library - SPConfig& conf=SPConfig::getConfig(); - conf.setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::Metadata | - SPConfig::Trust | - SPConfig::Credentials | - SPConfig::AttributeResolution | - SPConfig::Handlers | - SPConfig::OutOfProcess | - (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) - ); - if (!conf.init(shar_schemadir, shar_prefix)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - return -1; - } - - if (daemonize) { - // We must fork() early, while we're single threaded. - // StorageService cleanup thread is about to start. - switch (fork()) { - case 0: - break; - case -1: - perror("forking"); - exit(EXIT_FAILURE); - default: - sleep(daemon_wait); - exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE); - } - } - - if (!conf.instantiate(shar_config)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - conf.term(); - return -2; - } - - if (shar_checkonly) - fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n"); - else { - // Init the listener. - ListenerService* listener = conf.getServiceProvider()->getListenerService(); - if (!listener->init(unlink_socket)) { - fprintf(stderr, "listener failed to initialize\n"); - conf.term(); - return -3; - } - - if (daemonize) { - if (setsid() == -1) { - perror("setsid"); - exit(EXIT_FAILURE); - } - if (chdir("/") == -1) { - perror("chdir to root"); - exit(EXIT_FAILURE); - } - - if (pidfile) { - FILE* pidf = fopen(pidfile, "w"); - if (pidf) { - fprintf(pidf, "%d\n", getpid()); - fclose(pidf); - } - else { - perror(pidfile); - } - } - - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); - - // Signal our parent that we are A-OK. - kill(getppid(), SIGUSR1); - } - - // Run the listener. - if (!listener->run(&shibd_shutdown)) { - fprintf(stderr, "listener failure during service\n"); - listener->term(); - conf.term(); - if (pidfile) - unlink(pidfile); - return -3; - } - listener->term(); - } - - conf.term(); - if (pidfile) - unlink(pidfile); - return 0; -} - -#endif +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * shar.cpp -- the shibd "main" code. All the functionality is elsewhere + * + * Created By: Derek Atkins + * + * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $ + */ + + +// eventually we might be able to support autoconf via cygwin... +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include + +#ifdef HAVE_UNISTD_H +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +bool shibd_shutdown = false; +const char* shar_config = NULL; +const char* shar_schemadir = NULL; +const char* shar_prefix = NULL; +bool shar_checkonly = false; +bool shar_version = false; +static bool unlink_socket = false; +const char* pidfile = NULL; + +#ifdef WIN32 + +//#include + +#define nNoMansLandSize 4 +typedef struct _CrtMemBlockHeader +{ + struct _CrtMemBlockHeader * pBlockHeaderNext; + struct _CrtMemBlockHeader * pBlockHeaderPrev; + char * szFileName; + int nLine; + size_t nDataSize; + int nBlockUse; + long lRequest; + unsigned char gap[nNoMansLandSize]; + /* followed by: + * unsigned char data[nDataSize]; + * unsigned char anotherGap[nNoMansLandSize]; + */ +} _CrtMemBlockHeader; + +/* +int MyAllocHook(int nAllocType, void *pvData, + size_t nSize, int nBlockUse, long lRequest, + const unsigned char * szFileName, int nLine) +{ + if ( nBlockUse == _CRT_BLOCK ) + return( TRUE ); + if (nAllocType == _HOOK_FREE) { + _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1); + if (ptr->nDataSize == 8192) + fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize); + } + else if (nAllocType == _HOOK_ALLOC && nSize == 8192) + fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize); + return (TRUE); +} +*/ + +int real_main(int preinit) +{ + SPConfig& conf=SPConfig::getConfig(); + if (preinit) { + + // Initialize the SP library. + conf.setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::Metadata | + SPConfig::Trust | + SPConfig::Credentials | + SPConfig::AttributeResolution | + SPConfig::Handlers | + SPConfig::OutOfProcess | + (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) + ); + if (!conf.init(shar_schemadir, shar_prefix)) { + fprintf(stderr, "configuration is invalid, see console for specific problems\n"); + return -1; + } + + if (!conf.instantiate(shar_config)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + conf.term(); + return -2; + } + + // If just a test run, bail. + if (shar_checkonly) { + fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n"); + return 0; + } + } + else { + + //_CrtSetAllocHook(MyAllocHook); + + if (!shar_checkonly) { + // Run the listener. + ListenerService* listener = conf.getServiceProvider()->getListenerService(); + if (!listener->init(unlink_socket)) { + fprintf(stderr, "listener failed to initialize\n"); + conf.term(); + return -3; + } + else if (!listener->run(&shibd_shutdown)) { + fprintf(stderr, "listener failed during service\n"); + listener->term(); + conf.term(); + return -3; + } + listener->term(); + } + + conf.term(); + } + return 0; +} + +#else + +int daemon_wait = 3; +bool shibd_running = false; +bool daemonize = true; + +static void term_handler(int arg) +{ + shibd_shutdown = true; +} + +static void run_handler(int arg) +{ + shibd_running = true; +} + +static void child_handler(int arg) +{ + // Terminate the parent's wait/sleep if the newly born daemon dies early. +} + +static int setup_signals(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGPIPE, &sa, NULL) < 0) { + return -1; + } + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = term_handler; + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGHUP, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGINT, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGQUIT, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGTERM, &sa, NULL) < 0) { + return -1; + } + + if (daemonize) { + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = run_handler; + + if (sigaction(SIGUSR1, &sa, NULL) < 0) { + return -1; + } + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = child_handler; + + if (sigaction(SIGCHLD, &sa, NULL) < 0) { + return -1; + } + } + + return 0; +} + +static void usage(char* whoami) +{ + fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami); + fprintf(stderr, " -d\tinstallation prefix to use.\n"); + fprintf(stderr, " -c\tconfig file to use.\n"); + fprintf(stderr, " -x\tXML schema catalogs to use.\n"); + fprintf(stderr, " -t\ttest configuration file for problems.\n"); + fprintf(stderr, " -f\tforce removal of listener socket.\n"); + fprintf(stderr, " -F\tstay in the foreground.\n"); + fprintf(stderr, " -p\tpid file to use.\n"); + fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n"); + fprintf(stderr, " -v\tprint software version.\n"); + fprintf(stderr, " -h\tprint this help message.\n"); + exit(1); +} + +static int parse_args(int argc, char* argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) { + switch (opt) { + case 'd': + shar_prefix=optarg; + break; + case 'c': + shar_config=optarg; + break; + case 'x': + shar_schemadir=optarg; + break; + case 'f': + unlink_socket = true; + break; + case 'F': + daemonize = false; + break; + case 't': + shar_checkonly=true; + daemonize=false; + break; + case 'v': + shar_version=true; + break; + case 'p': + pidfile=optarg; + break; + case 'w': + if (optarg) + daemon_wait = atoi(optarg); + if (daemon_wait <= 0) + daemon_wait = 3; + break; + default: + return -1; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (parse_args(argc, argv) != 0) + usage(argv[0]); + else if (shar_version) { + fprintf(stdout, PACKAGE_STRING"\n"); + return 0; + } + + if (setup_signals() != 0) + return -1; + + // initialize the shib-target library + SPConfig& conf=SPConfig::getConfig(); + conf.setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::Metadata | + SPConfig::Trust | + SPConfig::Credentials | + SPConfig::AttributeResolution | + SPConfig::Handlers | + SPConfig::OutOfProcess | + (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) + ); + if (!conf.init(shar_schemadir, shar_prefix)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + return -1; + } + + if (daemonize) { + // We must fork() early, while we're single threaded. + // StorageService cleanup thread is about to start. + switch (fork()) { + case 0: + break; + case -1: + perror("forking"); + exit(EXIT_FAILURE); + default: + sleep(daemon_wait); + exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE); + } + } + + if (!conf.instantiate(shar_config)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + conf.term(); + return -2; + } + + if (shar_checkonly) + fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n"); + else { + // Init the listener. + ListenerService* listener = conf.getServiceProvider()->getListenerService(); + if (!listener->init(unlink_socket)) { + fprintf(stderr, "listener failed to initialize\n"); + conf.term(); + return -3; + } + + if (daemonize) { + if (setsid() == -1) { + perror("setsid"); + exit(EXIT_FAILURE); + } + if (chdir("/") == -1) { + perror("chdir to root"); + exit(EXIT_FAILURE); + } + + if (pidfile) { + FILE* pidf = fopen(pidfile, "w"); + if (pidf) { + fprintf(pidf, "%d\n", getpid()); + fclose(pidf); + } + else { + perror(pidfile); + } + } + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + + // Signal our parent that we are A-OK. + kill(getppid(), SIGUSR1); + } + + // Run the listener. + if (!listener->run(&shibd_shutdown)) { + fprintf(stderr, "listener failure during service\n"); + listener->term(); + conf.term(); + if (pidfile) + unlink(pidfile); + return -3; + } + listener->term(); + } + + conf.term(); + if (pidfile) + unlink(pidfile); + return 0; +} + +#endif diff --git a/shibd/shibd.rc b/shibd/shibd.rc index 4f11667..264fc0c 100644 --- a/shibd/shibd.rc +++ b/shibd/shibd.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // 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 @@ -47,14 +47,14 @@ BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "Internet2\0" VALUE "FileDescription", "Shibboleth Daemon Service\0" - VALUE "FileVersion", "2, 2, 1, 0\0" + VALUE "FileVersion", "2, 3, 0, 0\0" VALUE "InternalName", "shibd\0" VALUE "LegalCopyright", "Copyright © 2009 Internet2\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "shibd.exe\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 diff --git a/shibd/shibd_win32.cpp b/shibd/shibd_win32.cpp index b196ea8..7a9a602 100644 --- a/shibd/shibd_win32.cpp +++ b/shibd/shibd_win32.cpp @@ -1,529 +1,529 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shar_win32.cpp -- the SHAR "main" code on Win32 - * - * Created By: Scott Cantor (cantor.2@osu.edu) - * - * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $ - */ - -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 - -#include -#include -#include - -using namespace std; - -extern bool shibd_shutdown; // signals shutdown to Unix side -extern const char* shar_schemadir; -extern const char* shar_config; -extern const char* shar_prefix; -extern bool shar_checkonly; - -// internal variables -SERVICE_STATUS ssStatus; // current status of the service -SERVICE_STATUS_HANDLE sshStatusHandle; -DWORD dwErr = 0; -BOOL bConsole = FALSE; -char szErr[256]; -LPCSTR lpszInstall = NULL; -LPCSTR lpszRemove = NULL; - -// internal function prototypes -VOID WINAPI service_ctrl(DWORD dwCtrlCode); -VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv); -VOID CmdInstallService(LPCSTR); -VOID CmdRemoveService(LPCSTR); -LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ); - -BOOL LogEvent( - LPCTSTR lpUNCServerName, - WORD wType, - DWORD dwEventID, - PSID lpUserSid, - LPCTSTR message); - -VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv); -VOID ServiceStop(); -BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); -void AddToMessageLog(LPSTR lpszMsg); - -BOOL WINAPI BreakHandler(DWORD dwCtrlType) -{ - switch(dwCtrlType) - { - case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate - case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode - ServiceStop(); - return TRUE; - } - return FALSE; -} - - -int real_main(int); // The revised two-phase main() in shar.cpp - -int main(int argc, char *argv[]) -{ - int i=1; - while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/'))) - { - if (_stricmp("install", argv[i]+1) == 0) - { - if (argc > ++i) - lpszInstall = argv[i++]; - } - else if (_stricmp("remove", argv[i]+1) == 0) - { - if (argc > ++i) - lpszRemove = argv[i++]; - } - else if (_stricmp( "console", argv[i]+1) == 0) - { - i++; - bConsole = TRUE; - } - else if (_stricmp( "check", argv[i]+1) == 0) - { - i++; - bConsole = TRUE; - shar_checkonly=true; - } - else if (_stricmp( "config", argv[i]+1) == 0) - { - if (argc > ++i) - shar_config = argv[i++]; - } - else if (_stricmp( "prefix", argv[i]+1) == 0) - { - if (argc > ++i) - shar_prefix = argv[i++]; - } - else if (_stricmp( "catalogs", argv[i]+1) == 0) - { - if (argc > ++i) - shar_schemadir = argv[i++]; - } - else - { - goto dispatch; - } - } - - if (bConsole) - { - // Install break handler, then run the C routine twice, once to setup, once to start running. - SetConsoleCtrlHandler(&BreakHandler,TRUE); - if ((i=real_main(1))!=0) - { - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); - return i; - } - return real_main(0); - } - else if (lpszInstall) - { - CmdInstallService(lpszInstall); - return 0; - } - else if (lpszRemove) - { - CmdRemoveService(lpszRemove); - return 0; - } - - - // if it doesn't match any of the above parameters - // the service control manager may be starting the service - // so we must call StartServiceCtrlDispatcher - dispatch: - // this is just to be friendly - printf("%s -install to install the named service\n", argv[0]); - printf("%s -remove to remove the named service\n", argv[0]); - printf("%s -console to run as a console app for debugging\n", argv[0]); - printf("%s -check to run as a console app and check configuration\n", argv[0]); - printf("\t-prefix to specify the installation directory\n"); - printf("\t-config to specify the config file to use\n"); - printf("\t-catalogs to specify schema catalogs\n"); - printf("\nService starting.\nThis may take several seconds. Please wait.\n" ); - - SERVICE_TABLE_ENTRY dispatchTable[] = - { - { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main }, - { NULL, NULL } - }; - - if (!StartServiceCtrlDispatcher(dispatchTable)) - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed."); - return 0; -} - -// -// FUNCTION: ServiceStart -// -// PURPOSE: Actual code of the service -// that does the work. -// -VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv) -{ - - if (real_main(1)!=0) - { - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); - return; - } - - LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully."); - - if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0)) - return; - - real_main(0); -} - - -// -// FUNCTION: ServiceStop -// -// PURPOSE: Stops the service -// -VOID ServiceStop() -{ - if (!bConsole) - LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping..."); - shibd_shutdown=true; -} - - -void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv) -{ - - // register our service control handler: - sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl); - if (!sshStatusHandle) - goto cleanup; - - // SERVICE_STATUS members that don't change in example - ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - ssStatus.dwServiceSpecificExitCode = 0; - - - // report the status to the service control manager. - if (!ReportStatusToSCMgr( - SERVICE_START_PENDING, // service state - NO_ERROR, // exit code - 3000)) // wait hint - goto cleanup; - - - ServiceStart(dwArgc, lpszArgv); - -cleanup: - - // try to report the stopped status to the service control manager. - // - if (sshStatusHandle) - (VOID)ReportStatusToSCMgr( - SERVICE_STOPPED, - dwErr, - 0); - - return; -} - - -// -// FUNCTION: service_ctrl -// -// PURPOSE: This function is called by the SCM whenever -// ControlService() is called on this service. -// -// PARAMETERS: -// dwCtrlCode - type of control requested -// -// RETURN VALUE: -// none -// -VOID WINAPI service_ctrl(DWORD dwCtrlCode) -{ - // Handle the requested control code. - // - switch(dwCtrlCode) - { - // Stop the service. - // - case SERVICE_CONTROL_STOP: - ssStatus.dwCurrentState = SERVICE_STOP_PENDING; - ServiceStop(); - break; - - // Update the service status. - // - case SERVICE_CONTROL_INTERROGATE: - break; - - // invalid control code - // - default: - break; - - } - - ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); -} - - -// -// FUNCTION: ReportStatusToSCMgr() -// -// PURPOSE: Sets the current status of the service and -// reports it to the Service Control Manager -// -// PARAMETERS: -// dwCurrentState - the state of the service -// dwWin32ExitCode - error code to report -// dwWaitHint - worst case estimate to next checkpoint -// -// RETURN VALUE: -// TRUE - success -// FALSE - failure -// -BOOL ReportStatusToSCMgr(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) -{ - static DWORD dwCheckPoint = 1; - BOOL fResult = TRUE; - - - if (!bConsole) // when console we don't report to the SCM - { - if (dwCurrentState == SERVICE_START_PENDING) - ssStatus.dwControlsAccepted = 0; - else - ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - - ssStatus.dwCurrentState = dwCurrentState; - ssStatus.dwWin32ExitCode = dwWin32ExitCode; - ssStatus.dwWaitHint = dwWaitHint; - - if ( ( dwCurrentState == SERVICE_RUNNING ) || - ( dwCurrentState == SERVICE_STOPPED ) ) - ssStatus.dwCheckPoint = 0; - else - ssStatus.dwCheckPoint = dwCheckPoint++; - - - // Report the status of the service to the service control manager. - // - if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed."); - } - return fResult; -} - - -/////////////////////////////////////////////////////////////////// -// -// The following code handles service installation and removal -// -// -void CmdInstallService(LPCSTR name) -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - - char szPath[256]; - - if ( GetModuleFileName( NULL, szPath, 256 ) == 0 ) - { - printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256)); - return; - } - - string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")"; - string realName = string("shibd_") + name; - string cmd(szPath); - if (shar_prefix) - cmd = cmd + " -prefix " + shar_prefix; - if (shar_config) - cmd = cmd + " -config " + shar_config; - if (shar_schemadir) - cmd = cmd + " -schemadir " + shar_schemadir; - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_ALL_ACCESS // access required - ); - - - if ( schSCManager ) - { - schService = CreateService( - schSCManager, // SCManager database - realName.c_str(), // name of service - dispName.c_str(), // name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - SERVICE_AUTO_START, // start type - SERVICE_ERROR_NORMAL, // error control type - cmd.c_str(), // service's command line - NULL, // no load ordering group - NULL, // no tag identifier - NULL, // dependencies - NULL, // LocalSystem account - NULL); // no password - - if ( schService ) - { - printf("%s installed.\n", realName.c_str()); - CloseServiceHandle(schService); - } - else - { - printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256)); - } - - CloseServiceHandle(schSCManager); - } - else - printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); -} - -void CmdRemoveService(LPCSTR name) -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - char realName[512]; - - _snprintf(realName,sizeof(realName),"shibd_%s",name); - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_ALL_ACCESS // access required - ); - if ( schSCManager ) - { - schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS); - - if (schService) - { - // try to stop the service - if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) - { - printf("Stopping shibd (%s).", name); - Sleep( 1000 ); - - while( QueryServiceStatus( schService, &ssStatus ) ) - { - if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) - { - printf("."); - Sleep( 1000 ); - } - else - break; - } - - if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) - printf("\n%s stopped.\n", realName); - else - printf("\n%s failed to stop.\n", realName); - - } - - // now remove the service - if( DeleteService(schService) ) - printf("%s removed.\n", realName); - else - printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256)); - - - CloseServiceHandle(schService); - } - else - printf("OpenService failed - %s\n", GetLastErrorText(szErr,256)); - - CloseServiceHandle(schSCManager); - } - else - printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); -} - - -// -// FUNCTION: GetLastErrorText -// -// PURPOSE: copies error message text to string -// -// PARAMETERS: -// lpszBuf - destination buffer -// dwSize - size of buffer -// -// RETURN VALUE: -// destination buffer -// -// COMMENTS: -// -LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ) -{ - DWORD dwRet; - LPSTR lpszTemp = NULL; - - dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, - GetLastError(), - LANG_NEUTRAL, - (LPSTR)&lpszTemp, - 0, - NULL ); - - // supplied buffer is not long enough - if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) - lpszBuf[0] = '\0'; - else - { - lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character - sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() ); - } - - if ( lpszTemp ) - LocalFree((HLOCAL) lpszTemp ); - - return lpszBuf; -} - -BOOL LogEvent( - LPCSTR lpUNCServerName, - WORD wType, - DWORD dwEventID, - PSID lpUserSid, - LPCSTR message) -{ - LPCSTR messages[] = {message, NULL}; - - HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon"); - BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL); - return (DeregisterEventSource(hElog) && res); -} +/* + * Copyright 2001-2007 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * shar_win32.cpp -- the SHAR "main" code on Win32 + * + * Created By: Scott Cantor (cantor.2@osu.edu) + * + * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $ + */ + +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 + +#include +#include +#include + +using namespace std; + +extern bool shibd_shutdown; // signals shutdown to Unix side +extern const char* shar_schemadir; +extern const char* shar_config; +extern const char* shar_prefix; +extern bool shar_checkonly; + +// internal variables +SERVICE_STATUS ssStatus; // current status of the service +SERVICE_STATUS_HANDLE sshStatusHandle; +DWORD dwErr = 0; +BOOL bConsole = FALSE; +char szErr[256]; +LPCSTR lpszInstall = NULL; +LPCSTR lpszRemove = NULL; + +// internal function prototypes +VOID WINAPI service_ctrl(DWORD dwCtrlCode); +VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv); +VOID CmdInstallService(LPCSTR); +VOID CmdRemoveService(LPCSTR); +LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ); + +BOOL LogEvent( + LPCTSTR lpUNCServerName, + WORD wType, + DWORD dwEventID, + PSID lpUserSid, + LPCTSTR message); + +VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv); +VOID ServiceStop(); +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); +void AddToMessageLog(LPSTR lpszMsg); + +BOOL WINAPI BreakHandler(DWORD dwCtrlType) +{ + switch(dwCtrlType) + { + case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate + case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode + ServiceStop(); + return TRUE; + } + return FALSE; +} + + +int real_main(int); // The revised two-phase main() in shar.cpp + +int main(int argc, char *argv[]) +{ + int i=1; + while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/'))) + { + if (_stricmp("install", argv[i]+1) == 0) + { + if (argc > ++i) + lpszInstall = argv[i++]; + } + else if (_stricmp("remove", argv[i]+1) == 0) + { + if (argc > ++i) + lpszRemove = argv[i++]; + } + else if (_stricmp( "console", argv[i]+1) == 0) + { + i++; + bConsole = TRUE; + } + else if (_stricmp( "check", argv[i]+1) == 0) + { + i++; + bConsole = TRUE; + shar_checkonly=true; + } + else if (_stricmp( "config", argv[i]+1) == 0) + { + if (argc > ++i) + shar_config = argv[i++]; + } + else if (_stricmp( "prefix", argv[i]+1) == 0) + { + if (argc > ++i) + shar_prefix = argv[i++]; + } + else if (_stricmp( "catalogs", argv[i]+1) == 0) + { + if (argc > ++i) + shar_schemadir = argv[i++]; + } + else + { + goto dispatch; + } + } + + if (bConsole) + { + // Install break handler, then run the C routine twice, once to setup, once to start running. + SetConsoleCtrlHandler(&BreakHandler,TRUE); + if ((i=real_main(1))!=0) + { + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); + return i; + } + return real_main(0); + } + else if (lpszInstall) + { + CmdInstallService(lpszInstall); + return 0; + } + else if (lpszRemove) + { + CmdRemoveService(lpszRemove); + return 0; + } + + + // if it doesn't match any of the above parameters + // the service control manager may be starting the service + // so we must call StartServiceCtrlDispatcher + dispatch: + // this is just to be friendly + printf("%s -install to install the named service\n", argv[0]); + printf("%s -remove to remove the named service\n", argv[0]); + printf("%s -console to run as a console app for debugging\n", argv[0]); + printf("%s -check to run as a console app and check configuration\n", argv[0]); + printf("\t-prefix to specify the installation directory\n"); + printf("\t-config to specify the config file to use\n"); + printf("\t-catalogs to specify schema catalogs\n"); + printf("\nService starting.\nThis may take several seconds. Please wait.\n" ); + + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main }, + { NULL, NULL } + }; + + if (!StartServiceCtrlDispatcher(dispatchTable)) + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed."); + return 0; +} + +// +// FUNCTION: ServiceStart +// +// PURPOSE: Actual code of the service +// that does the work. +// +VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv) +{ + + if (real_main(1)!=0) + { + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); + return; + } + + LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully."); + + if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0)) + return; + + real_main(0); +} + + +// +// FUNCTION: ServiceStop +// +// PURPOSE: Stops the service +// +VOID ServiceStop() +{ + if (!bConsole) + LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping..."); + shibd_shutdown=true; +} + + +void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv) +{ + + // register our service control handler: + sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl); + if (!sshStatusHandle) + goto cleanup; + + // SERVICE_STATUS members that don't change in example + ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ssStatus.dwServiceSpecificExitCode = 0; + + + // report the status to the service control manager. + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto cleanup; + + + ServiceStart(dwArgc, lpszArgv); + +cleanup: + + // try to report the stopped status to the service control manager. + // + if (sshStatusHandle) + (VOID)ReportStatusToSCMgr( + SERVICE_STOPPED, + dwErr, + 0); + + return; +} + + +// +// FUNCTION: service_ctrl +// +// PURPOSE: This function is called by the SCM whenever +// ControlService() is called on this service. +// +// PARAMETERS: +// dwCtrlCode - type of control requested +// +// RETURN VALUE: +// none +// +VOID WINAPI service_ctrl(DWORD dwCtrlCode) +{ + // Handle the requested control code. + // + switch(dwCtrlCode) + { + // Stop the service. + // + case SERVICE_CONTROL_STOP: + ssStatus.dwCurrentState = SERVICE_STOP_PENDING; + ServiceStop(); + break; + + // Update the service status. + // + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + + } + + ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); +} + + +// +// FUNCTION: ReportStatusToSCMgr() +// +// PURPOSE: Sets the current status of the service and +// reports it to the Service Control Manager +// +// PARAMETERS: +// dwCurrentState - the state of the service +// dwWin32ExitCode - error code to report +// dwWaitHint - worst case estimate to next checkpoint +// +// RETURN VALUE: +// TRUE - success +// FALSE - failure +// +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + BOOL fResult = TRUE; + + + if (!bConsole) // when console we don't report to the SCM + { + if (dwCurrentState == SERVICE_START_PENDING) + ssStatus.dwControlsAccepted = 0; + else + ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + ssStatus.dwCurrentState = dwCurrentState; + ssStatus.dwWin32ExitCode = dwWin32ExitCode; + ssStatus.dwWaitHint = dwWaitHint; + + if ( ( dwCurrentState == SERVICE_RUNNING ) || + ( dwCurrentState == SERVICE_STOPPED ) ) + ssStatus.dwCheckPoint = 0; + else + ssStatus.dwCheckPoint = dwCheckPoint++; + + + // Report the status of the service to the service control manager. + // + if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed."); + } + return fResult; +} + + +/////////////////////////////////////////////////////////////////// +// +// The following code handles service installation and removal +// +// +void CmdInstallService(LPCSTR name) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + char szPath[256]; + + if ( GetModuleFileName( NULL, szPath, 256 ) == 0 ) + { + printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256)); + return; + } + + string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")"; + string realName = string("shibd_") + name; + string cmd(szPath); + if (shar_prefix) + cmd = cmd + " -prefix " + shar_prefix; + if (shar_config) + cmd = cmd + " -config " + shar_config; + if (shar_schemadir) + cmd = cmd + " -schemadir " + shar_schemadir; + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + + + if ( schSCManager ) + { + schService = CreateService( + schSCManager, // SCManager database + realName.c_str(), // name of service + dispName.c_str(), // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS, // service type + SERVICE_AUTO_START, // start type + SERVICE_ERROR_NORMAL, // error control type + cmd.c_str(), // service's command line + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // dependencies + NULL, // LocalSystem account + NULL); // no password + + if ( schService ) + { + printf("%s installed.\n", realName.c_str()); + CloseServiceHandle(schService); + } + else + { + printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256)); + } + + CloseServiceHandle(schSCManager); + } + else + printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); +} + +void CmdRemoveService(LPCSTR name) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + char realName[512]; + + _snprintf(realName,sizeof(realName),"shibd_%s",name); + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if ( schSCManager ) + { + schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS); + + if (schService) + { + // try to stop the service + if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) + { + printf("Stopping shibd (%s).", name); + Sleep( 1000 ); + + while( QueryServiceStatus( schService, &ssStatus ) ) + { + if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) + { + printf("."); + Sleep( 1000 ); + } + else + break; + } + + if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) + printf("\n%s stopped.\n", realName); + else + printf("\n%s failed to stop.\n", realName); + + } + + // now remove the service + if( DeleteService(schService) ) + printf("%s removed.\n", realName); + else + printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256)); + + + CloseServiceHandle(schService); + } + else + printf("OpenService failed - %s\n", GetLastErrorText(szErr,256)); + + CloseServiceHandle(schSCManager); + } + else + printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); +} + + +// +// FUNCTION: GetLastErrorText +// +// PURPOSE: copies error message text to string +// +// PARAMETERS: +// lpszBuf - destination buffer +// dwSize - size of buffer +// +// RETURN VALUE: +// destination buffer +// +// COMMENTS: +// +LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ) +{ + DWORD dwRet; + LPSTR lpszTemp = NULL; + + dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, + GetLastError(), + LANG_NEUTRAL, + (LPSTR)&lpszTemp, + 0, + NULL ); + + // supplied buffer is not long enough + if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) + lpszBuf[0] = '\0'; + else + { + lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character + sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() ); + } + + if ( lpszTemp ) + LocalFree((HLOCAL) lpszTemp ); + + return lpszBuf; +} + +BOOL LogEvent( + LPCSTR lpUNCServerName, + WORD wType, + DWORD dwEventID, + PSID lpUserSid, + LPCSTR message) +{ + LPCSTR messages[] = {message, NULL}; + + HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon"); + BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL); + return (DeregisterEventSource(hElog) && res); +} diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp index c18d826..249db33 100644 --- a/shibsp/AbstractSPRequest.cpp +++ b/shibsp/AbstractSPRequest.cpp @@ -17,20 +17,39 @@ /** * 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) @@ -50,6 +69,11 @@ AbstractSPRequest::~AbstractSPRequest() delete m_parser; } +const ServiceProvider& AbstractSPRequest::getServiceProvider() const +{ + return *m_sp; +} + RequestMapper::Settings AbstractSPRequest::getRequestSettings() const { if (!m_mapper) { @@ -147,6 +171,11 @@ void AbstractSPRequest::setRequestURI(const char* uri) } } +const char* AbstractSPRequest::getRequestURI() const +{ + return m_uri.c_str(); +} + const char* AbstractSPRequest::getRequestURL() const { if (m_url.empty()) { diff --git a/shibsp/AbstractSPRequest.h b/shibsp/AbstractSPRequest.h index 1253256..318f68c 100644 --- a/shibsp/AbstractSPRequest.h +++ b/shibsp/AbstractSPRequest.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,18 +17,18 @@ /** * @file shibsp/AbstractSPRequest.h * - * Abstract base for SPRequest implementations + * Abstract base for SPRequest implementations. */ #ifndef __shibsp_abstreq_h__ #define __shibsp_abstreq_h__ -#include #include -#include namespace shibsp { + class SHIBSP_API CGIParser; + #if defined (_MSC_VER) #pragma warning( push ) #pragma warning( disable : 4251 ) @@ -49,7 +49,7 @@ namespace shibsp { /** * 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 */ @@ -58,32 +58,18 @@ namespace shibsp { 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::size_type getParameters(const char* name, std::vector& 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: diff --git a/shibsp/AccessControl.h b/shibsp/AccessControl.h index 59178aa..c94e969 100644 --- a/shibsp/AccessControl.h +++ b/shibsp/AccessControl.h @@ -42,9 +42,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(AccessControl); protected: - AccessControl() {} + AccessControl(); public: - virtual ~AccessControl() {} + virtual ~AccessControl(); /** * Possible results from an access control decision. diff --git a/shibsp/Application.cpp b/shibsp/Application.cpp index 6ee7919..b54e5d5 100644 --- a/shibsp/Application.cpp +++ b/shibsp/Application.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -28,6 +28,7 @@ #include "remoting/ListenerService.h" #include +#include using namespace shibsp; using namespace xmltooling; @@ -42,6 +43,16 @@ Application::~Application() delete m_lock; } +const ServiceProvider& Application::getServiceProvider() const +{ + return *m_sp; +} + +const char* Application::getId() const +{ + return getString("id").second; +} + pair Application::getCookieNameProps(const char* prefix, time_t* lifetime) const { static const char* defProps="; path=/"; diff --git a/shibsp/Application.h b/shibsp/Application.h index cfd38e7..676b24c 100644 --- a/shibsp/Application.h +++ b/shibsp/Application.h @@ -25,15 +25,28 @@ #include -#include +#include +#include #ifndef SHIBSP_LITE # include -# include -# include -# include #endif -#include -#include + +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 { @@ -90,18 +103,14 @@ 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. diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am index 811d4ed..dea7654 100644 --- a/shibsp/Makefile.am +++ b/shibsp/Makefile.am @@ -107,6 +107,10 @@ common_sources = \ 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 \ @@ -164,6 +168,7 @@ libshibsp_la_SOURCES = \ 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 \ @@ -195,13 +200,14 @@ libshibsp_la_SOURCES = \ 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@ diff --git a/shibsp/Makefile.in b/shibsp/Makefile.in index 43015a5..6e3bd9c 100644 --- a/shibsp/Makefile.in +++ b/shibsp/Makefile.in @@ -76,6 +76,10 @@ am__objects_1 = libshibsp_lite_la-AbstractSPRequest.lo \ 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 \ @@ -121,7 +125,8 @@ libshibsp_lite_la_OBJECTS = $(am_libshibsp_lite_la_OBJECTS) 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 \ @@ -142,9 +147,9 @@ am_libshibsp_la_OBJECTS = $(am__objects_2) DOMAttributeDecoder.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 \ @@ -162,7 +167,8 @@ am_libshibsp_la_OBJECTS = $(am__objects_2) DOMAttributeDecoder.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 @@ -203,6 +209,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ @@ -490,6 +498,10 @@ common_sources = \ 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 \ @@ -547,6 +559,7 @@ libshibsp_la_SOURCES = \ 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 \ @@ -578,14 +591,15 @@ libshibsp_la_SOURCES = \ 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@ @@ -689,6 +703,7 @@ distclean-compile: @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@ @@ -712,6 +727,8 @@ distclean-compile: @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@ @@ -731,6 +748,7 @@ distclean-compile: @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@ @@ -738,6 +756,7 @@ distclean-compile: @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@ @@ -748,6 +767,7 @@ distclean-compile: @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@ @@ -773,6 +793,7 @@ distclean-compile: @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@ @@ -785,10 +806,12 @@ distclean-compile: @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@ @@ -798,6 +821,7 @@ distclean-compile: @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@ @@ -865,6 +889,34 @@ libshibsp_lite_la-ExtensibleAttribute.lo: attribute/ExtensibleAttribute.cpp @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 @@ -1166,6 +1218,34 @@ ExtensibleAttribute.lo: attribute/ExtensibleAttribute.cpp @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 @@ -1509,6 +1589,13 @@ XMLAttributeFilter.lo: attribute/filtering/impl/XMLAttributeFilter.cpp @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 @@ -1726,6 +1813,13 @@ MetadataExtSchemaValidators.lo: metadata/MetadataExtSchemaValidators.cpp @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 diff --git a/shibsp/RequestMapper.h b/shibsp/RequestMapper.h index 646cbdd..12971e2 100644 --- a/shibsp/RequestMapper.h +++ b/shibsp/RequestMapper.h @@ -1,5 +1,5 @@ /* - * 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. @@ -25,7 +25,10 @@ #include #include -#include + +namespace xmltooling { + class XMLTOOL_API HTTPRequest; +}; namespace shibsp { @@ -42,9 +45,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(RequestMapper); protected: - RequestMapper() {} + RequestMapper(); public: - virtual ~RequestMapper() {} + virtual ~RequestMapper(); /** Combination of configuration settings and effective access control. */ typedef std::pair Settings; diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp index cbc9f8c..c5c8d4e 100644 --- a/shibsp/SPConfig.cpp +++ b/shibsp/SPConfig.cpp @@ -18,7 +18,7 @@ /** * SPConfig.cpp * - * Library configuration + * Library configuration. */ #include "internal.h" @@ -41,6 +41,7 @@ #include "ServiceProvider.h" #include "SessionCache.h" #include "SPConfig.h" +#include "TransactionLog.h" #include "attribute/Attribute.h" #include "handler/SessionInitiator.h" #include "remoting/ListenerService.h" @@ -55,15 +56,16 @@ # include "metadata/MetadataExt.h" # include "security/PKIXTrustEngine.h" # include -#else -# include #endif #include #include +#include #include +#include #include #include +#include #include using namespace shibsp; @@ -96,12 +98,52 @@ SPConfig& SPConfig::getConfig() 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 @@ -342,3 +384,23 @@ bool SPConfig::instantiate(const char* config, bool rethrow) } 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(); +} diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h index 99f1a22..3764eda 100644 --- a/shibsp/SPConfig.h +++ b/shibsp/SPConfig.h @@ -24,10 +24,14 @@ #define __shibsp_config_h__ #include + +#include #ifndef SHIBSP_LITE # include +# include #endif #include +#include #include /** @@ -65,14 +69,9 @@ namespace shibsp { { 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. @@ -105,9 +104,7 @@ namespace shibsp { * * @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. @@ -115,9 +112,7 @@ namespace shibsp { * @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 @@ -153,9 +148,7 @@ namespace shibsp { * * @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 @@ -176,19 +169,14 @@ namespace shibsp { * * @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. */ diff --git a/shibsp/SPRequest.h b/shibsp/SPRequest.h index 255e8b5..6ce9eff 100644 --- a/shibsp/SPRequest.h +++ b/shibsp/SPRequest.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,7 +17,7 @@ /** * @file shibsp/SPRequest.h * - * Interface to server request being processed + * Interface to server request being processed. */ #ifndef __shibsp_req_h__ @@ -45,9 +45,9 @@ namespace shibsp { 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. @@ -98,9 +98,7 @@ namespace shibsp { * @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. @@ -130,8 +128,7 @@ namespace shibsp { * * @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 { diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp index 0006dbc..a43a9e0 100644 --- a/shibsp/ServiceProvider.cpp +++ b/shibsp/ServiceProvider.cpp @@ -33,6 +33,10 @@ #include #include +#ifndef SHIBSP_LITE +# include +# include +#endif #include #include #include @@ -99,23 +103,30 @@ namespace shibsp { 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); } @@ -139,6 +150,14 @@ void SHIBSP_API shibsp::registerServiceProviders() SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); } +ServiceProvider::ServiceProvider() +{ +} + +ServiceProvider::~ServiceProvider() +{ +} + pair ServiceProvider::doAuthentication(SPRequest& request, bool handler) const { #ifdef _DEBUG diff --git a/shibsp/ServiceProvider.h b/shibsp/ServiceProvider.h index 9ef1dae..2d0694a 100644 --- a/shibsp/ServiceProvider.h +++ b/shibsp/ServiceProvider.h @@ -1,5 +1,5 @@ /* - * 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. @@ -24,12 +24,19 @@ #define __shibsp_sp_h__ #include + +#include + +namespace xmltooling { + class XMLTOOL_API SOAPTransport; + class XMLTOOL_API StorageService; +}; + #ifndef SHIBSP_LITE -# include -# include -# include +namespace opensaml { + class SAML_API SecurityPolicyRule; +}; #endif -#include namespace shibsp { @@ -54,9 +61,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(ServiceProvider); protected: - ServiceProvider() {} + ServiceProvider(); public: - virtual ~ServiceProvider() {} + virtual ~ServiceProvider(); /** * Loads a configuration and prepares the instance for use. diff --git a/shibsp/SessionCache.h b/shibsp/SessionCache.h index ad3af9d..38fa126 100644 --- a/shibsp/SessionCache.h +++ b/shibsp/SessionCache.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,20 +17,35 @@ /** * @file shibsp/SessionCache.h * - * Caches and manages user sessions + * Caches and manages user sessions. */ #ifndef __shibsp_sessioncache_h__ #define __shibsp_sessioncache_h__ #include + +#include +#include +#include +#include +#include +#include + +namespace xmltooling { + class XMLTOOL_API HTTPRequest; + class XMLTOOL_API HTTPResponse; +}; + #ifndef SHIBSP_LITE -# include -# include +# include +namespace opensaml { + class SAML_API Assertion; + namespace saml2 { + class SAML_API NameID; + }; +}; #endif -#include -#include -#include namespace shibsp { @@ -49,8 +64,8 @@ namespace shibsp { { MAKE_NONCOPYABLE(Session); protected: - Session() {} - virtual ~Session() {} + Session(); + virtual ~Session(); public: /** * Returns the session key. @@ -203,9 +218,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(SessionCache); protected: - SessionCache() {} + SessionCache(); public: - virtual ~SessionCache() {} + virtual ~SessionCache(); #ifndef SHIBSP_LITE /** diff --git a/shibsp/SessionCacheEx.h b/shibsp/SessionCacheEx.h index b71f568..61a35fb 100644 --- a/shibsp/SessionCacheEx.h +++ b/shibsp/SessionCacheEx.h @@ -1,5 +1,5 @@ /* - * 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. @@ -33,9 +33,9 @@ namespace shibsp { class SHIBSP_API SessionCacheEx : public SessionCache { protected: - SessionCacheEx() {} + SessionCacheEx(); public: - virtual ~SessionCacheEx() {} + virtual ~SessionCacheEx(); #ifndef SHIBSP_LITE /** diff --git a/shibsp/TransactionLog.h b/shibsp/TransactionLog.h index 64ba2bc..96461c7 100644 --- a/shibsp/TransactionLog.h +++ b/shibsp/TransactionLog.h @@ -1,5 +1,5 @@ /* - * 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. @@ -26,10 +26,12 @@ #include #include #include -#include -namespace shibsp { +namespace xmltooling { + class XMLTOOL_API Mutex; +}; +namespace shibsp { /** * Interface to a synchronized logging object. * @@ -39,22 +41,13 @@ namespace shibsp { { 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; diff --git a/shibsp/attribute/Attribute.cpp b/shibsp/attribute/Attribute.cpp index 36c32bc..8b99f45 100644 --- a/shibsp/attribute/Attribute.cpp +++ b/shibsp/attribute/Attribute.cpp @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "exceptions.h" #include "SPConfig.h" #ifndef SHIBSP_LITE # include "attribute/AttributeDecoder.h" @@ -32,34 +33,19 @@ #include "attribute/XMLAttribute.h" #include "util/SPConstants.h" -#include #include +#include 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::Factory StringAttributeDecoderFactory; @@ -79,6 +65,7 @@ namespace shibsp { 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 }; @@ -104,7 +91,8 @@ void shibsp::registerAttributeDecoders() 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); @@ -116,6 +104,36 @@ AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), 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 simple(new SimpleAttribute(attr->getAliases())); + simple->setCaseSensitive(false); + simple->setInternal(m_internal); + vector& newdest = simple->getValues(); + const vector& serialized = attr->getSerializedValues(); + for (vector::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() @@ -130,6 +148,25 @@ void shibsp::registerAttributeFactories() map 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& 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(); @@ -147,6 +184,71 @@ Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()) } } +Attribute::~Attribute() +{ +} + +const char* Attribute::getId() const +{ + return m_id.front().c_str(); +} + +const vector& Attribute::getAliases() const +{ + return m_id; +} + +vector& 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& 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); @@ -173,27 +275,3 @@ Attribute* Attribute::unmarshall(DDF& in) throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name())); return (i->second)(in); } - -const vector& XMLAttribute::getSerializedValues() const -{ - xsecsize_t len; - XMLByte *pos, *pos2; - if (m_serialized.empty()) { - for (vector::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) { - XMLByte* enc = Base64::encode(reinterpret_cast(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(enc)); -#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE - XMLString::release(&enc); -#else - XMLString::release((char**)&enc); -#endif - } - } - } - return Attribute::getSerializedValues(); -} diff --git a/shibsp/attribute/Attribute.h b/shibsp/attribute/Attribute.h index 37e1d39..39dae79 100644 --- a/shibsp/attribute/Attribute.h +++ b/shibsp/attribute/Attribute.h @@ -23,7 +23,6 @@ #ifndef __shibsp_attribute_h__ #define __shibsp_attribute_h__ -#include #include #include @@ -59,8 +58,7 @@ namespace shibsp { * * @param ids array with primary identifier in first position, followed by any aliases */ - Attribute(const std::vector& ids) : m_id(ids), m_caseSensitive(true), m_internal(false) { - } + Attribute(const std::vector& ids); /** * Constructs based on a remoted Attribute. @@ -81,88 +79,70 @@ namespace shibsp { mutable std::vector 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& getAliases() const { - return m_id; - } + const std::vector& 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& getAliases() { - return m_id; - } + std::vector& 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 NOT 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 NOT 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& getSerializedValues() const { - return m_serialized; - } + virtual const std::vector& getSerializedValues() const; /** * Informs the Attribute that values have changed and any serializations @@ -176,9 +156,7 @@ namespace shibsp { * @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). @@ -186,19 +164,14 @@ namespace shibsp { * @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. @@ -227,25 +200,19 @@ namespace shibsp { * @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 m_factoryMap; diff --git a/shibsp/attribute/AttributeDecoder.h b/shibsp/attribute/AttributeDecoder.h index 5b0ad48..a4ffd04 100644 --- a/shibsp/attribute/AttributeDecoder.h +++ b/shibsp/attribute/AttributeDecoder.h @@ -23,11 +23,20 @@ #ifndef __shibsp_attrdecoder_h__ #define __shibsp_attrdecoder_h__ -#include -#include +#include + +#include +#include + +namespace xmltooling { + class XMLTOOL_API QName; + class XMLTOOL_API XMLObject; +}; namespace shibsp { + class SHIBSP_API Attribute; + /** * Decodes XML objects into resolved Attributes. */ @@ -48,20 +57,19 @@ namespace shibsp { /** 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. diff --git a/shibsp/attribute/DOMAttributeDecoder.cpp b/shibsp/attribute/DOMAttributeDecoder.cpp index 98cb87c..d996be3 100644 --- a/shibsp/attribute/DOMAttributeDecoder.cpp +++ b/shibsp/attribute/DOMAttributeDecoder.cpp @@ -1,226 +1,226 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * DOMAttributeDecoder.cpp - * - * Decodes a DOM into an ExtensibleAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/ExtensibleAttribute.h" - -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder - { - public: - DOMAttributeDecoder(const DOMElement* e); - ~DOMAttributeDecoder() {} - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - DDF convert(DOMElement* e, bool nameit=true) const; - auto_ptr_char m_formatter; - map,string> m_tagMap; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e) - { - return new DOMAttributeDecoder(e); - } - - static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g); - static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m); - static const XMLCh _to[] = UNICODE_LITERAL_2(t,o); - static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); -}; - -DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e) - : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); - - e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL; - while (e) { - if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) { - auto_ptr f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from))); - auto_ptr_char t(e->getAttributeNS(NULL, _to)); - if (f.get() && t.get() && *t.get()) { - if (log.isDebugEnabled()) - log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get()); - m_tagMap.insert( - pair< const pair,string>( - pair(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull), - t.get() - ) - ); - } - } - e = XMLHelper::getNextSiblingElement(e, Mapping); - } -} - -Attribute* DOMAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); - - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); - return NULL; - } - - auto_ptr attr(new ExtensibleAttribute(ids, m_formatter.get())); - DDF dest = attr->getValues(); - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - DOMElement* e = (*v)->getDOM(); - if (e) { - DDF converted = convert(e, false); - if (!converted.isnull()) - dest.add(converted); - } - else - log.warn("skipping AttributeValue without a backing DOM"); - } - - return dest.integer() ? _decode(attr.release()) : NULL; -} - -DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const -{ - const XMLCh* nsURI; - const XMLCh* local; - map,string>::const_iterator mapping; - DDF obj = DDF(NULL).structure(); - - if (nameit) { - // Name this structure. - nsURI = e->getNamespaceURI(); - local = e->getLocalName(); - mapping = m_tagMap.find(pair(local,nsURI)); - if (mapping == m_tagMap.end()) { - auto_ptr_char temp(local); - obj.name(temp.get()); - } - else { - obj.name(mapping->second.c_str()); - } - } - - // Process non-xmlns attributes. - DOMNamedNodeMap* attrs = e->getAttributes(); - for (XMLSize_t a = attrs->getLength(); a > 0; --a) { - DOMNode* attr = attrs->item(a-1); - nsURI = attr->getNamespaceURI(); - if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS)) - continue; - local = attr->getLocalName(); - mapping = m_tagMap.find(pair(local, nsURI ? nsURI : &chNull)); - if (mapping == m_tagMap.end()) { - auto_ptr_char temp(local); - obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false); - } - else { - obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false); - } - } - - DOMElement* child = XMLHelper::getFirstChildElement(e); - if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) { - // Attach a _text member if a text node is present. - obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false); - } - else { - while (child) { - // Convert the child element. - DDF converted = convert(child); - if (!converted.isnull()) { - // Now identify it and attach it. - if (obj[converted.name()].isnull()) { - // We're a new child, so just attach as a structure member. - obj.add(converted); - } - else if (obj[converted.name()].islist()) { - // We're already a repeating child, so add it to the list. - obj[converted.name()].add(converted); - } - else if (obj[converted.name()].isstruct()) { - // This is the complex case where we see a child for the second - // time and have to convert a structure member into a named list. - DDF newlist = DDF(converted.name()).list(); - newlist.add(obj[converted.name()].remove()); - newlist.add(converted); - obj.add(newlist); - } - } - child = XMLHelper::getNextSiblingElement(child); - } - } - - // If we're empty, just delete. - if (obj.integer() == 0) - obj.destroy(); - return obj; -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * DOMAttributeDecoder.cpp + * + * Decodes a DOM into an ExtensibleAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/ExtensibleAttribute.h" + +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder + { + public: + DOMAttributeDecoder(const DOMElement* e); + ~DOMAttributeDecoder() {} + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + DDF convert(DOMElement* e, bool nameit=true) const; + auto_ptr_char m_formatter; + map,string> m_tagMap; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e) + { + return new DOMAttributeDecoder(e); + } + + static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g); + static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m); + static const XMLCh _to[] = UNICODE_LITERAL_2(t,o); + static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); +}; + +DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e) + : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); + + e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL; + while (e) { + if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) { + auto_ptr f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from))); + auto_ptr_char t(e->getAttributeNS(NULL, _to)); + if (f.get() && t.get() && *t.get()) { + if (log.isDebugEnabled()) + log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get()); + m_tagMap.insert( + pair< const pair,string>( + pair(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull), + t.get() + ) + ); + } + } + e = XMLHelper::getNextSiblingElement(e, Mapping); + } +} + +Attribute* DOMAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); + + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); + return NULL; + } + + auto_ptr attr(new ExtensibleAttribute(ids, m_formatter.get())); + DDF dest = attr->getValues(); + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + DOMElement* e = (*v)->getDOM(); + if (e) { + DDF converted = convert(e, false); + if (!converted.isnull()) + dest.add(converted); + } + else + log.warn("skipping AttributeValue without a backing DOM"); + } + + return dest.integer() ? _decode(attr.release()) : NULL; +} + +DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const +{ + const XMLCh* nsURI; + const XMLCh* local; + map,string>::const_iterator mapping; + DDF obj = DDF(NULL).structure(); + + if (nameit) { + // Name this structure. + nsURI = e->getNamespaceURI(); + local = e->getLocalName(); + mapping = m_tagMap.find(pair(local,nsURI)); + if (mapping == m_tagMap.end()) { + auto_ptr_char temp(local); + obj.name(temp.get()); + } + else { + obj.name(mapping->second.c_str()); + } + } + + // Process non-xmlns attributes. + DOMNamedNodeMap* attrs = e->getAttributes(); + for (XMLSize_t a = attrs->getLength(); a > 0; --a) { + DOMNode* attr = attrs->item(a-1); + nsURI = attr->getNamespaceURI(); + if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS)) + continue; + local = attr->getLocalName(); + mapping = m_tagMap.find(pair(local, nsURI ? nsURI : &chNull)); + if (mapping == m_tagMap.end()) { + auto_ptr_char temp(local); + obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false); + } + else { + obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false); + } + } + + DOMElement* child = XMLHelper::getFirstChildElement(e); + if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) { + // Attach a _text member if a text node is present. + obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false); + } + else { + while (child) { + // Convert the child element. + DDF converted = convert(child); + if (!converted.isnull()) { + // Now identify it and attach it. + if (obj[converted.name()].isnull()) { + // We're a new child, so just attach as a structure member. + obj.add(converted); + } + else if (obj[converted.name()].islist()) { + // We're already a repeating child, so add it to the list. + obj[converted.name()].add(converted); + } + else if (obj[converted.name()].isstruct()) { + // This is the complex case where we see a child for the second + // time and have to convert a structure member into a named list. + DDF newlist = DDF(converted.name()).list(); + newlist.add(obj[converted.name()].remove()); + newlist.add(converted); + obj.add(newlist); + } + } + child = XMLHelper::getNextSiblingElement(child); + } + } + + // If we're empty, just delete. + if (obj.integer() == 0) + obj.destroy(); + return obj; +} diff --git a/shibsp/attribute/ExtensibleAttribute.cpp b/shibsp/attribute/ExtensibleAttribute.cpp index 5602c55..cede806 100644 --- a/shibsp/attribute/ExtensibleAttribute.cpp +++ b/shibsp/attribute/ExtensibleAttribute.cpp @@ -29,6 +29,61 @@ using namespace shibsp; using namespace xmltooling; using namespace std; +namespace shibsp { + SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) { + return new ExtensibleAttribute(in); + } +}; + +ExtensibleAttribute::ExtensibleAttribute(const vector& 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(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(vals.integer())) + vals[static_cast(index)].remove().destroy(); +} + const vector& ExtensibleAttribute::getSerializedValues() const { if (m_serialized.empty()) { @@ -77,3 +132,12 @@ const vector& ExtensibleAttribute::getSerializedValues() const } return Attribute::getSerializedValues(); } + +DDF ExtensibleAttribute::marshall() const +{ + if (!isCaseSensitive()) + m_obj.addmember("case_insensitive"); + if (isInternal()) + m_obj.addmember("internal"); + return m_obj.copy(); +} diff --git a/shibsp/attribute/ExtensibleAttribute.h b/shibsp/attribute/ExtensibleAttribute.h index 8a12836..1543288 100644 --- a/shibsp/attribute/ExtensibleAttribute.h +++ b/shibsp/attribute/ExtensibleAttribute.h @@ -24,7 +24,6 @@ #define __shibsp_extattr_h__ #include -#include namespace shibsp { @@ -45,65 +44,32 @@ 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& ids, const char* formatter) : Attribute(ids) { - m_obj = Attribute::marshall(); - m_obj.name("Extensible"); - m_obj.addmember("_formatter").string(formatter); - } + ExtensibleAttribute(const std::vector& 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(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(vals.integer())) - vals[static_cast(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& 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; diff --git a/shibsp/attribute/KeyInfoAttributeDecoder.cpp b/shibsp/attribute/KeyInfoAttributeDecoder.cpp index 3ab80f2..741d5da 100644 --- a/shibsp/attribute/KeyInfoAttributeDecoder.cpp +++ b/shibsp/attribute/KeyInfoAttributeDecoder.cpp @@ -1,157 +1,169 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * KeyInfoAttributeDecoder.cpp - * - * Decodes KeyInfo information into a SimpleAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/SimpleAttribute.h" - -#include -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmlsignature; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder - { - public: - KeyInfoAttributeDecoder(const DOMElement* e); - ~KeyInfoAttributeDecoder() { - delete m_keyInfoResolver; - } - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - void extract(const KeyInfo* k, vector& dest) const { - auto_ptr cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS)); - if (cred.get()) { - dest.push_back(string()); - dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash); - if (dest.back().empty()) - dest.pop_back(); - } - } - - const KeyInfoResolver* getKeyInfoResolver() const { - return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver(); - } - - bool m_hash; - KeyInfoResolver* m_keyInfoResolver; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e) - { - return new KeyInfoAttributeDecoder(e); - } - - static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r); - static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h); - static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); -}; - -KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) { - const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL; - m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1)); - e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL; - if (e) { - auto_ptr_char t(e->getAttributeNS(NULL, _type)); - if (t.get() && *t.get()) - m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e); - else - throw UnknownExtensionException(" element found with no type attribute"); - } -} - -Attribute* KeyInfoAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo"); - - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); - return NULL; - } - - auto_ptr attr(new SimpleAttribute(ids)); - vector& dest = attr->getValues(); - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - const KeyInfo* k = dynamic_cast(*v); - if (k) - extract(k, dest); - else if ((*v)->hasChildren()) { - const list& children = (*v)->getOrderedChildren(); - for (list::const_iterator vv = children.begin(); vv!=children.end(); ++vv) { - if (k=dynamic_cast(*vv)) - extract(k, dest); - else - log.warn("skipping AttributeValue without a recognizable KeyInfo"); - } - } - } - - return dest.empty() ? NULL : _decode(attr.release()); -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * KeyInfoAttributeDecoder.cpp + * + * Decodes KeyInfo information into a SimpleAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/SimpleAttribute.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmlsignature; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder + { + public: + KeyInfoAttributeDecoder(const DOMElement* e); + ~KeyInfoAttributeDecoder() { + delete m_keyInfoResolver; + } + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + void extract(const KeyInfo* k, vector& dest) const { + auto_ptr cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS)); + if (cred.get()) { + 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(" element found with no type attribute"); + } +} + +Attribute* KeyInfoAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo"); + + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); + return NULL; + } + + auto_ptr attr(new SimpleAttribute(ids)); + vector& dest = attr->getValues(); + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + const KeyInfo* k = dynamic_cast(*v); + if (k) + extract(k, dest); + else if ((*v)->hasChildren()) { + const list& children = (*v)->getOrderedChildren(); + for (list::const_iterator vv = children.begin(); vv!=children.end(); ++vv) { + if (k=dynamic_cast(*vv)) + extract(k, dest); + else + log.warn("skipping AttributeValue without a recognizable KeyInfo"); + } + } + } + + return dest.empty() ? NULL : _decode(attr.release()); +} diff --git a/shibsp/attribute/NameIDAttribute.cpp b/shibsp/attribute/NameIDAttribute.cpp new file mode 100644 index 0000000..978f78d --- /dev/null +++ b/shibsp/attribute/NameIDAttribute.cpp @@ -0,0 +1,153 @@ +/* + * 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 + +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& 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::getValues() +{ + return m_values; +} + +const vector& 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& NameIDAttribute::getSerializedValues() const +{ + if (m_serialized.empty()) { + for (vector::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::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; +} diff --git a/shibsp/attribute/NameIDAttribute.h b/shibsp/attribute/NameIDAttribute.h index 1b8d247..8a0aa99 100644 --- a/shibsp/attribute/NameIDAttribute.h +++ b/shibsp/attribute/NameIDAttribute.h @@ -24,7 +24,6 @@ #define __shibsp_nameidattr_h__ #include -#include namespace shibsp { @@ -48,44 +47,16 @@ 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& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER) - : Attribute(ids), m_formatter(formatter) { - } + NameIDAttribute(const std::vector& 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. @@ -104,81 +75,23 @@ namespace shibsp { * * @return a mutable vector of the values */ - std::vector& getValues() { - return m_values; - } + std::vector& getValues(); /** * Returns the set of values encoded as UTF-8 strings. * * @return an immutable vector of the values */ - const std::vector& 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& getSerializedValues() const { - if (m_serialized.empty()) { - for (std::vector::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::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& 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& getSerializedValues() const; + DDF marshall() const; private: std::vector m_values; diff --git a/shibsp/attribute/NameIDAttributeDecoder.cpp b/shibsp/attribute/NameIDAttributeDecoder.cpp index 903bc33..82ff313 100644 --- a/shibsp/attribute/NameIDAttributeDecoder.cpp +++ b/shibsp/attribute/NameIDAttributeDecoder.cpp @@ -1,234 +1,234 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * NameIDAttributeDecoder.cpp - * - * Decodes SAML into NameIDAttributes - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/NameIDAttribute.h" - -#include -#include - -using namespace shibsp; -using namespace opensaml::saml1; -using namespace opensaml::saml2; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); - static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s); - - class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder - { - public: - NameIDAttributeDecoder(const DOMElement* e) - : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) { - const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL; - if (flag && (*flag == chLatin_t || *flag == chDigit_1)) - m_defaultQualifiers = true; - } - ~NameIDAttributeDecoder() {} - - shibsp::Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - void extract( - const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const; - void extract( - const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const; - auto_ptr_char m_formatter; - bool m_defaultQualifiers; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) - { - return new NameIDAttributeDecoder(e); - } -}; - -shibsp::Attribute* NameIDAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - auto_ptr nameid( - new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER) - ); - vector& dest = nameid->getValues(); - vector::const_iterator v,stop; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID"); - - if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { - const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - const NameIDType* n2 = dynamic_cast(*v); - if (n2) - extract(n2, dest, assertingParty, relyingParty); - else { - const NameIdentifier* n1=dynamic_cast(*v); - if (n1) - extract(n1, dest, assertingParty, relyingParty); - else if ((*v)->hasChildren()) { - const list& values = (*v)->getOrderedChildren(); - for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { - if (n2=dynamic_cast(*vv)) - extract(n2, dest, assertingParty, relyingParty); - else if (n1=dynamic_cast(*vv)) - extract(n1, dest, assertingParty, relyingParty); - else - log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier"); - } - } - } - } - - return dest.empty() ? NULL : _decode(nameid.release()); - } - - const NameIDType* saml2name = dynamic_cast(xmlObject); - if (saml2name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml2name->getFormat()); - log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); - } - extract(saml2name, dest, assertingParty, relyingParty); - } - else { - const NameIdentifier* saml1name = dynamic_cast(xmlObject); - if (saml1name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml1name->getFormat()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", - ids.front().c_str(), f.get() ? f.get() : "unspecified" - ); - } - extract(saml1name, dest, assertingParty, relyingParty); - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - return dest.empty() ? NULL : _decode(nameid.release()); -} - -void NameIDAttributeDecoder::extract( - const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - auto_arrayptr name(toUTF8(n->getName())); - if (name.get() && *name.get()) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name.get(); - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (m_defaultQualifiers && assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - str = toUTF8(n->getSPNameQualifier()); - if (str && *str) - val.m_SPNameQualifier = str; - else if (m_defaultQualifiers && relyingParty) - val.m_SPNameQualifier = relyingParty; - delete[] str; - - str = toUTF8(n->getSPProvidedID()); - if (str) { - val.m_SPProvidedID = str; - delete[] str; - } - } -} - -void NameIDAttributeDecoder::extract( - const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - auto_arrayptr name(toUTF8(n->getName())); - if (name.get() && *name.get()) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name.get(); - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (m_defaultQualifiers && assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - if (m_defaultQualifiers && relyingParty) - val.m_SPNameQualifier = relyingParty; - } -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * NameIDAttributeDecoder.cpp + * + * Decodes SAML into NameIDAttributes + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/NameIDAttribute.h" + +#include +#include + +using namespace shibsp; +using namespace opensaml::saml1; +using namespace opensaml::saml2; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); + static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s); + + class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder + { + public: + NameIDAttributeDecoder(const DOMElement* e) + : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) { + const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL; + if (flag && (*flag == chLatin_t || *flag == chDigit_1)) + m_defaultQualifiers = true; + } + ~NameIDAttributeDecoder() {} + + shibsp::Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + void extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + void extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + auto_ptr_char m_formatter; + bool m_defaultQualifiers; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) + { + return new NameIDAttributeDecoder(e); + } +}; + +shibsp::Attribute* NameIDAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + auto_ptr nameid( + new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER) + ); + vector& dest = nameid->getValues(); + vector::const_iterator v,stop; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID"); + + if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { + const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + const NameIDType* n2 = dynamic_cast(*v); + if (n2) + extract(n2, dest, assertingParty, relyingParty); + else { + const NameIdentifier* n1=dynamic_cast(*v); + if (n1) + extract(n1, dest, assertingParty, relyingParty); + else if ((*v)->hasChildren()) { + const list& values = (*v)->getOrderedChildren(); + for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { + if (n2=dynamic_cast(*vv)) + extract(n2, dest, assertingParty, relyingParty); + else if (n1=dynamic_cast(*vv)) + extract(n1, dest, assertingParty, relyingParty); + else + log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier"); + } + } + } + } + + return dest.empty() ? NULL : _decode(nameid.release()); + } + + const NameIDType* saml2name = dynamic_cast(xmlObject); + if (saml2name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml2name->getFormat()); + log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); + } + extract(saml2name, dest, assertingParty, relyingParty); + } + else { + const NameIdentifier* saml1name = dynamic_cast(xmlObject); + if (saml1name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml1name->getFormat()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", + ids.front().c_str(), f.get() ? f.get() : "unspecified" + ); + } + extract(saml1name, dest, assertingParty, relyingParty); + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return NULL; + } + } + + return dest.empty() ? NULL : _decode(nameid.release()); +} + +void NameIDAttributeDecoder::extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + char* str = toUTF8(n->getFormat()); + if (str) { + val.m_Format = str; + delete[] str; + } + + str = toUTF8(n->getNameQualifier()); + if (str && *str) + val.m_NameQualifier = str; + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + delete[] str; + + str = toUTF8(n->getSPNameQualifier()); + if (str && *str) + val.m_SPNameQualifier = str; + else if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + delete[] str; + + str = toUTF8(n->getSPProvidedID()); + if (str) { + val.m_SPProvidedID = str; + delete[] str; + } + } +} + +void NameIDAttributeDecoder::extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + char* str = toUTF8(n->getFormat()); + if (str) { + val.m_Format = str; + delete[] str; + } + + str = toUTF8(n->getNameQualifier()); + if (str && *str) + val.m_NameQualifier = str; + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + delete[] str; + + if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + } +} diff --git a/shibsp/attribute/ScopedAttribute.cpp b/shibsp/attribute/ScopedAttribute.cpp new file mode 100644 index 0000000..567d8cf --- /dev/null +++ b/shibsp/attribute/ScopedAttribute.cpp @@ -0,0 +1,113 @@ +/* + * 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& 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(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 >& ScopedAttribute::getValues() +{ + return m_values; +} + +const vector< pair >& 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& ScopedAttribute::getSerializedValues() const +{ + if (m_serialized.empty()) { + for (vector< pair >::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 >::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; +} diff --git a/shibsp/attribute/ScopedAttribute.h b/shibsp/attribute/ScopedAttribute.h index a8acac5..808d6f3 100644 --- a/shibsp/attribute/ScopedAttribute.h +++ b/shibsp/attribute/ScopedAttribute.h @@ -51,27 +51,16 @@ namespace shibsp { * @param ids array with primary identifier in first position, followed by any aliases * @param delimeter value/scope delimeter when serializing */ - ScopedAttribute(const std::vector& ids, char delimeter='@') - : Attribute(ids), m_delimeter(delimeter) { - } + ScopedAttribute(const std::vector& 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(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. @@ -80,9 +69,7 @@ namespace shibsp { * * @return a mutable vector of the values */ - std::vector< std::pair >& getValues() { - return m_values; - } + std::vector< std::pair >& getValues(); /** * Returns the set of values encoded as UTF-8 strings. @@ -91,52 +78,16 @@ namespace shibsp { * * @return an immutable vector of the values */ - const std::vector< std::pair >& 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& getSerializedValues() const { - if (m_serialized.empty()) { - for (std::vector< std::pair >::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 >::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 >& 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& getSerializedValues() const; + DDF marshall() const; private: char m_delimeter; diff --git a/shibsp/attribute/ScopedAttributeDecoder.cpp b/shibsp/attribute/ScopedAttributeDecoder.cpp index c3054c8..424ee7c 100644 --- a/shibsp/attribute/ScopedAttributeDecoder.cpp +++ b/shibsp/attribute/ScopedAttributeDecoder.cpp @@ -17,7 +17,7 @@ /** * ScopedAttributeDecoder.cpp * - * Decodes SAML into ScopedAttributes + * Decodes SAML into ScopedAttributes. */ #include "internal.h" @@ -35,15 +35,15 @@ using namespace std; 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() {} @@ -53,7 +53,7 @@ namespace shibsp { ) const; private: - char m_delimeter; + char m_delimiter; }; AttributeDecoder* SHIBSP_DLLLOCAL ScopedAttributeDecoderFactory(const DOMElement* const & e) @@ -70,7 +70,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode( char* scope; const XMLCh* xmlscope; xmltooling::QName scopeqname(NULL,Scope); - auto_ptr scoped(new ScopedAttribute(ids, m_delimeter)); + auto_ptr scoped(new ScopedAttribute(ids, m_delimiter)); vector< pair >& dest = scoped->getValues(); vector::const_iterator v,stop; @@ -122,7 +122,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode( delete[] scope; } else { - scope = strchr(val, m_delimeter); + scope = strchr(val, m_delimiter); if (scope) { *scope++ = 0; if (*scope) @@ -174,8 +174,8 @@ shibsp::Attribute* ScopedAttributeDecoder::decode( } } - 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) @@ -184,7 +184,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode( 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 { diff --git a/shibsp/attribute/SimpleAttribute.cpp b/shibsp/attribute/SimpleAttribute.cpp new file mode 100644 index 0000000..11af5c8 --- /dev/null +++ b/shibsp/attribute/SimpleAttribute.cpp @@ -0,0 +1,69 @@ +/* + * 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& 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& 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::const_iterator i=m_serialized.begin(); i!=m_serialized.end(); ++i) + vlist.add(DDF(NULL).string(i->c_str())); + return ddf; +} diff --git a/shibsp/attribute/SimpleAttribute.h b/shibsp/attribute/SimpleAttribute.h index 39f869c..8402159 100644 --- a/shibsp/attribute/SimpleAttribute.h +++ b/shibsp/attribute/SimpleAttribute.h @@ -1,5 +1,5 @@ /* - * 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. @@ -38,22 +38,16 @@ namespace shibsp { * * @param ids array with primary identifier in first position, followed by any aliases */ - SimpleAttribute(const std::vector& ids) : Attribute(ids) {} + SimpleAttribute(const std::vector& 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. @@ -63,21 +57,11 @@ namespace shibsp { * * @return a mutable vector of the values */ - std::vector& getValues() { - return m_serialized; - } + std::vector& 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::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; }; }; diff --git a/shibsp/attribute/StringAttributeDecoder.cpp b/shibsp/attribute/StringAttributeDecoder.cpp index f2a9d6f..c19fc6b 100644 --- a/shibsp/attribute/StringAttributeDecoder.cpp +++ b/shibsp/attribute/StringAttributeDecoder.cpp @@ -1,148 +1,148 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * StringAttributeDecoder.cpp - * - * Decodes SAML into SimpleAttributes - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/SimpleAttribute.h" - -#include -#include - -using namespace shibsp; -using namespace opensaml::saml1; -using namespace opensaml::saml2; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder - { - public: - StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} - ~StringAttributeDecoder() {} - - shibsp::Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e) - { - return new StringAttributeDecoder(e); - } -}; - -shibsp::Attribute* StringAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - char* val; - auto_ptr simple(new SimpleAttribute(ids)); - vector& dest = simple->getValues(); - vector::const_iterator v,stop; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String"); - - if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { - const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - if (!(*v)->hasChildren()) { - val = toUTF8((*v)->getTextContent()); - if (val && *val) - dest.push_back(val); - else - log.warn("skipping empty AttributeValue"); - delete[] val; - } - else { - log.warn("skipping complex AttributeValue"); - } - } - - return dest.empty() ? NULL : _decode(simple.release()); - } - - const NameID* saml2name = dynamic_cast(xmlObject); - if (saml2name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml2name->getFormat()); - log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); - } - val = toUTF8(saml2name->getName()); - } - else { - const NameIdentifier* saml1name = dynamic_cast(xmlObject); - if (saml1name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml1name->getFormat()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", - ids.front().c_str(), f.get() ? f.get() : "unspecified" - ); - } - val = toUTF8(saml1name->getName()); - } - else { - log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); - return NULL; - } - } - - if (val && *val) - dest.push_back(val); - else - log.warn("ignoring empty NameID"); - delete[] val; - return dest.empty() ? NULL : _decode(simple.release()); -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * StringAttributeDecoder.cpp + * + * Decodes SAML into SimpleAttributes + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/SimpleAttribute.h" + +#include +#include + +using namespace shibsp; +using namespace opensaml::saml1; +using namespace opensaml::saml2; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder + { + public: + StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} + ~StringAttributeDecoder() {} + + shibsp::Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e) + { + return new StringAttributeDecoder(e); + } +}; + +shibsp::Attribute* StringAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + char* val; + auto_ptr simple(new SimpleAttribute(ids)); + vector& dest = simple->getValues(); + vector::const_iterator v,stop; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String"); + + if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { + const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + if (!(*v)->hasChildren()) { + val = toUTF8((*v)->getTextContent()); + if (val && *val) + dest.push_back(val); + else + log.warn("skipping empty AttributeValue"); + delete[] val; + } + else { + log.warn("skipping complex AttributeValue"); + } + } + + return dest.empty() ? NULL : _decode(simple.release()); + } + + const NameID* saml2name = dynamic_cast(xmlObject); + if (saml2name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml2name->getFormat()); + log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); + } + val = toUTF8(saml2name->getName()); + } + else { + const NameIdentifier* saml1name = dynamic_cast(xmlObject); + if (saml1name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml1name->getFormat()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", + ids.front().c_str(), f.get() ? f.get() : "unspecified" + ); + } + val = toUTF8(saml1name->getName()); + } + else { + log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); + return NULL; + } + } + + if (val && *val) + dest.push_back(val); + else + log.warn("ignoring empty NameID"); + delete[] val; + return dest.empty() ? NULL : _decode(simple.release()); +} diff --git a/shibsp/attribute/XMLAttribute.cpp b/shibsp/attribute/XMLAttribute.cpp new file mode 100644 index 0000000..38bc13d --- /dev/null +++ b/shibsp/attribute/XMLAttribute.cpp @@ -0,0 +1,122 @@ +/* + * 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 + +#ifndef SHIBSP_LITE +# include +#endif + +using namespace shibsp; +using namespace std; + +namespace shibsp { + SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) { + return new XMLAttribute(in); + } +}; + +XMLAttribute::XMLAttribute(const vector& 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& XMLAttribute::getValues() +{ + return m_values; +} + +const vector& 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& XMLAttribute::getSerializedValues() const +{ + xsecsize_t len; + XMLByte *pos, *pos2; + if (m_serialized.empty()) { + for (vector::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) { + XMLByte* enc = Base64::encode(reinterpret_cast(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(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::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) + vlist.add(DDF(NULL).string(i->c_str())); + return ddf; +} diff --git a/shibsp/attribute/XMLAttribute.h b/shibsp/attribute/XMLAttribute.h index 3c9a4f6..8f9f0a1 100644 --- a/shibsp/attribute/XMLAttribute.h +++ b/shibsp/attribute/XMLAttribute.h @@ -38,69 +38,38 @@ namespace shibsp { * * @param ids array with primary identifier in first position, followed by any aliases */ - XMLAttribute(const std::vector& ids) : Attribute(ids) {} + XMLAttribute(const std::vector& 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& getValues() { - return m_values; - } + std::vector& getValues(); /** * Returns the set of values encoded as XML. * * @return an immutable vector of the values */ - const std::vector& 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& 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& getSerializedValues() const; - - DDF marshall() const { - DDF ddf = Attribute::marshall(); - ddf.name("XML"); - DDF vlist = ddf.first(); - for (std::vector::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 m_values; diff --git a/shibsp/attribute/XMLAttributeDecoder.cpp b/shibsp/attribute/XMLAttributeDecoder.cpp index 2d59528..4c99938 100644 --- a/shibsp/attribute/XMLAttributeDecoder.cpp +++ b/shibsp/attribute/XMLAttributeDecoder.cpp @@ -1,138 +1,138 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * XMLAttributeDecoder.cpp - * - * Decodes arbitrary XML into an XMLAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/XMLAttribute.h" - -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder - { - public: - XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} - ~XMLAttributeDecoder() {} - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - DDF convert(DOMElement* e, bool nameit=true) const; - auto_ptr_char m_formatter; - map,string> m_tagMap; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e) - { - return new XMLAttributeDecoder(e); - } -}; - - -Attribute* XMLAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - if (!xmlObject) - return NULL; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML"); - - auto_ptr attr(new XMLAttribute(ids)); - vector& dest = attr->getValues(); - - // Handle any non-Attribute object directly. - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - DOMElement* e = xmlObject->getDOM(); - if (e) { - if (log.isDebugEnabled()) { - log.debug( - "decoding XMLAttribute (%s) from XMLObject (%s)", - ids.front().c_str(), - (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str() - ); - } - dest.push_back(string()); - XMLHelper::serialize(e, dest.back()); - } - else { - log.warn("skipping XMLObject without a backing DOM"); - } - return dest.empty() ? NULL : _decode(attr.release()); - } - - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - DOMElement* e = (*v)->getDOM(); - if (e) { - dest.push_back(string()); - XMLHelper::serialize(e, dest.back()); - } - else - log.warn("skipping AttributeValue without a backing DOM"); - } - - return dest.empty() ? NULL : _decode(attr.release()); -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * XMLAttributeDecoder.cpp + * + * Decodes arbitrary XML into an XMLAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/XMLAttribute.h" + +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder + { + public: + XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} + ~XMLAttributeDecoder() {} + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + DDF convert(DOMElement* e, bool nameit=true) const; + auto_ptr_char m_formatter; + map,string> m_tagMap; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e) + { + return new XMLAttributeDecoder(e); + } +}; + + +Attribute* XMLAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + if (!xmlObject) + return NULL; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML"); + + auto_ptr attr(new XMLAttribute(ids)); + vector& dest = attr->getValues(); + + // Handle any non-Attribute object directly. + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + DOMElement* e = xmlObject->getDOM(); + if (e) { + if (log.isDebugEnabled()) { + log.debug( + "decoding XMLAttribute (%s) from XMLObject (%s)", + ids.front().c_str(), + (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str() + ); + } + dest.push_back(string()); + XMLHelper::serialize(e, dest.back()); + } + else { + log.warn("skipping XMLObject without a backing DOM"); + } + return dest.empty() ? NULL : _decode(attr.release()); + } + + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + DOMElement* e = (*v)->getDOM(); + if (e) { + dest.push_back(string()); + XMLHelper::serialize(e, dest.back()); + } + else + log.warn("skipping AttributeValue without a backing DOM"); + } + + return dest.empty() ? NULL : _decode(attr.release()); +} diff --git a/shibsp/attribute/filtering/AttributeFilter.h b/shibsp/attribute/filtering/AttributeFilter.h index 75521a3..2a249e4 100644 --- a/shibsp/attribute/filtering/AttributeFilter.h +++ b/shibsp/attribute/filtering/AttributeFilter.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,12 +23,16 @@ #ifndef __shibsp_attrfilt_h__ #define __shibsp_attrfilt_h__ -#include +#include +#include #include namespace shibsp { + class SHIBSP_API Attribute; + class SHIBSP_API FilteringContext; + /** * Engine for filtering attribute values. */ @@ -36,9 +40,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(AttributeFilter); protected: - AttributeFilter() {} + AttributeFilter(); public: - virtual ~AttributeFilter() {} + virtual ~AttributeFilter(); /** * Filters values out of a set of attributes. diff --git a/shibsp/attribute/filtering/BasicFilteringContext.h b/shibsp/attribute/filtering/BasicFilteringContext.h index 6c66f57..888a324 100644 --- a/shibsp/attribute/filtering/BasicFilteringContext.h +++ b/shibsp/attribute/filtering/BasicFilteringContext.h @@ -1,5 +1,5 @@ /* - * 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. @@ -27,6 +27,8 @@ namespace shibsp { + class SHIBSP_API Attribute; + class SHIBSP_API BasicFilteringContext : public FilteringContext { public: @@ -45,39 +47,19 @@ namespace shibsp { 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(role->getParent())->getEntityID(); - for (std::vector::const_iterator a = attributes.begin(); a != attributes.end(); ++a) - m_attributes.insert(std::multimap::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& 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& getAttributes() const; private: const Application& m_app; diff --git a/shibsp/attribute/filtering/FilterPolicyContext.h b/shibsp/attribute/filtering/FilterPolicyContext.h index 2fff8ae..f658643 100644 --- a/shibsp/attribute/filtering/FilterPolicyContext.h +++ b/shibsp/attribute/filtering/FilterPolicyContext.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,13 +23,15 @@ #ifndef __shibsp_filtpolctx_h__ #define __shibsp_filtpolctx_h__ -#include +#include #include #include namespace shibsp { + class SHIBSP_API MatchFunctor; + /** * Context for lookup of instantiated MatchFunctor objects. */ @@ -42,10 +44,9 @@ namespace shibsp { * * @param functors reference to a map of id/functor pairs */ - FilterPolicyContext(std::multimap& functors) : m_functors(functors) { - } + FilterPolicyContext(std::multimap& functors); - virtual ~FilterPolicyContext() {} + virtual ~FilterPolicyContext(); /** * Gets a mutable map to store id/functor pairs. @@ -54,9 +55,7 @@ namespace shibsp { * * @return reference to a mutable map containing available MatchFunctors */ - std::multimap& getMatchFunctors() const { - return m_functors; - } + std::multimap& getMatchFunctors() const; private: std::multimap& m_functors; diff --git a/shibsp/attribute/filtering/FilteringContext.h b/shibsp/attribute/filtering/FilteringContext.h index c4e3032..422a725 100644 --- a/shibsp/attribute/filtering/FilteringContext.h +++ b/shibsp/attribute/filtering/FilteringContext.h @@ -1,5 +1,5 @@ /* - * 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. @@ -25,7 +25,14 @@ #include -#include +#include +#include + +namespace opensaml { + namespace saml2md { + class SAML_API RoleDescriptor; + }; +}; namespace shibsp { @@ -39,9 +46,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(FilteringContext); protected: - FilteringContext() {} + FilteringContext(); public: - virtual ~FilteringContext() {} + virtual ~FilteringContext(); /** * Gets the Application doing the filtering. diff --git a/shibsp/attribute/filtering/MatchFunctor.h b/shibsp/attribute/filtering/MatchFunctor.h index 6018414..a802d3d 100644 --- a/shibsp/attribute/filtering/MatchFunctor.h +++ b/shibsp/attribute/filtering/MatchFunctor.h @@ -1,5 +1,5 @@ /* - * 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. @@ -37,9 +37,9 @@ namespace shibsp { { 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 diff --git a/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp index 35cea2c..828071d 100644 --- a/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -23,6 +23,7 @@ #include "internal.h" #include "exceptions.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include "util/SPConstants.h" #include diff --git a/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp b/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp index a782f78..55bbd14 100644 --- a/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -22,6 +22,7 @@ #include "internal.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" using namespace shibsp; diff --git a/shibsp/attribute/filtering/impl/AttributeFilter.cpp b/shibsp/attribute/filtering/impl/AttributeFilter.cpp index ad21399..dc67e1f 100644 --- a/shibsp/attribute/filtering/impl/AttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/AttributeFilter.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -38,3 +38,11 @@ void SHIBSP_API shibsp::registerAttributeFilters() conf.AttributeFilterManager.registerFactory(XML_ATTRIBUTE_FILTER, XMLAttributeFilterFactory); conf.AttributeFilterManager.registerFactory(CHAINING_ATTRIBUTE_FILTER, ChainingAttributeFilterFactory); } + +AttributeFilter::AttributeFilter() +{ +} + +AttributeFilter::~AttributeFilter() +{ +} diff --git a/shibsp/attribute/filtering/impl/AttributeIssuerInEntityGroupFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeIssuerInEntityGroupFunctor.cpp index 6825fe3..9701023 100644 --- a/shibsp/attribute/filtering/impl/AttributeIssuerInEntityGroupFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeIssuerInEntityGroupFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,9 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" + +#include using namespace opensaml::saml2md; diff --git a/shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp index f342f61..b421a11 100644 --- a/shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include diff --git a/shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp index 563e762..e4cb12d 100644 --- a/shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" namespace shibsp { diff --git a/shibsp/attribute/filtering/impl/AttributeRequesterInEntityGroupFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeRequesterInEntityGroupFunctor.cpp index e774a7a..8c37255 100644 --- a/shibsp/attribute/filtering/impl/AttributeRequesterInEntityGroupFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeRequesterInEntityGroupFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -17,7 +17,7 @@ /** * AttributeRequesterInEntityGroupFunctor.cpp * - * A match function that evaluates to true if the attribute requester is found in metadata and is a member + * A match function that evaluates to true if the attribute requester is found in metadata and is a member * of the given entity group. */ @@ -25,6 +25,9 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" + +#include using namespace opensaml::saml2md; @@ -33,7 +36,7 @@ namespace shibsp { 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 + * 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 diff --git a/shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp index 1bbdc23..171a898 100644 --- a/shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include diff --git a/shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp index 5eecf7d..82cb30f 100644 --- a/shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" namespace shibsp { diff --git a/shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp index b7899b3..5f57d71 100644 --- a/shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,8 +25,10 @@ #include "attribute/Attribute.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include "metadata/MetadataExt.h" +#include #include using namespace opensaml::saml2md; diff --git a/shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp index c3e58e8..3b33ac1 100644 --- a/shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "attribute/Attribute.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include diff --git a/shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp index 14a1bb1..9a1cdfc 100644 --- a/shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #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; diff --git a/shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp index 5fc4fa0..ac4952b 100644 --- a/shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "attribute/Attribute.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include diff --git a/shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp b/shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp index 707f318..7721fe8 100644 --- a/shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #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; diff --git a/shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp b/shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp index b66bbbd..d7e6665 100644 --- a/shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include diff --git a/shibsp/attribute/filtering/impl/AuthenticationMethodStringFunctor.cpp b/shibsp/attribute/filtering/impl/AuthenticationMethodStringFunctor.cpp index 3c8393e..f52843a 100644 --- a/shibsp/attribute/filtering/impl/AuthenticationMethodStringFunctor.cpp +++ b/shibsp/attribute/filtering/impl/AuthenticationMethodStringFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #include "exceptions.h" #include "attribute/filtering/FilteringContext.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" namespace shibsp { diff --git a/shibsp/attribute/filtering/impl/BasicFilteringContext.cpp b/shibsp/attribute/filtering/impl/BasicFilteringContext.cpp new file mode 100644 index 0000000..67ba166 --- /dev/null +++ b/shibsp/attribute/filtering/impl/BasicFilteringContext.cpp @@ -0,0 +1,98 @@ +/* + * 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 + +using namespace shibsp; +using namespace opensaml::saml2md; +using namespace std; + +FilteringContext::FilteringContext() +{ +} + +FilteringContext::~FilteringContext() +{ +} + +BasicFilteringContext::BasicFilteringContext( + const Application& app, + const vector& 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(role->getParent())->getEntityID(); + for (vector::const_iterator a = attributes.begin(); a != attributes.end(); ++a) + m_attributes.insert(multimap::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& BasicFilteringContext::getAttributes() const +{ + return m_attributes; +} diff --git a/shibsp/attribute/filtering/impl/MatchFunctor.cpp b/shibsp/attribute/filtering/impl/MatchFunctor.cpp index 1ba0ec6..a2e7e45 100644 --- a/shibsp/attribute/filtering/impl/MatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/MatchFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "attribute/filtering/FilterPolicyContext.h" #include "attribute/filtering/MatchFunctor.h" #include "util/SPConstants.h" @@ -125,3 +126,24 @@ void SHIBSP_API shibsp::registerMatchFunctors() REGISTER_FACTORY(AttributeRequesterInEntityGroup); REGISTER_FACTORY(AttributeScopeMatchesShibMDScope); } + +MatchFunctor::MatchFunctor() +{ +} + +MatchFunctor::~MatchFunctor() +{ +} + +FilterPolicyContext::FilterPolicyContext(multimap& functors) : m_functors(functors) +{ +} + +FilterPolicyContext::~FilterPolicyContext() +{ +} + +multimap& FilterPolicyContext::getMatchFunctors() const +{ + return m_functors; +} diff --git a/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp index 9a22474..a0f07b4 100644 --- a/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -23,6 +23,7 @@ #include "internal.h" #include "exceptions.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include "util/SPConstants.h" #include diff --git a/shibsp/attribute/filtering/impl/NumberOfAttributeValuesFunctor.cpp b/shibsp/attribute/filtering/impl/NumberOfAttributeValuesFunctor.cpp index 91d1106..f1630c3 100644 --- a/shibsp/attribute/filtering/impl/NumberOfAttributeValuesFunctor.cpp +++ b/shibsp/attribute/filtering/impl/NumberOfAttributeValuesFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -26,6 +26,7 @@ #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; diff --git a/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp index 2649f42..7b260c2 100644 --- a/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -23,6 +23,7 @@ #include "internal.h" #include "exceptions.h" #include "attribute/filtering/FilterPolicyContext.h" +#include "attribute/filtering/MatchFunctor.h" #include "util/SPConstants.h" #include diff --git a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp index 32fab83..d266096 100644 --- a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -21,11 +21,14 @@ */ #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 diff --git a/shibsp/attribute/resolver/AttributeExtractor.h b/shibsp/attribute/resolver/AttributeExtractor.h index 63644ca..9e4f217 100644 --- a/shibsp/attribute/resolver/AttributeExtractor.h +++ b/shibsp/attribute/resolver/AttributeExtractor.h @@ -24,8 +24,20 @@ #define __shibsp_extractor_h__ #include + +#include +#include #include -#include + +namespace xmltooling { + class XMLTOOL_API XMLObject; +}; + +namespace opensaml { + namespace saml2md { + class SAML_API RoleDescriptor; + }; +}; namespace shibsp { @@ -39,9 +51,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(AttributeExtractor); protected: - AttributeExtractor() {} + AttributeExtractor(); public: - virtual ~AttributeExtractor() {} + virtual ~AttributeExtractor(); /** * Extracts the attributes found in an XMLObject. diff --git a/shibsp/attribute/resolver/AttributeResolver.h b/shibsp/attribute/resolver/AttributeResolver.h index 524dde8..bcf0232 100644 --- a/shibsp/attribute/resolver/AttributeResolver.h +++ b/shibsp/attribute/resolver/AttributeResolver.h @@ -25,10 +25,20 @@ #include -#include -#include +#include +#include #include +namespace opensaml { + class SAML_API Assertion; + namespace saml2 { + class SAML_API NameID; + }; + namespace saml2md { + class SAML_API EntityDescriptor; + }; +}; + namespace shibsp { class SHIBSP_API Application; @@ -48,9 +58,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(AttributeResolver); protected: - AttributeResolver() {} + AttributeResolver(); public: - virtual ~AttributeResolver() {} + virtual ~AttributeResolver(); /** * Creates a ResolutionContext based on session bootstrap material. diff --git a/shibsp/attribute/resolver/ResolutionContext.h b/shibsp/attribute/resolver/ResolutionContext.h index 760246a..6eab48a 100644 --- a/shibsp/attribute/resolver/ResolutionContext.h +++ b/shibsp/attribute/resolver/ResolutionContext.h @@ -1,5 +1,5 @@ /* - * 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. @@ -25,7 +25,11 @@ #include -#include +#include + +namespace opensaml { + class SAML_API Assertion; +}; namespace shibsp { @@ -38,9 +42,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(ResolutionContext); protected: - ResolutionContext() {} + ResolutionContext(); public: - virtual ~ResolutionContext() {} + virtual ~ResolutionContext(); /** * Returns the set of Attributes resolved and added to the context. diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp index 523cdc3..d46fdff 100644 --- a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp +++ b/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp @@ -88,6 +88,14 @@ void SHIBSP_API shibsp::registerAttributeExtractors() SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory); } +AttributeExtractor::AttributeExtractor() +{ +} + +AttributeExtractor::~AttributeExtractor() +{ +} + ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e) { SPConfig& conf = SPConfig::getConfig(); diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp index d0b63f1..4dd7702 100644 --- a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp @@ -27,6 +27,7 @@ #include "attribute/resolver/AttributeResolver.h" #include "attribute/resolver/ResolutionContext.h" +#include #include #include @@ -149,6 +150,22 @@ void SHIBSP_API shibsp::registerAttributeResolvers() 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(); diff --git a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp index d44311e..f98f2a2 100644 --- a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp +++ b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp @@ -28,7 +28,10 @@ #include "util/SPConstants.h" #include +#include #include +#include +#include #include #include @@ -165,29 +168,29 @@ void DelegationExtractor::extractAttributes( val.addmember("DelegationInstant").string(temp.get()); } - auto_arrayptr 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; - } + auto_arrayptr 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; diff --git a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp index d730b35..0cb4142 100644 --- a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp +++ b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "exceptions.h" #include "Application.h" #include "attribute/AttributeDecoder.h" #include "attribute/SimpleAttribute.h" @@ -28,6 +29,8 @@ #include #include +#include +#include #include #include #include @@ -72,6 +75,7 @@ namespace shibsp { } private: + auto_ptr_char m_hashAlg; vector m_hashId; vector m_signingId; vector m_encryptionId; @@ -88,10 +92,11 @@ namespace shibsp { 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); @@ -129,12 +134,15 @@ void KeyDescriptorExtractor::extractAttributes( 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 attr(new SimpleAttribute(m_hashId)); vector& vals = attr->getValues(); for (vector::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(); diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp index ceff508..2c9c8fc 100644 --- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp @@ -32,16 +32,17 @@ #include "attribute/resolver/ResolutionContext.h" #include "binding/SOAPClient.h" #include "metadata/MetadataProviderCriteria.h" +#include "security/SecurityPolicy.h" #include "util/SPConstants.h" #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -239,7 +240,7 @@ QueryResolver::QueryResolver(const DOMElement* e) : m_log(Category::getInstance( 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 obj(AttributeDesignatorBuilder::buildOneFromElement(child)); AttributeDesignator* down = dynamic_cast(obj.get()); if (down) { diff --git a/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp b/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp index abd1cad..c4d3336 100644 --- a/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp +++ b/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "exceptions.h" #include "Application.h" #include "ServiceProvider.h" #include "SessionCache.h" @@ -32,14 +33,18 @@ #include "attribute/resolver/ResolutionContext.h" #include "binding/SOAPClient.h" #include "metadata/MetadataProviderCriteria.h" +#include "security/SecurityPolicy.h" #include "util/SPConstants.h" #include #include -#include #include #include +#include +#include #include +#include +#include #include #include #include diff --git a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp index c27df80..e77133a 100644 --- a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp +++ b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp @@ -21,22 +21,29 @@ */ #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 #include #include +#include #include #include +#include +#include #include #include +#include #include #include diff --git a/shibsp/binding/ArtifactResolver.h b/shibsp/binding/ArtifactResolver.h index 7f89680..95427f6 100644 --- a/shibsp/binding/ArtifactResolver.h +++ b/shibsp/binding/ArtifactResolver.h @@ -1,5 +1,5 @@ /* - * 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. @@ -33,8 +33,8 @@ namespace shibsp { */ class SHIBSP_API ArtifactResolver : public opensaml::MessageDecoder::ArtifactResolver { public: - ArtifactResolver() {} - virtual ~ArtifactResolver() {} + ArtifactResolver(); + virtual ~ArtifactResolver(); opensaml::saml1p::Response* resolve( const std::vector& artifacts, diff --git a/shibsp/binding/SOAPClient.h b/shibsp/binding/SOAPClient.h index eedebc0..f5b3ce3 100644 --- a/shibsp/binding/SOAPClient.h +++ b/shibsp/binding/SOAPClient.h @@ -23,13 +23,14 @@ #ifndef __shibsp_soap11client_h__ #define __shibsp_soap11client_h__ -#include +#include + #include -#include namespace shibsp { class SHIBSP_API PropertySet; + class SHIBSP_API SecurityPolicy; /** * Specialized SOAPClient for SP environment. @@ -44,10 +45,7 @@ namespace shibsp { */ SOAPClient(SecurityPolicy& policy); - virtual ~SOAPClient() { - if (m_credResolver) - m_credResolver->unlock(); - } + virtual ~SOAPClient(); /** * Override handles message signing for SAML payloads. diff --git a/shibsp/binding/impl/ArtifactResolver.cpp b/shibsp/binding/impl/ArtifactResolver.cpp index 52e68fc..3e18aff 100644 --- a/shibsp/binding/impl/ArtifactResolver.cpp +++ b/shibsp/binding/impl/ArtifactResolver.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -22,16 +22,17 @@ #include "internal.h" #include "Application.h" -#include "exceptions.h" #include "binding/ArtifactResolver.h" #include "binding/SOAPClient.h" #include "security/SecurityPolicy.h" +#include #include #include #include #include #include +#include #include #include @@ -44,6 +45,14 @@ using namespace opensaml; using namespace xmltooling; using namespace std; +ArtifactResolver::ArtifactResolver() +{ +} + +ArtifactResolver::~ArtifactResolver() +{ +} + saml1p::Response* ArtifactResolver::resolve( const vector& artifacts, const IDPSSODescriptor& idpDescriptor, diff --git a/shibsp/binding/impl/SOAPClient.cpp b/shibsp/binding/impl/SOAPClient.cpp index cc5c6dc..e12f4f0 100644 --- a/shibsp/binding/impl/SOAPClient.cpp +++ b/shibsp/binding/impl/SOAPClient.cpp @@ -22,11 +22,16 @@ #include "internal.h" #include "Application.h" -#include "exceptions.h" #include "ServiceProvider.h" #include "binding/SOAPClient.h" +#include "security/SecurityPolicy.h" +#include #include +#include +#include +#include +#include #include #include #include @@ -42,6 +47,12 @@ SOAPClient::SOAPClient(SecurityPolicy& policy) { } +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. diff --git a/shibsp/exceptions.h b/shibsp/exceptions.h index a12e720..c56197c 100644 --- a/shibsp/exceptions.h +++ b/shibsp/exceptions.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,18 +17,14 @@ /** * @file shibsp/exceptions.h * - * Exception classes + * Exception classes. */ #ifndef __shibsp_exceptions_h__ #define __shibsp_exceptions_h__ #include -#ifndef SHIBSP_LITE -# include -#else -# include -#endif +#include namespace shibsp { diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h index 20a480b..fcc5927 100644 --- a/shibsp/handler/AbstractHandler.h +++ b/shibsp/handler/AbstractHandler.h @@ -27,14 +27,27 @@ #include #include +#include +#include +#include + #ifndef SHIBSP_LITE -# include -# include +namespace opensaml { + class SAML_API MessageEncoder; + namespace saml2md { + class SAML_API RoleDescriptor; + }; + namespace saml2p { + class SAML_API StatusResponseType; + }; +}; #endif -#include -#include -#include -#include + +namespace xmltooling { + class XMLTOOL_API HTTPRequest; + class XMLTOOL_API HTTPResponse; + class XMLTOOL_API XMLObject; +}; namespace shibsp { @@ -213,7 +226,7 @@ namespace shibsp { xmltooling::auto_ptr_char m_configNS; public: - virtual ~AbstractHandler() {} + virtual ~AbstractHandler(); private: std::pair getPostCookieNameProps(const Application& app, const char* relayState) const; diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h index 752e86c..4354e97 100644 --- a/shibsp/handler/AssertionConsumerService.h +++ b/shibsp/handler/AssertionConsumerService.h @@ -25,12 +25,22 @@ #include #include + #ifndef SHIBSP_LITE -# include -# include -# include +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 namespace shibsp { @@ -57,11 +67,19 @@ 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* remapper=NULL + ); /** * Enforce address checking requirements. @@ -154,9 +172,7 @@ namespace shibsp { ) const; public: - const char* getType() const { - return "AssertionConsumerService"; - } + const char* getType() const; #endif private: @@ -185,7 +201,6 @@ namespace shibsp { #if defined (_MSC_VER) #pragma warning( pop ) #endif - }; #endif /* __shibsp_acshandler_h__ */ diff --git a/shibsp/handler/Handler.h b/shibsp/handler/Handler.h index a73b1ff..f397e27 100644 --- a/shibsp/handler/Handler.h +++ b/shibsp/handler/Handler.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,15 +17,20 @@ /** * @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 + #ifndef SHIBSP_LITE -# include +namespace opensaml { + namespace saml2md { + class SAML_API SPSSODescriptor; + }; +}; #endif namespace shibsp { @@ -39,9 +44,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(Handler); protected: - Handler() {} + Handler(); public: - virtual ~Handler() {} + virtual ~Handler(); /** * Executes handler functionality as an incoming request. @@ -72,9 +77,7 @@ namespace shibsp { * * @return a Handler type */ - virtual const char* getType() const { - return getString("type").second; - } + virtual const char* getType() const; #endif }; diff --git a/shibsp/handler/LogoutHandler.h b/shibsp/handler/LogoutHandler.h index 7026563..7040500 100644 --- a/shibsp/handler/LogoutHandler.h +++ b/shibsp/handler/LogoutHandler.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,7 +23,6 @@ #ifndef __shibsp_logout_h__ #define __shibsp_logout_h__ -#include #include namespace shibsp { @@ -39,7 +38,7 @@ namespace shibsp { class SHIBSP_API LogoutHandler : public RemotedHandler { public: - virtual ~LogoutHandler() {} + virtual ~LogoutHandler(); /** * The base method will iteratively attempt front-channel notification @@ -69,7 +68,7 @@ namespace shibsp { 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; @@ -107,6 +106,7 @@ namespace shibsp { ) 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 @@ -122,6 +122,21 @@ namespace shibsp { 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 sendLogoutPage( + const Application& application, + const xmltooling::HTTPRequest& request, + xmltooling::HTTPResponse& response, + const char* type + ) const; }; #if defined (_MSC_VER) diff --git a/shibsp/handler/RemotedHandler.h b/shibsp/handler/RemotedHandler.h index 37c6e53..d7bdd8a 100644 --- a/shibsp/handler/RemotedHandler.h +++ b/shibsp/handler/RemotedHandler.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,10 +23,14 @@ #ifndef __shibsp_remhandler_h__ #define __shibsp_remhandler_h__ -#include #include #include +namespace xmltooling { + class XMLTOOL_API HTTPRequest; + class XMLTOOL_API HTTPResponse; +}; + namespace shibsp { /** @@ -38,7 +42,7 @@ namespace shibsp { virtual ~RemotedHandler(); protected: - RemotedHandler() {} + RemotedHandler(); /** * Establishes message remoting using the supplied address. diff --git a/shibsp/handler/SessionInitiator.h b/shibsp/handler/SessionInitiator.h index ab19446..67530d4 100644 --- a/shibsp/handler/SessionInitiator.h +++ b/shibsp/handler/SessionInitiator.h @@ -1,5 +1,5 @@ /* - * 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. @@ -35,11 +35,15 @@ namespace shibsp { */ class SHIBSP_API SessionInitiator : public virtual Handler { + friend void SHIBSP_API registerSessionInitiators(); protected: - SessionInitiator() {} + /** Property remapper for configuration compatibility. */ + static std::map m_remapper; + + SessionInitiator(); public: - virtual ~SessionInitiator() {} + virtual ~SessionInitiator(); /** * Executes an incoming request. @@ -57,9 +61,7 @@ namespace shibsp { std::pair run(SPRequest& request, bool isHandler=true) const; #ifndef SHIBSP_LITE - const char* getType() const { - return "SessionInitiator"; - } + const char* getType() const; #endif }; diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp index e42ef5b..ca7e3c2 100644 --- a/shibsp/handler/impl/AbstractHandler.cpp +++ b/shibsp/handler/impl/AbstractHandler.cpp @@ -1,654 +1,676 @@ -/* - * 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 -#include -#include -#include -#include - - -#ifndef SHIBSP_LITE -# include -# include -# include -# include -# include -# include -# include -# include -using namespace opensaml::saml2md; -#else -# include "lite/SAMLConstants.h" -#endif - -#include -#include - -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 >::Factory SAML1ConsumerFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2ConsumerFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2ArtifactResolutionFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory ChainingLogoutInitiatorFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory LocalLogoutInitiatorFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2LogoutInitiatorFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2LogoutFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2NameIDMgmtFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory AssertionLookupFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory MetadataGeneratorFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory StatusHandlerFactory; - SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::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> 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* 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(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(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 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(role->getParent()) : NULL; - const PropertySet* relyingParty = application.getRelyingParty(entity); - pair 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 keyName = relyingParty->getString("keyName"); - pair 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 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 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 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 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 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 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 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 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& collection = respParam.m_collectionMap["PostedData"]; - DDF param = postData.first(); - while (param.isstring()) { - collection.insert(pair(param.name(), (param.string() ? param.string() : ""))); - param = postData.next(); - } - - stringstream str; - XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam); - - pair 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 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 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 plimit = props->getUnsignedInt("postLimit"); - if (!plimit.first) - plimit.second = 1024 * 1024; - if (plimit.second == 0 || request.getContentLength() <= plimit.second) { - CGIParser cgi(request); - pair 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(); -} +/* + * 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 "exceptions.h" +#include "Application.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 +#include +#include +#include +#include + + +#ifndef SHIBSP_LITE +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +using namespace opensaml::saml2md; +using namespace opensaml; +#else +# include "lite/SAMLConstants.h" +#endif + +#include +#include + +using namespace shibsp; +using namespace samlconstants; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +namespace shibsp { + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML1ConsumerFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2ConsumerFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2ArtifactResolutionFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory ChainingLogoutInitiatorFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory LocalLogoutInitiatorFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2LogoutInitiatorFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2LogoutFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory SAML2NameIDMgmtFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory AssertionLookupFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory MetadataGeneratorFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::Factory StatusHandlerFactory; + SHIBSP_DLLLOCAL PluginManager< Handler,string,pair >::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> 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); +} + +Handler::Handler() +{ +} + +Handler::~Handler() +{ +} + +AbstractHandler::AbstractHandler( + const DOMElement* e, Category& log, DOMNodeFilter* filter, const map* remapper + ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) { + load(e,NULL,filter,remapper); +} + +AbstractHandler::~AbstractHandler() +{ +} + +#ifndef SHIBSP_LITE + +const char* Handler::getType() const +{ + return getString("type").second; +} + +void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleDescriptor* role) const +{ + const saml2p::StatusResponseType* r2 = dynamic_cast(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(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 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(role->getParent()) : NULL; + const PropertySet* relyingParty = application.getRelyingParty(entity); + pair 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 keyName = relyingParty->getString("keyName"); + pair 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 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 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 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 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 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 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 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 +{ + HTTPResponse::sanitizeURL(url); + + const PropertySet* props=application.getPropertySet("Sessions"); + pair 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& collection = respParam.m_collectionMap["PostedData"]; + DDF param = postData.first(); + while (!param.isnull()) { + collection.insert(pair(param.name(), (param.string() ? param.string() : ""))); + param = postData.next(); + } + + stringstream str; + XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam); + + pair 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 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 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 plimit = props->getUnsignedInt("postLimit"); + if (!plimit.first) + plimit.second = 1024 * 1024; + if (plimit.second == 0 || request.getContentLength() <= plimit.second) { + CGIParser cgi(request); + pair params = cgi.getParameters(NULL); + if (params.first == params.second) + return DDF("parameters").list(); + 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(); +} diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp index 52f747b..f88ba99 100644 --- a/shibsp/handler/impl/AssertionConsumerService.cpp +++ b/shibsp/handler/impl/AssertionConsumerService.cpp @@ -21,9 +21,10 @@ */ #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" @@ -37,8 +38,10 @@ # include "attribute/resolver/ResolutionContext.h" # include "metadata/MetadataProviderCriteria.h" # include "security/SecurityPolicy.h" +# include # include # include +# include # include using namespace samlconstants; using opensaml::saml2md::MetadataProvider; @@ -56,8 +59,9 @@ using namespace opensaml; 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* remapper + ) : AbstractHandler(e, log, filter, remapper) #ifndef SHIBSP_LITE ,m_decoder(NULL), m_role(samlconstants::SAML20MD_NS, opensaml::saml2md::IDPSSODescriptor::LOCAL_NAME) #endif @@ -223,6 +227,11 @@ void AssertionConsumerService::checkAddress(const Application& application, cons #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; diff --git a/shibsp/handler/impl/AssertionLookup.cpp b/shibsp/handler/impl/AssertionLookup.cpp index adeb711..d842763 100644 --- a/shibsp/handler/impl/AssertionLookup.cpp +++ b/shibsp/handler/impl/AssertionLookup.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -21,17 +21,24 @@ */ #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 +# include +# include +using namespace opensaml; +#endif + using namespace shibspconstants; using namespace shibsp; -using namespace opensaml; using namespace xmltooling; using namespace std; diff --git a/shibsp/handler/impl/LocalLogoutInitiator.cpp b/shibsp/handler/impl/LocalLogoutInitiator.cpp index 6850bec..47345c7 100644 --- a/shibsp/handler/impl/LocalLogoutInitiator.cpp +++ b/shibsp/handler/impl/LocalLogoutInitiator.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #include "Application.h" #include "ServiceProvider.h" #include "SessionCache.h" +#include "SPRequest.h" #include "handler/AbstractHandler.h" #include "handler/LogoutHandler.h" @@ -102,16 +103,15 @@ pair LocalLogoutInitiator::run(SPRequest& request, bool isHandler) co if (!session_id.empty()) { // Do back channel notification. vector 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"); } diff --git a/shibsp/handler/impl/LogoutHandler.cpp b/shibsp/handler/impl/LogoutHandler.cpp index dfa43ed..5d6b087 100644 --- a/shibsp/handler/impl/LogoutHandler.cpp +++ b/shibsp/handler/impl/LogoutHandler.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,6 +25,7 @@ #include "Application.h" #include "ServiceProvider.h" #include "SessionCache.h" +#include "SPRequest.h" #include "handler/LogoutHandler.h" #include "util/TemplateParameters.h" @@ -37,33 +38,46 @@ using namespace shibsp; using namespace xmltooling; using namespace std; +LogoutHandler::LogoutHandler() : m_initiator(true) +{ +} + +LogoutHandler::~LogoutHandler() +{ +} + pair 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 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 prop = props ? props->getString(local ? "localLogout" : "globalLogout") : pair(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 prop = props ? props->getString(tname.c_str()) : pair(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 LogoutHandler::run(SPRequest& request, bool isHandler) const diff --git a/shibsp/handler/impl/MetadataGenerator.cpp b/shibsp/handler/impl/MetadataGenerator.cpp index 2a847cb..c89e8ce 100644 --- a/shibsp/handler/impl/MetadataGenerator.cpp +++ b/shibsp/handler/impl/MetadataGenerator.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,16 +24,27 @@ #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 +# include +# include +# include +# include +# include +# include +# include +# include +# include # include +# include +# include #endif -#include -#include using namespace shibsp; #ifndef SHIBSP_LITE @@ -250,6 +261,9 @@ pair MetadataGenerator::processMessage( entity = EntityDescriptorBuilder::buildEntityDescriptor(); } + if (!entity->getID()) + entity->setID(SAMLConfig::getConfig().generateIdentifier()); + auto_ptr wrapper(entity); pair cache = getUnsignedInt("cacheDuration"); if (cache.first) { diff --git a/shibsp/handler/impl/RemotedHandler.cpp b/shibsp/handler/impl/RemotedHandler.cpp index 2ee35a1..93f21df 100644 --- a/shibsp/handler/impl/RemotedHandler.cpp +++ b/shibsp/handler/impl/RemotedHandler.cpp @@ -24,6 +24,7 @@ #include "Application.h" #include "exceptions.h" #include "ServiceProvider.h" +#include "SPRequest.h" #include "handler/RemotedHandler.h" #include @@ -227,6 +228,10 @@ void RemotedHandler::setAddress(const char* address) } } +RemotedHandler::RemotedHandler() +{ +} + RemotedHandler::~RemotedHandler() { SPConfig& conf = SPConfig::getConfig(); diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp index 239d7d2..88ab9c0 100644 --- a/shibsp/handler/impl/SAML1Consumer.cpp +++ b/shibsp/handler/impl/SAML1Consumer.cpp @@ -24,15 +24,19 @@ #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 # include +# include +# include # include # include # include +# include +# include using namespace opensaml::saml1; using namespace opensaml::saml1p; using namespace opensaml; diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp index 6b98392..6e609a3 100644 --- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp +++ b/shibsp/handler/impl/SAML2ArtifactResolution.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -21,15 +21,17 @@ */ #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 # include # include # include @@ -41,6 +43,7 @@ using namespace opensaml::saml2md; using namespace opensaml::saml2p; using namespace opensaml::saml2; +using namespace opensaml; using namespace samlconstants; #endif @@ -48,7 +51,6 @@ using namespace samlconstants; using namespace shibspconstants; using namespace shibsp; -using namespace opensaml; using namespace soap11; using namespace xmltooling; using namespace std; diff --git a/shibsp/handler/impl/SAML2Consumer.cpp b/shibsp/handler/impl/SAML2Consumer.cpp index 532c0ac..1c7af13 100644 --- a/shibsp/handler/impl/SAML2Consumer.cpp +++ b/shibsp/handler/impl/SAML2Consumer.cpp @@ -24,16 +24,20 @@ #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 # include +# include # include # include # include # include +# include +# include +# include using namespace opensaml::saml2; using namespace opensaml::saml2p; using namespace opensaml::saml2md; diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp index 9a2e71a..d6931ce 100644 --- a/shibsp/handler/impl/SAML2Logout.cpp +++ b/shibsp/handler/impl/SAML2Logout.cpp @@ -24,6 +24,7 @@ #include "exceptions.h" #include "Application.h" #include "ServiceProvider.h" +#include "SPRequest.h" #include "handler/AbstractHandler.h" #include "handler/LogoutHandler.h" #include "util/SPConstants.h" @@ -34,9 +35,11 @@ # include "metadata/MetadataProviderCriteria.h" # include "util/TemplateParameters.h" # include +# include # include # include # include +# include # include # include using namespace opensaml::saml2; @@ -531,11 +534,18 @@ pair SAML2Logout::doRequest(const Application& application, const HTT // 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."); diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp index 249eb8f..24b8bfa 100644 --- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp +++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,17 +25,24 @@ #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 # include # include # include # include +# include # include +# include +# include +# include using namespace opensaml::saml2; using namespace opensaml::saml2p; using namespace opensaml::saml2md; @@ -282,7 +289,7 @@ pair SAML2LogoutInitiator::doRequest( 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 @@ -317,7 +324,7 @@ pair SAML2LogoutInitiator::doRequest( } } 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); @@ -346,27 +353,32 @@ pair SAML2LogoutInitiator::doRequest( } } + // 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) { diff --git a/shibsp/handler/impl/SAML2NameIDMgmt.cpp b/shibsp/handler/impl/SAML2NameIDMgmt.cpp index 3af13a5..e285ebb 100644 --- a/shibsp/handler/impl/SAML2NameIDMgmt.cpp +++ b/shibsp/handler/impl/SAML2NameIDMgmt.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #include "exceptions.h" #include "Application.h" #include "ServiceProvider.h" +#include "SPRequest.h" #include "handler/AbstractHandler.h" #include "handler/RemotedHandler.h" #include "util/SPConstants.h" @@ -33,9 +34,11 @@ # include "security/SecurityPolicy.h" # include "util/TemplateParameters.h" # include +# include # include # include # include +# include # include # include using namespace opensaml::saml2; diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp index ae14e44..87a3750 100644 --- a/shibsp/handler/impl/SAML2SessionInitiator.cpp +++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp @@ -37,10 +37,12 @@ # include # include # include +# include using namespace opensaml::saml2; using namespace opensaml::saml2p; using namespace opensaml::saml2md; #else +# include "lite/SAMLConstants.h" #include #endif @@ -90,6 +92,8 @@ namespace shibsp { bool forceAuthn, const char* authnContextClassRef, const char* authnContextComparison, + const char* NameIDFormat, + const char* SPNameQualifier, string& relayState ) const; @@ -119,7 +123,7 @@ namespace shibsp { }; 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); @@ -233,8 +237,7 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, string postData; const Handler* ACS=NULL; const char* option; - pair acClass; - pair acComp; + pair acClass, acComp, nidFormat, spQual; bool isPassive=false,forceAuthn=false; const Application& app=request.getApplication(); @@ -246,7 +249,7 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, 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; @@ -289,6 +292,16 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, 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. @@ -313,6 +326,12 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, 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) @@ -328,11 +347,11 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, ACS = handlers.front(); } else { - pair index = getUnsignedInt("defaultACSIndex"); + pair 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(); @@ -345,14 +364,14 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, if (ACSbinding.first) { pair 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)); } } } @@ -397,6 +416,8 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, isPassive, forceAuthn, acClass.first ? acClass.second : NULL, acComp.first ? acComp.second : NULL, + nidFormat.first ? nidFormat.second : NULL, + spQual.first ? spQual.second : NULL, target ); } @@ -423,6 +444,8 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, isPassive, forceAuthn, acClass.first ? acClass.second : NULL, acComp.first ? acComp.second : NULL, + nidFormat.first ? nidFormat.second : NULL, + spQual.first ? spQual.second : NULL, target ); } @@ -441,6 +464,10 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, 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. @@ -531,6 +558,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out) 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()) @@ -564,6 +592,8 @@ pair SAML2SessionInitiator::doRequest( bool forceAuthn, const char* authnContextClassRef, const char* authnContextComparison, + const char* NameIDFormat, + const char* SPNameQualifier, string& relayState ) const { @@ -659,6 +689,14 @@ pair SAML2SessionInitiator::doRequest( 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) { diff --git a/shibsp/handler/impl/SAMLDSSessionInitiator.cpp b/shibsp/handler/impl/SAMLDSSessionInitiator.cpp index 5ff0878..1c0a7e3 100644 --- a/shibsp/handler/impl/SAMLDSSessionInitiator.cpp +++ b/shibsp/handler/impl/SAMLDSSessionInitiator.cpp @@ -37,6 +37,8 @@ using namespace xmltooling; using namespace std; #ifndef SHIBSP_LITE +# include +# include using namespace opensaml::saml2md; #endif @@ -122,6 +124,7 @@ pair SAMLDSSessionInitiator::run(SPRequest& request, string& entityID const char* option; bool isPassive=false; const Application& app=request.getApplication(); + pair discoveryURL = pair(true, m_url); if (isHandler) { option = request.getParameter("SAMLDS"); @@ -140,6 +143,10 @@ pair SAMLDSSessionInitiator::run(SPRequest& request, string& entityID 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. @@ -148,9 +155,12 @@ pair SAMLDSSessionInitiator::run(SPRequest& request, string& entityID target=request.getRequestURL(); pair 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()); @@ -212,7 +222,7 @@ pair SAMLDSSessionInitiator::run(SPRequest& request, string& entityID 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; diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp index acc194e..b02e7d0 100644 --- a/shibsp/handler/impl/SessionInitiator.cpp +++ b/shibsp/handler/impl/SessionInitiator.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -39,6 +39,8 @@ namespace shibsp { SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair >::Factory CookieSessionInitiatorFactory; }; +map SessionInitiator::m_remapper; + void SHIBSP_API shibsp::registerSessionInitiators() { SPConfig& conf=SPConfig::getConfig(); @@ -50,7 +52,24 @@ void SHIBSP_API shibsp::registerSessionInitiators() 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 SessionInitiator::run(SPRequest& request, bool isHandler) const { diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp index c9de163..7bdc6cd 100644 --- a/shibsp/handler/impl/Shib1SessionInitiator.cpp +++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp @@ -34,6 +34,9 @@ # include "metadata/MetadataProviderCriteria.h" # include # include +# include +#else +# include "lite/SAMLConstants.h" #endif #include #include @@ -55,7 +58,7 @@ namespace shibsp { { 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 loc = getString("Location"); if (loc.first) { @@ -124,7 +127,7 @@ pair Shib1SessionInitiator::run(SPRequest& request, string& entityID, 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"); @@ -143,11 +146,11 @@ pair Shib1SessionInitiator::run(SPRequest& request, string& entityID, // Since we're not passing by index, we need to fully compute the return URL. if (!ACS) { - pair index = getUnsignedInt("defaultACSIndex"); + pair 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(); @@ -158,13 +161,13 @@ pair Shib1SessionInitiator::run(SPRequest& request, string& entityID, if (ACSbinding.first) { pair 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)); } } diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp index b9e066d..64cca9a 100644 --- a/shibsp/handler/impl/StatusHandler.cpp +++ b/shibsp/handler/impl/StatusHandler.cpp @@ -24,6 +24,7 @@ #include "Application.h" #include "exceptions.h" #include "ServiceProvider.h" +#include "SPRequest.h" #include "handler/AbstractHandler.h" #include "handler/RemotedHandler.h" #include "util/CGIParser.h" @@ -33,6 +34,9 @@ using namespace shibsp; # include "SessionCache.h" # include "metadata/MetadataProviderCriteria.h" # include +# include +# include +# include using namespace opensaml::saml2md; using namespace opensaml; using namespace xmlsignature; diff --git a/shibsp/handler/impl/WAYFSessionInitiator.cpp b/shibsp/handler/impl/WAYFSessionInitiator.cpp index f0e075d..aeeedf1 100644 --- a/shibsp/handler/impl/WAYFSessionInitiator.cpp +++ b/shibsp/handler/impl/WAYFSessionInitiator.cpp @@ -27,6 +27,12 @@ #include "handler/AbstractHandler.h" #include "handler/SessionInitiator.h" +#ifndef SHIBSP_LITE +# include +#else +# include "lite/SAMLConstants.h" +#endif + #include #include #include @@ -47,7 +53,7 @@ namespace shibsp { { 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 url = getString("URL"); if (!url.first) throw ConfigurationException("WAYF SessionInitiator requires a URL property."); @@ -84,33 +90,39 @@ pair WAYFSessionInitiator::run(SPRequest& request, string& entityID, const char* option; const Handler* ACS=NULL; const Application& app=request.getApplication(); + pair discoveryURL = pair(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 index = getUnsignedInt("defaultACSIndex"); + pair 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(); @@ -121,17 +133,19 @@ pair WAYFSessionInitiator::run(SPRequest& request, string& entityID, if (ACSbinding.first) { pair 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()); @@ -156,7 +170,7 @@ pair WAYFSessionInitiator::run(SPRequest& request, string& entityID, 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); diff --git a/shibsp/impl/ChainingAccessControl.cpp b/shibsp/impl/ChainingAccessControl.cpp index 8b73906..6feafda 100644 --- a/shibsp/impl/ChainingAccessControl.cpp +++ b/shibsp/impl/ChainingAccessControl.cpp @@ -1,136 +1,146 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * ChainingAccessControl.cpp - * - * Access control plugin that combines other plugins. - */ - -#include "internal.h" -#include "exceptions.h" -#include "AccessControl.h" -#include "SessionCache.h" -#include "SPRequest.h" - -#include -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - - class ChainingAccessControl : public AccessControl - { - public: - ChainingAccessControl(const DOMElement* e); - - ~ChainingAccessControl() { - for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); - } - - Lockable* lock() { - for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::lock)); - return this; - } - void unlock() { - for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::unlock)); - } - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - enum operator_t { OP_AND, OP_OR } m_op; - vector m_ac; - }; - - AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e) - { - return new ChainingAccessControl(e); - } - - static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); - static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r); - static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); - static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); - static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); - - extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e); -} - -void SHIBSP_API shibsp::registerAccessControls() -{ - SPConfig& conf=SPConfig::getConfig(); - conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory); - conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory); - conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory); -} - -ChainingAccessControl::ChainingAccessControl(const DOMElement* e) -{ - const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL; - if (XMLString::equals(op, AND)) - m_op=OP_AND; - else if (XMLString::equals(op, OR)) - m_op=OP_OR; - else - throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration."); - - try { - e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL; - while (e) { - auto_ptr_char type(e->getAttributeNS(NULL, _type)); - if (type.get() && *type.get()) { - Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get()); - m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e)); - } - e = XMLHelper::getNextSiblingElement(e, _AccessControl); - } - } - catch (exception&) { - for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); - throw; - } - if (m_ac.empty()) - throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin."); -} - -AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const -{ - switch (m_op) { - case OP_AND: - { - for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { - if ((*i)->authorized(request, session) != shib_acl_true) - return shib_acl_false; - } - return shib_acl_true; - } - - case OP_OR: - { - for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { - if ((*i)->authorized(request,session) == shib_acl_true) - return shib_acl_true; - } - return shib_acl_false; - } - } - request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access"); - return shib_acl_false; -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * ChainingAccessControl.cpp + * + * Access control plugin that combines other plugins. + */ + +#include "internal.h" +#include "exceptions.h" +#include "AccessControl.h" +#include "SessionCache.h" +#include "SPRequest.h" + +#include +#include +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + class ChainingAccessControl : public AccessControl + { + public: + ChainingAccessControl(const DOMElement* e); + + ~ChainingAccessControl() { + for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); + } + + Lockable* lock() { + for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::lock)); + return this; + } + void unlock() { + for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::unlock)); + } + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum operator_t { OP_AND, OP_OR } m_op; + vector m_ac; + }; + + AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e) + { + return new ChainingAccessControl(e); + } + + static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); + static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r); + static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + + extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e); +} + +void SHIBSP_API shibsp::registerAccessControls() +{ + SPConfig& conf=SPConfig::getConfig(); + conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory); + conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory); + conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory); +} + +AccessControl::AccessControl() +{ +} + +AccessControl::~AccessControl() +{ +} + +ChainingAccessControl::ChainingAccessControl(const DOMElement* e) +{ + const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL; + if (XMLString::equals(op, AND)) + m_op=OP_AND; + else if (XMLString::equals(op, OR)) + m_op=OP_OR; + else + throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration."); + + try { + e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL; + while (e) { + auto_ptr_char type(e->getAttributeNS(NULL, _type)); + if (type.get() && *type.get()) { + Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get()); + m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e)); + } + e = XMLHelper::getNextSiblingElement(e, _AccessControl); + } + } + catch (exception&) { + for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); + throw; + } + if (m_ac.empty()) + throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin."); +} + +AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const +{ + switch (m_op) { + case OP_AND: + { + for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { + if ((*i)->authorized(request, session) != shib_acl_true) + return shib_acl_false; + } + return shib_acl_true; + } + + case OP_OR: + { + for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { + if ((*i)->authorized(request,session) == shib_acl_true) + return shib_acl_true; + } + return shib_acl_false; + } + } + request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access"); + return shib_acl_false; +} diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp index 27f7610..16cf5e5 100644 --- a/shibsp/impl/StorageServiceSessionCache.cpp +++ b/shibsp/impl/StorageServiceSessionCache.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -38,12 +38,22 @@ #include "remoting/ListenerService.h" #include "util/SPConstants.h" +#include +#include +#include +#include #include +#include +#include #include #include #ifndef SHIBSP_LITE +# include # include +# include +# include +# include # include using namespace opensaml::saml2md; #else @@ -352,6 +362,14 @@ void SHIBSP_API shibsp::registerSessionCaches() SPConfig::getConfig().SessionCacheManager.registerFactory(STORAGESERVICE_SESSION_CACHE, StorageServiceCacheFactory); } +Session::Session() +{ +} + +Session::~Session() +{ +} + void StoredSession::unmarshallAttributes() const { Attribute* attribute; @@ -711,6 +729,22 @@ void StoredSession::addAssertion(Assertion* assertion) #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 diff --git a/shibsp/impl/XMLAccessControl.cpp b/shibsp/impl/XMLAccessControl.cpp index 5d9d352..7e08b73 100644 --- a/shibsp/impl/XMLAccessControl.cpp +++ b/shibsp/impl/XMLAccessControl.cpp @@ -1,443 +1,445 @@ -/* - * 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. - */ - -/** - * XMLAccessControl.cpp - * - * XML-based access control syntax - */ - -#include "internal.h" -#include "exceptions.h" -#include "AccessControl.h" -#include "SessionCache.h" -#include "SPRequest.h" -#include "attribute/Attribute.h" - -#include -#include -#include -#include - -#ifndef HAVE_STRCASECMP -# define strcasecmp _stricmp -#endif - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - - class Rule : public AccessControl - { - public: - Rule(const DOMElement* e); - ~Rule() {} - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - string m_alias; - vector m_vals; - }; - - class RuleRegex : public AccessControl - { - public: - RuleRegex(const DOMElement* e); - ~RuleRegex() { - delete m_re; - } - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - string m_alias; - auto_arrayptr m_exp; - RegularExpression* m_re; - }; - - class Operator : public AccessControl - { - public: - Operator(const DOMElement* e); - ~Operator(); - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - enum operator_t { OP_NOT, OP_AND, OP_OR } m_op; - vector m_operands; - }; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 ) -#endif - - class XMLAccessControl : public AccessControl, public ReloadableXMLFile - { - public: - XMLAccessControl(const DOMElement* e) - : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) { - load(); // guarantees an exception or the policy is loaded - } - - ~XMLAccessControl() { - delete m_rootAuthz; - } - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - protected: - pair load(); - - private: - AccessControl* m_rootAuthz; - }; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - - AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e) - { - return new XMLAccessControl(e); - } - - static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); - static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e); - static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i); - static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t); - static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e); - static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T); - static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); - static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); - static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e); - static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x); -} - -Rule::Rule(const DOMElement* e) -{ - auto_ptr_char req(e->getAttributeNS(NULL,require)); - if (!req.get() || !*req.get()) - throw ConfigurationException("Access control rule missing require attribute"); - m_alias=req.get(); - - auto_arrayptr vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)); - if (!vals.get()) - return; - - const XMLCh* flag = e->getAttributeNS(NULL,_list); - if (flag && (*flag == chLatin_f || *flag == chDigit_0)) { - if (*vals.get()) - m_vals.push_back(vals.get()); - return; - } - -#ifdef HAVE_STRTOK_R - char* pos=NULL; - const char* token=strtok_r(const_cast(vals.get())," ",&pos); -#else - const char* token=strtok(const_cast(vals.get())," "); -#endif - while (token) { - m_vals.push_back(token); -#ifdef HAVE_STRTOK_R - token=strtok_r(NULL," ",&pos); -#else - token=strtok(NULL," "); -#endif - } -} - -AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const -{ - // We can make this more complex later using pluggable comparison functions, - // but for now, just a straight port to the new Attribute API. - - // Map alias in rule to the attribute. - if (!session) { - request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); - return shib_acl_false; - } - - if (m_alias == "valid-user") { - if (session) { - request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); - return shib_acl_true; - } - return shib_acl_false; - } - if (m_alias == "user") { - for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { - if (*i == request.getRemoteUser()) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - else if (m_alias == "authnContextClassRef") { - const char* ref = session->getAuthnContextClassRef(); - for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { - if (!strcmp(i->c_str(),ref)) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - else if (m_alias == "authnContextDeclRef") { - const char* ref = session->getAuthnContextDeclRef(); - for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { - if (!strcmp(i->c_str(),ref)) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - - // Find the attribute(s) matching the require rule. - pair::const_iterator, multimap::const_iterator> attrs = - session->getIndexedAttributes().equal_range(m_alias); - if (attrs.first == attrs.second) { - request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); - return shib_acl_false; - } - - for (; attrs.first != attrs.second; ++attrs.first) { - bool caseSensitive = attrs.first->second->isCaseSensitive(); - - // Now we have to intersect the attribute's values against the rule's list. - const vector& vals = attrs.first->second->getSerializedValues(); - for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { - for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { - if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted"); - return shib_acl_true; - } - } - } - } - - return shib_acl_false; -} - -RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)) -{ - auto_ptr_char req(e->getAttributeNS(NULL,require)); - if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get()) - throw ConfigurationException("Access control rule missing require attribute or element content."); - m_alias=req.get(); - - const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase); - bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1)); - try { - m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get())); - } -} - -AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const -{ - // Map alias in rule to the attribute. - if (!session) { - request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); - return shib_acl_false; - } - - if (m_alias == "valid-user") { - if (session) { - request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); - return shib_acl_true; - } - return shib_acl_false; - } - - try { - if (m_alias == "user") { - if (m_re->matches(request.getRemoteUser().c_str())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - else if (m_alias == "authnContextClassRef") { - if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - else if (m_alias == "authnContextDeclRef") { - if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - - // Find the attribute(s) matching the require rule. - pair::const_iterator, multimap::const_iterator> attrs = - session->getIndexedAttributes().equal_range(m_alias); - if (attrs.first == attrs.second) { - request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); - return shib_acl_false; - } - - for (; attrs.first != attrs.second; ++attrs.first) { - // Now we have to intersect the attribute's values against the regular expression. - const vector& vals = attrs.first->second->getSerializedValues(); - for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { - if (m_re->matches(j->c_str())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - } - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get()); - } - - return shib_acl_false; -} - -Operator::Operator(const DOMElement* e) -{ - if (XMLString::equals(e->getLocalName(),NOT)) - m_op=OP_NOT; - else if (XMLString::equals(e->getLocalName(),AND)) - m_op=OP_AND; - else if (XMLString::equals(e->getLocalName(),OR)) - m_op=OP_OR; - else - throw ConfigurationException("Unrecognized operator in access control rule"); - - try { - e=XMLHelper::getFirstChildElement(e); - if (XMLString::equals(e->getLocalName(),_Rule)) - m_operands.push_back(new Rule(e)); - else if (XMLString::equals(e->getLocalName(),_RuleRegex)) - m_operands.push_back(new RuleRegex(e)); - else - m_operands.push_back(new Operator(e)); - - if (m_op==OP_NOT) - return; - - e=XMLHelper::getNextSiblingElement(e); - while (e) { - if (XMLString::equals(e->getLocalName(),_Rule)) - m_operands.push_back(new Rule(e)); - else if (XMLString::equals(e->getLocalName(),_RuleRegex)) - m_operands.push_back(new RuleRegex(e)); - else - m_operands.push_back(new Operator(e)); - e=XMLHelper::getNextSiblingElement(e); - } - } - catch (exception&) { - for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); - throw; - } -} - -Operator::~Operator() -{ - for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); -} - -AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const -{ - switch (m_op) { - case OP_NOT: - switch (m_operands.front()->authorized(request,session)) { - case shib_acl_true: - return shib_acl_false; - case shib_acl_false: - return shib_acl_true; - default: - return shib_acl_indeterminate; - } - - case OP_AND: - { - for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { - if ((*i)->authorized(request,session) != shib_acl_true) - return shib_acl_false; - } - return shib_acl_true; - } - - case OP_OR: - { - for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { - if ((*i)->authorized(request,session) == shib_acl_true) - return shib_acl_true; - } - return shib_acl_false; - } - } - request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access"); - return shib_acl_false; -} - -pair XMLAccessControl::load() -{ - // Load from source using base class. - pair raw = ReloadableXMLFile::load(); - - // If we own it, wrap it. - XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); - - // Check for AccessControl wrapper and drop a level. - if (XMLString::equals(raw.second->getLocalName(),_AccessControl)) - raw.second = XMLHelper::getFirstChildElement(raw.second); - - AccessControl* authz; - if (XMLString::equals(raw.second->getLocalName(),_Rule)) - authz=new Rule(raw.second); - else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex)) - authz=new RuleRegex(raw.second); - else - authz=new Operator(raw.second); - - delete m_rootAuthz; - m_rootAuthz = authz; - return make_pair(false,(DOMElement*)NULL); -} - -AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const -{ - return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * XMLAccessControl.cpp + * + * XML-based access control syntax + */ + +#include "internal.h" +#include "exceptions.h" +#include "AccessControl.h" +#include "SessionCache.h" +#include "SPRequest.h" +#include "attribute/Attribute.h" + +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_STRCASECMP +# define strcasecmp _stricmp +#endif + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + class Rule : public AccessControl + { + public: + Rule(const DOMElement* e); + ~Rule() {} + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + string m_alias; + vector m_vals; + }; + + class RuleRegex : public AccessControl + { + public: + RuleRegex(const DOMElement* e); + ~RuleRegex() { + delete m_re; + } + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + string m_alias; + auto_arrayptr m_exp; + RegularExpression* m_re; + }; + + class Operator : public AccessControl + { + public: + Operator(const DOMElement* e); + ~Operator(); + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum operator_t { OP_NOT, OP_AND, OP_OR } m_op; + vector m_operands; + }; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + class XMLAccessControl : public AccessControl, public ReloadableXMLFile + { + public: + XMLAccessControl(const DOMElement* e) + : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) { + load(); // guarantees an exception or the policy is loaded + } + + ~XMLAccessControl() { + delete m_rootAuthz; + } + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + protected: + pair load(); + + private: + AccessControl* m_rootAuthz; + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + + AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e) + { + return new XMLAccessControl(e); + } + + static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); + static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e); + static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i); + static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t); + static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e); + static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e); + static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x); +} + +Rule::Rule(const DOMElement* e) +{ + auto_ptr_char req(e->getAttributeNS(NULL,require)); + if (!req.get() || !*req.get()) + throw ConfigurationException("Access control rule missing require attribute"); + m_alias=req.get(); + + auto_arrayptr vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)); + if (!vals.get()) + return; + + const XMLCh* flag = e->getAttributeNS(NULL,_list); + if (flag && (*flag == chLatin_f || *flag == chDigit_0)) { + if (*vals.get()) + m_vals.push_back(vals.get()); + return; + } + +#ifdef HAVE_STRTOK_R + char* pos=NULL; + const char* token=strtok_r(const_cast(vals.get())," ",&pos); +#else + const char* token=strtok(const_cast(vals.get())," "); +#endif + while (token) { + m_vals.push_back(token); +#ifdef HAVE_STRTOK_R + token=strtok_r(NULL," ",&pos); +#else + token=strtok(NULL," "); +#endif + } +} + +AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const +{ + // We can make this more complex later using pluggable comparison functions, + // but for now, just a straight port to the new Attribute API. + + // Map alias in rule to the attribute. + if (!session) { + request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); + return shib_acl_false; + } + + if (m_alias == "valid-user") { + if (session) { + request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); + return shib_acl_true; + } + return shib_acl_false; + } + if (m_alias == "user") { + for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { + if (*i == request.getRemoteUser()) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + else if (m_alias == "authnContextClassRef") { + const char* ref = session->getAuthnContextClassRef(); + for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { + if (!strcmp(i->c_str(),ref)) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + else if (m_alias == "authnContextDeclRef") { + const char* ref = session->getAuthnContextDeclRef(); + for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { + if (!strcmp(i->c_str(),ref)) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + + // Find the attribute(s) matching the require rule. + pair::const_iterator, multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(m_alias); + if (attrs.first == attrs.second) { + request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); + return shib_acl_false; + } + + for (; attrs.first != attrs.second; ++attrs.first) { + bool caseSensitive = attrs.first->second->isCaseSensitive(); + + // Now we have to intersect the attribute's values against the rule's list. + const vector& vals = attrs.first->second->getSerializedValues(); + for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { + for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { + if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted"); + return shib_acl_true; + } + } + } + } + + return shib_acl_false; +} + +RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)) +{ + auto_ptr_char req(e->getAttributeNS(NULL,require)); + if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get()) + throw ConfigurationException("Access control rule missing require attribute or element content."); + m_alias=req.get(); + + const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase); + bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1)); + try { + m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); + } + catch (XMLException& ex) { + auto_ptr_char tmp(ex.getMessage()); + throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get())); + } +} + +AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const +{ + // Map alias in rule to the attribute. + if (!session) { + request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); + return shib_acl_false; + } + + if (m_alias == "valid-user") { + if (session) { + request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); + return shib_acl_true; + } + return shib_acl_false; + } + + try { + if (m_alias == "user") { + if (m_re->matches(request.getRemoteUser().c_str())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + else if (m_alias == "authnContextClassRef") { + if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + else if (m_alias == "authnContextDeclRef") { + if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + + // Find the attribute(s) matching the require rule. + pair::const_iterator, multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(m_alias); + if (attrs.first == attrs.second) { + request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); + return shib_acl_false; + } + + for (; attrs.first != attrs.second; ++attrs.first) { + // Now we have to intersect the attribute's values against the regular expression. + const vector& vals = attrs.first->second->getSerializedValues(); + for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { + if (m_re->matches(j->c_str())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + } + } + } + catch (XMLException& ex) { + auto_ptr_char tmp(ex.getMessage()); + request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get()); + } + + return shib_acl_false; +} + +Operator::Operator(const DOMElement* e) +{ + if (XMLString::equals(e->getLocalName(),NOT)) + m_op=OP_NOT; + else if (XMLString::equals(e->getLocalName(),AND)) + m_op=OP_AND; + else if (XMLString::equals(e->getLocalName(),OR)) + m_op=OP_OR; + else + throw ConfigurationException("Unrecognized operator in access control rule"); + + try { + e=XMLHelper::getFirstChildElement(e); + if (XMLString::equals(e->getLocalName(),_Rule)) + m_operands.push_back(new Rule(e)); + else if (XMLString::equals(e->getLocalName(),_RuleRegex)) + m_operands.push_back(new RuleRegex(e)); + else + m_operands.push_back(new Operator(e)); + + if (m_op==OP_NOT) + return; + + e=XMLHelper::getNextSiblingElement(e); + while (e) { + if (XMLString::equals(e->getLocalName(),_Rule)) + m_operands.push_back(new Rule(e)); + else if (XMLString::equals(e->getLocalName(),_RuleRegex)) + m_operands.push_back(new RuleRegex(e)); + else + m_operands.push_back(new Operator(e)); + e=XMLHelper::getNextSiblingElement(e); + } + } + catch (exception&) { + for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); + throw; + } +} + +Operator::~Operator() +{ + for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); +} + +AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const +{ + switch (m_op) { + case OP_NOT: + switch (m_operands.front()->authorized(request,session)) { + case shib_acl_true: + return shib_acl_false; + case shib_acl_false: + return shib_acl_true; + default: + return shib_acl_indeterminate; + } + + case OP_AND: + { + for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { + if ((*i)->authorized(request,session) != shib_acl_true) + return shib_acl_false; + } + return shib_acl_true; + } + + case OP_OR: + { + for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { + if ((*i)->authorized(request,session) == shib_acl_true) + return shib_acl_true; + } + return shib_acl_false; + } + } + request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access"); + return shib_acl_false; +} + +pair XMLAccessControl::load() +{ + // Load from source using base class. + pair raw = ReloadableXMLFile::load(); + + // If we own it, wrap it. + XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); + + // Check for AccessControl wrapper and drop a level. + if (XMLString::equals(raw.second->getLocalName(),_AccessControl)) + raw.second = XMLHelper::getFirstChildElement(raw.second); + + AccessControl* authz; + if (XMLString::equals(raw.second->getLocalName(),_Rule)) + authz=new Rule(raw.second); + else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex)) + authz=new RuleRegex(raw.second); + else + authz=new Operator(raw.second); + + delete m_rootAuthz; + m_rootAuthz = authz; + return make_pair(false,(DOMElement*)NULL); +} + +AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const +{ + return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false; +} diff --git a/shibsp/impl/XMLRequestMapper.cpp b/shibsp/impl/XMLRequestMapper.cpp index 78e6edf..c048e0c 100644 --- a/shibsp/impl/XMLRequestMapper.cpp +++ b/shibsp/impl/XMLRequestMapper.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -16,7 +16,7 @@ /** XMLRequestMapper.cpp * - * XML-based RequestMapper implementation + * XML-based RequestMapper implementation. */ #include "internal.h" @@ -27,6 +27,7 @@ #include "util/DOMPropertySet.h" #include "util/SPConstants.h" +#include #include #include #include @@ -162,6 +163,14 @@ void SHIBSP_API shibsp::registerRequestMappers() conf.RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER, XMLRequestMapperFactory); } +RequestMapper::RequestMapper() +{ +} + +RequestMapper::~RequestMapper() +{ +} + void Override::loadACL(const DOMElement* e, Category& log) { try { diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp index 5b9de5f..05f3ef4 100644 --- a/shibsp/impl/XMLServiceProvider.cpp +++ b/shibsp/impl/XMLServiceProvider.cpp @@ -1,1678 +1,1708 @@ -/* - * 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 -#elif defined(XMLTOOLING_LOG4CPP) -# include -#else -# error "Supported logging library not available." -#endif -#include -#include -#include -#include -#include -#include -#include - -#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 -# include -# include -# include -# include -# include -# include -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 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 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* 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& 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& getAssertionConsumerServicesByBinding(const XMLCh* binding) const; - const Handler* getHandler(const char* path) const; - void getHandlers(vector& 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 >::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 m_attributePrefix; -#ifndef SHIBSP_LITE - MetadataProvider* m_metadata; - TrustEngine* m_trust; - AttributeExtractor* m_attrExtractor; - AttributeFilter* m_attrFilter; - AttributeResolver* m_attrResolver; - CredentialResolver* m_credResolver; - vector m_audiences; - - // RelyingParty properties - map m_partyMap; -#endif - vector m_remoteUsers,m_frontLogout,m_backLogout; - - // manage handler objects - vector m_handlers; - - // maps location (path info) to applicable handlers - map m_handlerMap; - - // maps unique indexes to consumer services - map m_acsIndexMap; - - // pointer to default consumer service - const Handler* m_acsDefault; - - // maps binding strings to supporting consumer service(s) - typedef map > ACSBindingMap; - ACSBindingMap m_acsBindingMap; - - // pointer to default session initiator - const SessionInitiator* m_sessionInitDefault; - - // maps unique ID strings to session initiators - map m_sessionInitMap; - - // pointer to default artifact resolution service - const Handler* m_artifactResolutionDefault; - - pair 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 m_appmap; -#ifndef SHIBSP_LITE - map< string,pair< PropertySet*,vector > > m_policyMap; - vector< pair< string, pair > > 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()); -#endif - } - - // PropertySet - const PropertySet* getParent() const { return m_impl->getParent(); } - void setParent(const PropertySet* parent) {return m_impl->setParent(parent);} - pair getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);} - pair getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);} - pair getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);} - pair getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);} - pair getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);} - void getAll(map& 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::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::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 > >::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 element.", params(1,id)); - } - - const vector& getPolicyRules(const char* id) const { - map > >::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 element.", params(1,id)); - } - - bool setTransportOptions(SOAPTransport& transport) const { - bool ret = true; - vector< pair< string, pair > >::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 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 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 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 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(m_attributePrefix.first + start, m_attributePrefix.second + transformed)); - if (prefix.first) - m_unsetHeaders.push_back(pair(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed)); - start = pos ? pos+1 : NULL; - } - free(dup); - m_unsetHeaders.push_back(pair(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 location = sessions ? sessions->getString("exportLocation") : pair(false,NULL); - if (location.first) { - try { - DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler); - exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second); - pair 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(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 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 si_id=handler->getString("id"); - if (si_id.first && si_id.second) - m_sessionInitMap[si_id.second]=sihandler; - if (!hardSessionInit) { - pair 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 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 && igetLength(); i++) { - if (nlist->item(i)->getParentNode()->isSameNode(e)) { - const XMLCh* channel = static_cast(nlist->item(i))->getAttributeNS(NULL,Channel); - auto_ptr_char loc(static_cast(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 elements outside of a Security Policy Rule is deprecated"); - for (XMLSize_t i=0; igetLength(); 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 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 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 prefix = getString("metadataAttributePrefix"); - if (prefix.first) { - pch = prefix.second; - while (*pch) { - transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_'); - pch++; - } - } - for (vector::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(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed)); - if (prefix.first) - m_unsetHeaders.push_back(pair(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed)); - } - } - m_unsetHeaders.push_back(pair(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 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()); - m_handlers.clear(); -#ifndef SHIBSP_LITE - for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair()); - 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::const_iterator i=m_partyMap.find(provider->getEntityID()); - if (i!=m_partyMap.end()) - return i->second; - const EntitiesDescriptor* group=dynamic_cast(provider->getParent()); - while (group) { - if (group->getName()) { - i=m_partyMap.find(group->getName()); - if (i!=m_partyMap.end()) - return i->second; - } - group=dynamic_cast(group->getParent()); - } - return this; -} - -const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const -{ - if (!entityID) - return this; - - map::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& 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::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::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& 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::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& handlers) const -{ - handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end()); - if (m_base) { - for (map::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 skew=getUnsignedInt("clockSkew"); - if (skew.first) - xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28)); - - pair 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(m_outer)); - m_outer->m_listener->regListener("get::RelayState", const_cast(m_outer)); - m_outer->m_listener->regListener("set::PostData", const_cast(m_outer)); - m_outer->m_listener->regListener("get::PostData", const_cast(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 >& rules = m_policyMap[id.get()]; - rules.first = NULL; - auto_ptr 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 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()); - m_appmap.clear(); -#ifndef SHIBSP_LITE - for (map< string,pair > >::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()); - } - 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 XMLConfig::load() -{ - // Load from source using base class. - pair raw = ReloadableXMLFile::load(); - - // If we own it, wrap it. - XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); - - 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); -} +/* + * 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 +#elif defined(XMLTOOLING_LOG4CPP) +# include +#else +# error "Supported logging library not available." +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +using namespace opensaml::saml2; +using namespace opensaml::saml2p; +using namespace opensaml::saml2md; +using namespace opensaml; +#else +# include "lite/SAMLConstants.h" +#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 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 index = make_pair(false,0); + const PropertySet* props = getRelyingParty(relyingParty); + index = props->getInt("artifactEndpointIndex"); + if (!index.first) + index = getArtifactEndpointIndex(); + pair entityID = props->getString("entityID"); + return new SAML2ArtifactType0004( + SecurityHelper::doHash("SHA1", entityID.second, strlen(entityID.second), false), + 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* 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& 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& getAssertionConsumerServicesByBinding(const XMLCh* binding) const; + const Handler* getHandler(const char* path) const; + void getHandlers(vector& 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 >::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 m_attributePrefix; +#ifndef SHIBSP_LITE + MetadataProvider* m_metadata; + TrustEngine* m_trust; + AttributeExtractor* m_attrExtractor; + AttributeFilter* m_attrFilter; + AttributeResolver* m_attrResolver; + CredentialResolver* m_credResolver; + vector m_audiences; + + // RelyingParty properties + map m_partyMap; +#endif + vector m_remoteUsers,m_frontLogout,m_backLogout; + + // manage handler objects + vector m_handlers; + + // maps location (path info) to applicable handlers + map m_handlerMap; + + // maps unique indexes to consumer services + map m_acsIndexMap; + + // pointer to default consumer service + const Handler* m_acsDefault; + + // maps binding strings to supporting consumer service(s) + typedef map > ACSBindingMap; + ACSBindingMap m_acsBindingMap; + + // pointer to default session initiator + const SessionInitiator* m_sessionInitDefault; + + // maps unique ID strings to session initiators + map m_sessionInitMap; + + // pointer to default artifact resolution service + const Handler* m_artifactResolutionDefault; + + pair 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 m_appmap; +#ifndef SHIBSP_LITE + map< string,pair< PropertySet*,vector > > m_policyMap; + vector< pair< string, pair > > 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()); +#endif + } + + // PropertySet + const PropertySet* getParent() const { return m_impl->getParent(); } + void setParent(const PropertySet* parent) {return m_impl->setParent(parent);} + pair getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);} + pair getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);} + pair getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);} + pair getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);} + pair getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);} + void getAll(map& 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::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::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 > >::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 element.", params(1,id)); + } + + const vector& getPolicyRules(const char* id) const { + map > >::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 element.", params(1,id)); + } + + bool setTransportOptions(SOAPTransport& transport) const { + bool ret = true; + vector< pair< string, pair > >::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 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 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 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 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(m_attributePrefix.first + start, m_attributePrefix.second + transformed)); + if (prefix.first) + m_unsetHeaders.push_back(pair(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed)); + start = pos ? pos+1 : NULL; + } + free(dup); + m_unsetHeaders.push_back(pair(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 location = sessions ? sessions->getString("exportLocation") : pair(false,NULL); + if (location.first) { + try { + DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler); + exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second); + pair 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(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 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 si_id=handler->getString("id"); + if (si_id.first && si_id.second) + m_sessionInitMap[si_id.second]=sihandler; + if (!hardSessionInit) { + pair 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 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 && igetLength(); i++) { + if (nlist->item(i)->getParentNode()->isSameNode(e)) { + const XMLCh* channel = static_cast(nlist->item(i))->getAttributeNS(NULL,Channel); + auto_ptr_char loc(static_cast(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 elements outside of a Security Policy Rule is deprecated"); + for (XMLSize_t i=0; igetLength(); 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 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 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 prefix = getString("metadataAttributePrefix"); + if (prefix.first) { + pch = prefix.second; + while (*pch) { + transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_'); + pch++; + } + } + for (vector::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(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed)); + if (prefix.first) + m_unsetHeaders.push_back(pair(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed)); + } + } + m_unsetHeaders.push_back(pair(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 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()); + m_handlers.clear(); +#ifndef SHIBSP_LITE + for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair()); + 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::const_iterator i=m_partyMap.find(provider->getEntityID()); + if (i!=m_partyMap.end()) + return i->second; + const EntitiesDescriptor* group=dynamic_cast(provider->getParent()); + while (group) { + if (group->getName()) { + i=m_partyMap.find(group->getName()); + if (i!=m_partyMap.end()) + return i->second; + } + group=dynamic_cast(group->getParent()); + } + return this; +} + +const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const +{ + if (!entityID) + return this; + + map::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& 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::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::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& 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::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& handlers) const +{ + handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end()); + if (m_base) { + for (map::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 skew=getUnsignedInt("clockSkew"); + if (skew.first) + xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28)); + + pair unsafe = getString("unsafeChars"); + if (unsafe.first) + TemplateEngine::unsafe_chars = unsafe.second; + + unsafe = getString("allowedSchemes"); + if (unsafe.first) { + HTTPResponse::getAllowedSchemes().clear(); + string schemes=unsafe.second; + unsigned int j_sch=0; + for (unsigned int i_sch=0; i_sch < schemes.length(); i_sch++) { + if (schemes.at(i_sch)==' ') { + HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, i_sch-j_sch)); + j_sch = i_sch + 1; + } + } + HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, schemes.length()-j_sch)); + } + + // 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(m_outer)); + m_outer->m_listener->regListener("get::RelayState", const_cast(m_outer)); + m_outer->m_listener->regListener("set::PostData", const_cast(m_outer)); + m_outer->m_listener->regListener("get::PostData", const_cast(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 >& rules = m_policyMap[id.get()]; + rules.first = NULL; + auto_ptr 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 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()); + m_appmap.clear(); +#ifndef SHIBSP_LITE + for (map< string,pair > >::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()); + } + 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 XMLConfig::load() +{ + // Load from source using base class. + pair raw = ReloadableXMLFile::load(); + + // If we own it, wrap it. + XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); + + 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); +} diff --git a/shibsp/lite/CommonDomainCookie.cpp b/shibsp/lite/CommonDomainCookie.cpp index cb8ffc0..2d3eeee 100644 --- a/shibsp/lite/CommonDomainCookie.cpp +++ b/shibsp/lite/CommonDomainCookie.cpp @@ -69,6 +69,15 @@ CommonDomainCookie::CommonDomainCookie(const char* cookie) } } +CommonDomainCookie::~CommonDomainCookie() +{ +} + +const vector& CommonDomainCookie::get() const +{ + return m_list; +} + const char* CommonDomainCookie::set(const char* entityID) { // First scan the list for this IdP. diff --git a/shibsp/lite/CommonDomainCookie.h b/shibsp/lite/CommonDomainCookie.h index a15f88c..faffa46 100644 --- a/shibsp/lite/CommonDomainCookie.h +++ b/shibsp/lite/CommonDomainCookie.h @@ -1,5 +1,5 @@ /* - * 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. @@ -47,16 +47,14 @@ namespace opensaml { */ CommonDomainCookie(const char* cookie); - ~CommonDomainCookie() {} + ~CommonDomainCookie(); /** * Returns list of IdPs stored in cookie. * * @return reference to vector of entityIDs */ - const std::vector& get() const { - return m_list; - } + const std::vector& get() const; /** * Adds/moves an IdP to the front of the list. diff --git a/shibsp/lite/SAMLConstants.h b/shibsp/lite/SAMLConstants.h index f04b3f3..83b4de9 100644 --- a/shibsp/lite/SAMLConstants.h +++ b/shibsp/lite/SAMLConstants.h @@ -23,7 +23,8 @@ #ifndef __shibsp_xmlconstants_h__ #define __shibsp_xmlconstants_h__ -#include +#include +#include /** * SAML related constants. diff --git a/shibsp/metadata/DynamicMetadataProvider.cpp b/shibsp/metadata/DynamicMetadataProvider.cpp index 9e583e4..98605c1 100644 --- a/shibsp/metadata/DynamicMetadataProvider.cpp +++ b/shibsp/metadata/DynamicMetadataProvider.cpp @@ -22,26 +22,28 @@ #include "internal.h" #include "exceptions.h" +#include "Application.h" #include "ServiceProvider.h" #include "metadata/MetadataProviderCriteria.h" +#include +#include +#include #include #include #include #include - #include -#include +#include #include #include #include #include #include +#include +#include #include -#include -#include - using namespace shibsp; using namespace opensaml; using namespace xmltooling::logging; @@ -135,7 +137,7 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad name = temp.get(); } else if (criteria.artifact) { - throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact."); + throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact."); } // Establish networking properties based on calling application. diff --git a/shibsp/metadata/MetadataExt.h b/shibsp/metadata/MetadataExt.h index d0badc0..c9054c2 100644 --- a/shibsp/metadata/MetadataExt.h +++ b/shibsp/metadata/MetadataExt.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,20 +17,25 @@ /** * @file shibsp/metadata/MetadataExt.h * - * XMLObjects representing Shibboleth metadata extensions + * XMLObjects representing Shibboleth metadata extensions. */ #ifndef __shibsp_metaext_h__ #define __shibsp_metaext_h__ #include -#include -#include -#include + +#include +#include +#include #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); diff --git a/shibsp/metadata/MetadataExtImpl.cpp b/shibsp/metadata/MetadataExtImpl.cpp index 71fb17a..7ae11c2 100644 --- a/shibsp/metadata/MetadataExtImpl.cpp +++ b/shibsp/metadata/MetadataExtImpl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -29,6 +29,7 @@ #include #include #include +#include #include using namespace shibsp; diff --git a/shibsp/metadata/MetadataExtSchemaValidators.cpp b/shibsp/metadata/MetadataExtSchemaValidators.cpp index f9b4472..7841539 100644 --- a/shibsp/metadata/MetadataExtSchemaValidators.cpp +++ b/shibsp/metadata/MetadataExtSchemaValidators.cpp @@ -1,5 +1,5 @@ /* -* 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. @@ -17,7 +17,7 @@ /** * MetadataExtSchemaValidators.cpp * - * Schema-based validators for Shibboleth metadata extension classes + * Schema-based validators for Shibboleth metadata extension classes. */ #include "internal.h" @@ -26,6 +26,7 @@ #include #include +#include #include using namespace shibsp; diff --git a/shibsp/metadata/MetadataProviderCriteria.cpp b/shibsp/metadata/MetadataProviderCriteria.cpp new file mode 100644 index 0000000..55ddffd --- /dev/null +++ b/shibsp/metadata/MetadataProviderCriteria.cpp @@ -0,0 +1,55 @@ +/* + * 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() +{ +} diff --git a/shibsp/metadata/MetadataProviderCriteria.h b/shibsp/metadata/MetadataProviderCriteria.h index 286a4a0..d1a0d98 100644 --- a/shibsp/metadata/MetadataProviderCriteria.h +++ b/shibsp/metadata/MetadataProviderCriteria.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,11 +23,14 @@ #ifndef __shibsp_metaprovcrit_h__ #define __shibsp_metaprovcrit_h__ -#include +#include + #include namespace shibsp { + class SHIBSP_API Application; + /** * Extended criteria for metadata lookup for Shibboleth-aware metadata providers. */ @@ -38,8 +41,7 @@ namespace shibsp { * * @param app application performing the lookup */ - MetadataProviderCriteria(const Application& app) : application(app) { - } + MetadataProviderCriteria(const Application& app); /** * Constructor. @@ -50,9 +52,9 @@ namespace shibsp { * @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. @@ -63,9 +65,9 @@ namespace shibsp { * @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. @@ -76,11 +78,13 @@ namespace shibsp { * @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; }; }; diff --git a/shibsp/paths.h b/shibsp/paths.h index 6eb507d..2f9ac99 100644 --- a/shibsp/paths.h +++ b/shibsp/paths.h @@ -1,53 +1,53 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file shibsp/paths.h - * - * Default configuration paths. - */ - -#ifndef __shibsp_paths_h__ -#define __shibsp_paths_h__ - -/** Default schema catalogs. */ -#define SHIBSP_SCHEMAS "/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" - -/** 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__ */ +/* + * 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__ */ diff --git a/shibsp/paths.h.in b/shibsp/paths.h.in index f35df0b..abd4f71 100644 --- a/shibsp/paths.h.in +++ b/shibsp/paths.h.in @@ -1,53 +1,53 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file shibsp/paths.h - * - * Default configuration paths. - */ - -#ifndef __shibsp_paths_h__ -#define __shibsp_paths_h__ - -/** Default schema catalogs. */ -#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml" - -/** Default name of SP configuration file. */ -#define SHIBSP_CONFIG "shibboleth2.xml" - -/** Default name of SP console tool logging file. */ -#define SHIBSP_LOGGING "console.logger" - -/** Default prefix for installation (used to resolve relative paths). */ -#define SHIBSP_PREFIX "@-PREFIX-@" - -/** Library directory for installation (used to resolve relative paths). */ -#define SHIBSP_LIBDIR "@-LIBDIR-@" - -/** Log directory for installation (used to resolve relative paths). */ -#define SHIBSP_LOGDIR "@-LOGDIR-@" - -/** Configuration directory for installation (used to resolve relative paths). */ -#define SHIBSP_CFGDIR "@-SYSCONFDIR-@" - -/** Runtime state directory for installation (used to resolve relative paths). */ -#define SHIBSP_RUNDIR "@-RUNDIR-@" - -/** XML directory for installation (used to resolve relative paths). */ -#define SHIBSP_XMLDIR "@-XMLDIR-@" - -#endif /* __shibsp_paths_h__ */ +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file shibsp/paths.h + * + * Default configuration paths. + */ + +#ifndef __shibsp_paths_h__ +#define __shibsp_paths_h__ + +/** Default schema catalogs. */ +#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml" + +/** Default name of SP configuration file. */ +#define SHIBSP_CONFIG "shibboleth2.xml" + +/** Default name of SP console tool logging file. */ +#define SHIBSP_LOGGING "console.logger" + +/** Default prefix for installation (used to resolve relative paths). */ +#define SHIBSP_PREFIX "@-PREFIX-@" + +/** Library directory for installation (used to resolve relative paths). */ +#define SHIBSP_LIBDIR "@-LIBDIR-@" + +/** Log directory for installation (used to resolve relative paths). */ +#define SHIBSP_LOGDIR "@-LOGDIR-@" + +/** Configuration directory for installation (used to resolve relative paths). */ +#define SHIBSP_CFGDIR "@-SYSCONFDIR-@" + +/** Runtime state directory for installation (used to resolve relative paths). */ +#define SHIBSP_RUNDIR "@-RUNDIR-@" + +/** XML directory for installation (used to resolve relative paths). */ +#define SHIBSP_XMLDIR "@-XMLDIR-@" + +#endif /* __shibsp_paths_h__ */ diff --git a/shibsp/remoting/ListenerService.h b/shibsp/remoting/ListenerService.h index c85af8c..60b5b7a 100644 --- a/shibsp/remoting/ListenerService.h +++ b/shibsp/remoting/ListenerService.h @@ -39,9 +39,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(Remoted); protected: - Remoted() {} + Remoted(); public: - virtual ~Remoted() {} + virtual ~Remoted(); /** * Remoted classes implement this method to process incoming messages. @@ -72,8 +72,10 @@ namespace shibsp { */ class SHIBSP_API ListenerService : public virtual Remoted { + protected: + ListenerService(); public: - virtual ~ListenerService() {} + virtual ~ListenerService(); /** * Send a remoted message and return the response. @@ -126,9 +128,7 @@ namespace shibsp { * @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 @@ -142,8 +142,7 @@ namespace shibsp { /** * OutOfProcess servers can implement server-side termination/cleanup. */ - virtual void term() { - } + virtual void term(); private: std::map m_listenerMap; diff --git a/shibsp/remoting/ddf.h b/shibsp/remoting/ddf.h index b361ec0..abcc045 100644 --- a/shibsp/remoting/ddf.h +++ b/shibsp/remoting/ddf.h @@ -42,7 +42,7 @@ namespace shibsp { 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); @@ -77,13 +77,9 @@ namespace shibsp { // destructive node conversion methods DDF& empty(); - DDF& string(const char* val) { - return string(const_cast(val), true); - } - DDF& unsafe_string(const char* val) { - return string(const_cast(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); @@ -110,7 +106,7 @@ namespace shibsp { // 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); diff --git a/shibsp/remoting/impl/ListenerService.cpp b/shibsp/remoting/impl/ListenerService.cpp index f33b307..814db96 100644 --- a/shibsp/remoting/impl/ListenerService.cpp +++ b/shibsp/remoting/impl/ListenerService.cpp @@ -48,6 +48,22 @@ void SHIBSP_API shibsp::registerListenerServices() #endif } +Remoted::Remoted() +{ +} + +Remoted::~Remoted() +{ +} + +ListenerService::ListenerService() +{ +} + +ListenerService::~ListenerService() +{ +} + Remoted* ListenerService::regListener(const char* address, Remoted* listener) { Remoted* ret=NULL; @@ -96,3 +112,12 @@ void ListenerService::receive(DDF &in, ostream& out) dest->receive(in, out); } + +bool ListenerService::init(bool force) +{ + return true; +} + +void ListenerService::term() +{ +} diff --git a/shibsp/remoting/impl/ddf.cpp b/shibsp/remoting/impl/ddf.cpp index ae44d4f..81122cf 100644 --- a/shibsp/remoting/impl/ddf.cpp +++ b/shibsp/remoting/impl/ddf.cpp @@ -119,6 +119,10 @@ struct shibsp::ddf_body_t { // library implementation +DDF::DDF() : m_handle(NULL) +{ +} + DDF::DDF(const char* n) { m_handle=new(nothrow) ddf_body_t; @@ -365,6 +369,16 @@ DDF& DDF::string(char* val, bool copyit, bool safe) return *this; } +DDF& DDF::string(const char* val) +{ + return string(const_cast(val), true); +} + +DDF& DDF::unsafe_string(const char* val) +{ + return string(const_cast(val), true, false); +} + DDF& DDF::string(long val) { char buf[20]; @@ -600,6 +614,11 @@ DDF DDF::previous() return p; } +DDF DDF::operator[](const char* path) const +{ + return getmember(path); +} + DDF DDF::operator[](unsigned long index) const { DDF d; @@ -997,8 +1016,7 @@ DDF deserialize(DOMElement* root, bool lowercase) } 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 } } } diff --git a/shibsp/resource.h b/shibsp/resource.h index 8df1c2f..79fe549 100644 --- a/shibsp/resource.h +++ b/shibsp/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by shibsp.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by shibsp.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/shibsp/security/PKIXTrustEngine.cpp b/shibsp/security/PKIXTrustEngine.cpp index d52db86..8c4bea3 100644 --- a/shibsp/security/PKIXTrustEngine.cpp +++ b/shibsp/security/PKIXTrustEngine.cpp @@ -31,6 +31,7 @@ #include #include #include +#include using namespace shibsp; using namespace opensaml::saml2md; diff --git a/shibsp/security/SecurityPolicy.cpp b/shibsp/security/SecurityPolicy.cpp index 8317554..e66c028 100644 --- a/shibsp/security/SecurityPolicy.cpp +++ b/shibsp/security/SecurityPolicy.cpp @@ -43,6 +43,10 @@ SecurityPolicy::SecurityPolicy(const Application& application, const xmltooling: } } +SecurityPolicy::~SecurityPolicy() +{ +} + opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProviderCriteria() const { if (!m_metadataCriteria) @@ -51,3 +55,8 @@ opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProvid m_metadataCriteria->reset(); return *m_metadataCriteria; } + +const Application& SecurityPolicy::getApplication() const +{ + return m_application; +} diff --git a/shibsp/security/SecurityPolicy.h b/shibsp/security/SecurityPolicy.h index 29a3bf5..0357e82 100644 --- a/shibsp/security/SecurityPolicy.h +++ b/shibsp/security/SecurityPolicy.h @@ -46,7 +46,7 @@ namespace shibsp { */ 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; @@ -55,9 +55,7 @@ namespace shibsp { * * @return the associated Application */ - const Application& getApplication() const { - return m_application; - } + const Application& getApplication() const; private: const Application& m_application; diff --git a/shibsp/shibsp-lite.vcproj b/shibsp/shibsp-lite.vcproj index e465154..a109bb8 100644 --- a/shibsp/shibsp-lite.vcproj +++ b/shibsp/shibsp-lite.vcproj @@ -67,7 +67,7 @@ + + + + + + + + + + + + @@ -489,14 +497,26 @@ > + + + + + + @@ -607,6 +627,10 @@ > + + diff --git a/shibsp/util/CGIParser.cpp b/shibsp/util/CGIParser.cpp index d1cba90..0314896 100644 --- a/shibsp/util/CGIParser.cpp +++ b/shibsp/util/CGIParser.cpp @@ -24,6 +24,7 @@ #include "util/CGIParser.h" #include +#include #include using namespace shibsp; diff --git a/shibsp/util/CGIParser.h b/shibsp/util/CGIParser.h index c0e3371..66d133b 100644 --- a/shibsp/util/CGIParser.h +++ b/shibsp/util/CGIParser.h @@ -24,7 +24,13 @@ #define __shibsp_cgi_h__ #include -#include + +#include +#include + +namespace xmltooling { + class XMLTOOL_API HTTPRequest; +}; namespace shibsp { diff --git a/shibsp/util/DOMPropertySet.cpp b/shibsp/util/DOMPropertySet.cpp index f2cb41a..0a5dadd 100644 --- a/shibsp/util/DOMPropertySet.cpp +++ b/shibsp/util/DOMPropertySet.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -32,6 +32,18 @@ using namespace xmltooling; using namespace xercesc; using namespace std; +PropertySet::PropertySet() +{ +} + +PropertySet::~PropertySet() +{ +} + +DOMPropertySet::DOMPropertySet() : m_parent(NULL), m_root(NULL) +{ +} + DOMPropertySet::~DOMPropertySet() { for (map >::iterator i=m_map.begin(); i!=m_map.end(); i++) @@ -39,6 +51,21 @@ DOMPropertySet::~DOMPropertySet() for_each(m_nested.begin(),m_nested.end(),cleanup_pair()); } +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, @@ -70,7 +97,7 @@ void DOMPropertySet::load( 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(); } } @@ -102,7 +129,7 @@ void DOMPropertySet::load( 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(); } } diff --git a/shibsp/util/DOMPropertySet.h b/shibsp/util/DOMPropertySet.h index d642615..a42294b 100644 --- a/shibsp/util/DOMPropertySet.h +++ b/shibsp/util/DOMPropertySet.h @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,7 @@ #define __shibsp_dompropset_h__ #include + #include namespace shibsp { @@ -34,18 +35,12 @@ 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 getBool(const char* name, const char* ns=NULL) const; std::pair getString(const char* name, const char* ns=NULL) const; std::pair getXMLString(const char* name, const char* ns=NULL) const; @@ -53,10 +48,7 @@ namespace shibsp { std::pair getInt(const char* name, const char* ns=NULL) const; void getAll(std::map& 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. diff --git a/shibsp/util/PropertySet.h b/shibsp/util/PropertySet.h index bfc7988..98c1091 100644 --- a/shibsp/util/PropertySet.h +++ b/shibsp/util/PropertySet.h @@ -1,5 +1,5 @@ /* - * 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. @@ -24,7 +24,9 @@ #define __shibsp_propset_h__ #include + #include +#include #include namespace shibsp { @@ -36,9 +38,9 @@ namespace shibsp { { MAKE_NONCOPYABLE(PropertySet); protected: - PropertySet() {} + PropertySet(); public: - virtual ~PropertySet() {} + virtual ~PropertySet(); /** * Returns parent of this PropertySet, if any. diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp index 38f0a0a..6614bad 100644 --- a/shibsp/util/SPConstants.cpp +++ b/shibsp/util/SPConstants.cpp @@ -1,116 +1,116 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * SPConstants.cpp - * - * SP XML namespace constants - */ - -#include "internal.h" -#include "util/SPConstants.h" -#include - -using namespace shibspconstants; - -const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0 -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chNull -}; - -const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0 -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon, - chDigit_1, chPeriod, chDigit_0, chNull -}; - -const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d); - -const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon, - chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, - chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash, - chLatin_m, chLatin_a, chLatin_p, chNull -}; - -const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon, - chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, - chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, - chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull -}; - -const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, - chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_u, chLatin_r, chLatin_i, chNull -}; - -const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_n, chLatin_a, chLatin_m, chLatin_e, - chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull -}; - -const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon, - chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n, - chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull -}; - -const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit"; - -const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout"; - -const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config"; +/* + * Copyright 2001-2007 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * SPConstants.cpp + * + * SP XML namespace constants + */ + +#include "internal.h" +#include "util/SPConstants.h" +#include + +using namespace shibspconstants; + +const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0 +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chNull +}; + +const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0 +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon, + chDigit_1, chPeriod, chDigit_0, chNull +}; + +const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d); + +const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon, + chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash, + chLatin_m, chLatin_a, chLatin_p, chNull +}; + +const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon, + chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull +}; + +const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, + chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_u, chLatin_r, chLatin_i, chNull +}; + +const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_n, chLatin_a, chLatin_m, chLatin_e, + chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull +}; + +const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon, + chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n, + chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull +}; + +const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit"; + +const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout"; + +const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config"; diff --git a/shibsp/util/SPConstants.h b/shibsp/util/SPConstants.h index dd730f9..20f9cc2 100644 --- a/shibsp/util/SPConstants.h +++ b/shibsp/util/SPConstants.h @@ -1,5 +1,5 @@ /* - * 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. @@ -24,11 +24,7 @@ #define __shibsp_constants_h__ #include -#ifndef SHIBSP_LITE -# include -#else -# include -#endif +#include /** * Shibboleth SP XML constants. diff --git a/shibsp/util/TemplateParameters.cpp b/shibsp/util/TemplateParameters.cpp index f83abd2..520dfc0 100644 --- a/shibsp/util/TemplateParameters.cpp +++ b/shibsp/util/TemplateParameters.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "util/PropertySet.h" #include "util/TemplateParameters.h" #include @@ -31,6 +32,16 @@ using namespace shibsp; using namespace xmltooling; using namespace std; +TemplateParameters::TemplateParameters(const exception* e, const PropertySet* props) + : m_exception(e), m_toolingException(dynamic_cast(e)) +{ + setPropertySet(props); +} + +TemplateParameters::~TemplateParameters() +{ +} + void TemplateParameters::setPropertySet(const PropertySet* props) { m_props = props; @@ -48,6 +59,11 @@ void TemplateParameters::setPropertySet(const PropertySet* props) #endif } +const XMLToolingException* TemplateParameters::getRichException() const +{ + return m_toolingException; +} + const char* TemplateParameters::getParameter(const char* name) const { if (m_exception) { diff --git a/shibsp/util/TemplateParameters.h b/shibsp/util/TemplateParameters.h index f04f42a..783979c 100644 --- a/shibsp/util/TemplateParameters.h +++ b/shibsp/util/TemplateParameters.h @@ -1,5 +1,5 @@ /* - * 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. @@ -23,11 +23,14 @@ #ifndef __shibsp_tempparams_h__ #define __shibsp_tempparams_h__ -#include +#include + #include namespace shibsp { + class SHIBSP_API PropertySet; + /** * Supplies xmltooling TemplateEngine with additional parameters from a PropertySet. */ @@ -40,12 +43,9 @@ namespace shibsp { * @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(e)) { - setPropertySet(props); - } + TemplateParameters(const std::exception* e=NULL, const PropertySet* props=NULL); - virtual ~TemplateParameters() {} + virtual ~TemplateParameters(); /** * Sets a PropertySet to supply additional parameters. @@ -59,9 +59,7 @@ namespace shibsp { * * @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; diff --git a/shibsp/version.h b/shibsp/version.h index b08f76d..e8707e4 100644 --- a/shibsp/version.h +++ b/shibsp/version.h @@ -38,8 +38,8 @@ */ #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 */ diff --git a/util/Makefile.in b/util/Makefile.in index b9ced07..7112067 100644 --- a/util/Makefile.in +++ b/util/Makefile.in @@ -79,6 +79,8 @@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ APR1_CONFIG = @APR1_CONFIG@ APR_CONFIG = @APR_CONFIG@ +APU1_CONFIG = @APU1_CONFIG@ +APU_CONFIG = @APU_CONFIG@ APXS = @APXS@ APXS2 = @APXS2@ APXS22 = @APXS22@ diff --git a/util/mdquery.cpp b/util/mdquery.cpp index 89cc34e..9b928a8 100644 --- a/util/mdquery.cpp +++ b/util/mdquery.cpp @@ -1,160 +1,162 @@ -/* - * 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. - */ - -/** - * mdquery.cpp - * - * SAML Metadata Query tool layered on SP configuration - */ - -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace opensaml::saml2md; -using namespace opensaml; -using namespace xmltooling::logging; -using namespace xmltooling; -using namespace std; - -void usage() -{ - cerr << "usage: mdquery -e [-a -nostrict]" << endl; - cerr << " mdquery -e -r -p [-a -ns -nostrict]" << endl; -} - -int main(int argc,char* argv[]) -{ - char* entityID = NULL; - char* appID = "default"; - bool strict = true; - char* prot = NULL; - const XMLCh* protocol = NULL; - char* rname = NULL; - char* rns = NULL; - - for (int i=1; ilock(); - - Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery"); - - const Application* app = sp->getApplication(appID); - if (!app) { - log.error("unknown application ID (%s)", appID); - sp->unlock(); - conf.term(); - return -3; - } - - app->getMetadataProvider()->lock(); - MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict); - if (rname) { - const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; - auto_ptr_XMLCh n(rname); - QName q(ns, n.get()); - mc.role = &q; - mc.protocol = protocol; - const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second; - if (role) - XMLHelper::serialize(role->marshall(), cout, true); - else - log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); - } - else { - const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first; - if (entity) - XMLHelper::serialize(entity->marshall(), cout, true); - else - log.error("no metadata found for (%s)", entityID); - } - - app->getMetadataProvider()->unlock(); - - sp->unlock(); - conf.term(); - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * mdquery.cpp + * + * SAML Metadata Query tool layered on SP configuration + */ + +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace opensaml::saml2md; +using namespace opensaml; +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace std; + +using xercesc::XMLString; + +void usage() +{ + cerr << "usage: mdquery -e [-a -nostrict]" << endl; + cerr << " mdquery -e -r -p [-a -ns -nostrict]" << endl; +} + +int main(int argc,char* argv[]) +{ + char* entityID = NULL; + char* appID = "default"; + bool strict = true; + char* prot = NULL; + const XMLCh* protocol = NULL; + char* rname = NULL; + char* rns = NULL; + + for (int i=1; ilock(); + + Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery"); + + const Application* app = sp->getApplication(appID); + if (!app) { + log.error("unknown application ID (%s)", appID); + sp->unlock(); + conf.term(); + return -3; + } + + app->getMetadataProvider()->lock(); + MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict); + if (rname) { + const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; + auto_ptr_XMLCh n(rname); + QName q(ns, n.get()); + mc.role = &q; + mc.protocol = protocol; + const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second; + if (role) + XMLHelper::serialize(role->marshall(), cout, true); + else + log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); + } + else { + const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first; + if (entity) + XMLHelper::serialize(entity->marshall(), cout, true); + else + log.error("no metadata found for (%s)", entityID); + } + + app->getMetadataProvider()->unlock(); + + sp->unlock(); + conf.term(); + return 0; +} diff --git a/util/resolvertest.cpp b/util/resolvertest.cpp index 6fe35e2..9a1709d 100644 --- a/util/resolvertest.cpp +++ b/util/resolvertest.cpp @@ -32,7 +32,6 @@ #endif #include -#include #include #include #include @@ -41,11 +40,14 @@ #include #include +#include #include #include #include +#include #include #include +#include #include using namespace shibsp; @@ -160,7 +162,8 @@ int main(int argc,char* argv[]) SPConfig::Trust | SPConfig::AttributeResolution | SPConfig::Credentials | - SPConfig::OutOfProcess + SPConfig::OutOfProcess | + SPConfig::Caching ); if (!conf.init()) return -1; -- 2.1.4