Imported Upstream version 2.2.1+dfsg
authorRuss Allbery <rra@debian.org>
Fri, 21 Aug 2009 17:32:58 +0000 (10:32 -0700)
committerRuss Allbery <rra@debian.org>
Fri, 21 Aug 2009 17:32:58 +0000 (10:32 -0700)
174 files changed:
Makefile.am
Makefile.in
Portfile [new file with mode: 0644]
Portfile.in [new file with mode: 0644]
Shibboleth.sln
adfs/adfs-lite.vcproj
adfs/adfs.cpp
adfs/adfs.rc
adfs/adfs.vcproj
apache/mod_apache.cpp
apache/mod_shib13.vcproj
apache/mod_shib20.vcproj
apache/mod_shib22.vcproj
apache/mod_shib_13.cpp
apache/mod_shib_13.rc
apache/mod_shib_20.cpp
apache/mod_shib_20.rc
apache/mod_shib_22.cpp
apache/mod_shib_22.rc
config.h.in
config_win32.h
configs/Makefile.am
configs/Makefile.in
configs/attribute-map.xml
configs/keygen.bat
configs/metagen.sh [new file with mode: 0755]
configs/postTemplate.html [new file with mode: 0644]
configs/shibboleth2.xml
configs/shibd-debian.in
configs/shibd-osx.plist.in
configs/shibd-redhat.in
configs/shibd-suse.in [new file with mode: 0644]
configure
configure.ac
depend
doc/FASTCGI.LICENSE
doc/LOG4CPP.LICENSE
doc/Makefile.am
doc/Makefile.in
doc/OPENSSL.LICENSE
doc/README.txt
doc/RELEASE.txt
doc/main.css
doxygen.m4
fastcgi/shibauthorizer.cpp
fastcgi/shibauthorizer.rc
fastcgi/shibauthorizer.vcproj
fastcgi/shibresponder.cpp
fastcgi/shibresponder.rc
fastcgi/shibresponder.vcproj
isapi_shib/isapi_shib.cpp
isapi_shib/isapi_shib.cpp.mine [new file with mode: 0644]
isapi_shib/isapi_shib.cpp.r3059 [new file with mode: 0644]
isapi_shib/isapi_shib.cpp.r3097 [new file with mode: 0644]
isapi_shib/isapi_shib.rc
isapi_shib/isapi_shib.vcproj
memcache-store/memcache-store.cpp
memcache-store/memcache-store.rc
memcache-store/memcache-store.vcproj
nsapi_shib/nsapi_shib.cpp
nsapi_shib/nsapi_shib.rc
nsapi_shib/nsapi_shib.vcproj
odbc-store/odbc-store.rc
odbc-store/odbc-store.vcproj
pkginfo
pkginfo.in
schemas/shibboleth-2.0-attribute-map.xsd
schemas/shibboleth-2.0-native-sp-config.xsd
shibboleth.spec
shibboleth.spec.in
shibd/shibd.cpp
shibd/shibd.rc
shibd/shibd.vcproj
shibsp/AbstractSPRequest.cpp
shibsp/AbstractSPRequest.h
shibsp/AccessControl.h
shibsp/Application.cpp
shibsp/Application.h
shibsp/Makefile.am
shibsp/Makefile.in
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/SPRequest.h
shibsp/ServiceProvider.cpp
shibsp/attribute/Attribute.cpp
shibsp/attribute/Attribute.h
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/DOMAttributeDecoder.cpp [new file with mode: 0644]
shibsp/attribute/ExtensibleAttribute.cpp [new file with mode: 0644]
shibsp/attribute/ExtensibleAttribute.h [new file with mode: 0644]
shibsp/attribute/KeyInfoAttributeDecoder.cpp [new file with mode: 0644]
shibsp/attribute/NameIDAttribute.h
shibsp/attribute/NameIDAttributeDecoder.cpp
shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp
shibsp/attribute/ScopedAttribute.h
shibsp/attribute/ScopedAttributeDecoder.cpp
shibsp/attribute/StringAttributeDecoder.cpp
shibsp/attribute/XMLAttribute.h [new file with mode: 0644]
shibsp/attribute/XMLAttributeDecoder.cpp [new file with mode: 0644]
shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
shibsp/attribute/filtering/impl/MatchFunctor.cpp
shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
shibsp/attribute/resolver/AttributeExtractor.h
shibsp/attribute/resolver/AttributeResolver.h
shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp [new file with mode: 0644]
shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp [new file with mode: 0644]
shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp [new file with mode: 0644]
shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
shibsp/base.h
shibsp/binding/SOAPClient.h
shibsp/binding/impl/ArtifactResolver.cpp
shibsp/binding/impl/SOAPClient.cpp
shibsp/handler/AbstractHandler.h
shibsp/handler/AssertionConsumerService.h
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/handler/impl/AssertionLookup.cpp
shibsp/handler/impl/ChainingLogoutInitiator.cpp
shibsp/handler/impl/ChainingSessionInitiator.cpp
shibsp/handler/impl/LogoutHandler.cpp
shibsp/handler/impl/MetadataGenerator.cpp
shibsp/handler/impl/RemotedHandler.cpp
shibsp/handler/impl/SAML1Consumer.cpp
shibsp/handler/impl/SAML2ArtifactResolution.cpp
shibsp/handler/impl/SAML2Consumer.cpp
shibsp/handler/impl/SAML2Logout.cpp
shibsp/handler/impl/SAML2LogoutInitiator.cpp
shibsp/handler/impl/SAML2NameIDMgmt.cpp
shibsp/handler/impl/SAML2SessionInitiator.cpp
shibsp/handler/impl/SAMLDSSessionInitiator.cpp
shibsp/handler/impl/SessionHandler.cpp
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/handler/impl/StatusHandler.cpp
shibsp/handler/impl/TransformSessionInitiator.cpp
shibsp/handler/impl/WAYFSessionInitiator.cpp
shibsp/impl/ChainingAccessControl.cpp [new file with mode: 0644]
shibsp/impl/StorageServiceSessionCache.cpp
shibsp/impl/XMLAccessControl.cpp
shibsp/impl/XMLRequestMapper.cpp
shibsp/impl/XMLServiceProvider.cpp
shibsp/lite/CommonDomainCookie.cpp
shibsp/lite/SAMLConstants.cpp
shibsp/lite/SAMLConstants.h
shibsp/metadata/DynamicMetadataProvider.cpp
shibsp/metadata/MetadataExtImpl.cpp
shibsp/metadata/MetadataExtSchemaValidators.cpp
shibsp/metadata/MetadataProviderCriteria.h
shibsp/paths.h
shibsp/paths.h.in
shibsp/remoting/ListenerService.h
shibsp/remoting/ddf.h
shibsp/remoting/impl/ListenerService.cpp
shibsp/remoting/impl/SocketListener.cpp
shibsp/remoting/impl/SocketListener.h
shibsp/remoting/impl/TCPListener.cpp
shibsp/remoting/impl/ddf.cpp
shibsp/security/PKIXTrustEngine.cpp
shibsp/security/SecurityPolicy.cpp
shibsp/security/SecurityPolicy.h
shibsp/shibsp-lite.vcproj
shibsp/shibsp.rc
shibsp/shibsp.vcproj
shibsp/util/CGIParser.cpp
shibsp/util/CGIParser.h
shibsp/version.h
util/mdquery.cpp
util/mdquery.vcproj
util/resolvertest.cpp
util/resolvertest.vcproj

index 28448cf..96b8823 100644 (file)
@@ -13,34 +13,18 @@ SUBDIRS = $(WANT_SUBDIRS)
 DIST_SUBDIRS = doc schemas configs shibsp shibd adfs util apache nsapi_shib fastcgi odbc-store memcache-store selinux
 
 if DX_COND_doc
-all-local: shibboleth.spec pkginfo doxygen-doc
-APIDOCS = doc/api
+all-local: doxygen-doc
 else
-all-local: shibboleth.spec pkginfo
+all-local:
 endif
 
-install-data-hook:
-       rm -rf $(DESTDIR)$(datadir)/doc/@PACKAGE@/api
-       cp -r doc/api $(DESTDIR)$(datadir)/doc/@PACKAGE@
-
 dist-hook:
        rm -rf `find $(distdir)/isapi_shib -name .svn`
        rm -rf `find $(distdir)/doc/api -name .svn`
 
-shibboleth.spec: shibboleth.spec.in Makefile
-       rm -f $@.tmp
-       sed < $@.in > $@.tmp \
-           -e 's:@-VERSION-@:${VERSION}:'
-       mv $@.tmp $@
-
-pkginfo: pkginfo.in Makefile
-       rm -f $@.tmp
-       sed < $@.in > $@.tmp \
-           -e 's:@-VERSION-@:${VERSION}:'
-       mv $@.tmp $@
+GENFILES = shibboleth.spec pkginfo Portfile
 
 EXTRA_DIST = $(DX_CONFIG) \
-    $(APIDOCS) \
     isapi_shib \
     Shibboleth.sln \
     libtool.m4 \
@@ -48,11 +32,7 @@ EXTRA_DIST = $(DX_CONFIG) \
     acx_pthread.m4 \
     depcomp \
     config_win32.h \
-    shibboleth.spec.in \
-    shibboleth.spec \
-    pkginfo.in \
-    pkginfo \
+    $(GENFILES) \
+    $(GENFILES:%=%.in) \
     depend \
     postinstall
-
-DISTCLEANFILES = shibboleth.spec pkginfo
index 7f86166..b296c95 100644 (file)
@@ -66,9 +66,11 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
-       $(srcdir)/Makefile.in $(srcdir)/config.h.in \
-       $(srcdir)/doxygen.am $(top_srcdir)/configure config.guess \
-       config.sub depcomp install-sh ltmain.sh missing
+       $(srcdir)/Makefile.in $(srcdir)/Portfile.in \
+       $(srcdir)/config.h.in $(srcdir)/doxygen.am \
+       $(srcdir)/pkginfo.in $(srcdir)/shibboleth.spec.in \
+       $(top_srcdir)/configure config.guess config.sub depcomp \
+       install-sh ltmain.sh missing
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/libtool.m4 \
@@ -80,7 +82,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno configure.status.lineno
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = shibboleth.spec pkginfo Portfile
 SOURCES =
 DIST_SOURCES =
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -328,9 +330,8 @@ ACLOCAL_AMFLAGS = -I .
 MOSTLYCLEANFILES = $(DX_CLEANFILES)
 SUBDIRS = $(WANT_SUBDIRS)
 DIST_SUBDIRS = doc schemas configs shibsp shibd adfs util apache nsapi_shib fastcgi odbc-store memcache-store selinux
-@DX_COND_doc_TRUE@APIDOCS = doc/api
+GENFILES = shibboleth.spec pkginfo Portfile
 EXTRA_DIST = $(DX_CONFIG) \
-    $(APIDOCS) \
     isapi_shib \
     Shibboleth.sln \
     libtool.m4 \
@@ -338,14 +339,11 @@ EXTRA_DIST = $(DX_CONFIG) \
     acx_pthread.m4 \
     depcomp \
     config_win32.h \
-    shibboleth.spec.in \
-    shibboleth.spec \
-    pkginfo.in \
-    pkginfo \
+    $(GENFILES) \
+    $(GENFILES:%=%.in) \
     depend \
     postinstall
 
-DISTCLEANFILES = shibboleth.spec pkginfo
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -400,6 +398,12 @@ $(srcdir)/config.h.in:  $(am__configure_deps)
 
 distclean-hdr:
        -rm -f config.h stamp-h1
+shibboleth.spec: $(top_builddir)/config.status $(srcdir)/shibboleth.spec.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+pkginfo: $(top_builddir)/config.status $(srcdir)/pkginfo.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+Portfile: $(top_builddir)/config.status $(srcdir)/Portfile.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
 
 mostlyclean-libtool:
        -rm -f *.lo
@@ -546,7 +550,7 @@ distclean-tags:
 distdir: $(DISTFILES)
        $(am__remove_distdir)
        mkdir $(distdir)
-       $(mkdir_p) $(distdir)/doc
+       $(mkdir_p) $(distdir)/.
        @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
        topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
        list='$(DISTFILES)'; for file in $$list; do \
@@ -714,7 +718,6 @@ clean-generic:
 
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
 
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
@@ -740,8 +743,6 @@ info: info-recursive
 info-am:
 
 install-data-am:
-       @$(NORMAL_INSTALL)
-       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
 
 install-exec-am:
 
@@ -780,14 +781,13 @@ uninstall-info: uninstall-info-recursive
        distclean distclean-generic distclean-hdr distclean-libtool \
        distclean-recursive distclean-tags distcleancheck distdir \
        distuninstallcheck dvi dvi-am html html-am info info-am \
-       install install-am install-data install-data-am \
-       install-data-hook install-exec install-exec-am install-info \
-       install-info-am install-man install-strip installcheck \
-       installcheck-am installdirs installdirs-am maintainer-clean \
-       maintainer-clean-generic maintainer-clean-recursive \
-       mostlyclean mostlyclean-generic mostlyclean-libtool \
-       mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
-       uninstall uninstall-am uninstall-info-am
+       install install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am maintainer-clean maintainer-clean-generic \
+       maintainer-clean-recursive mostlyclean mostlyclean-generic \
+       mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am uninstall-info-am
 
 
 @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
@@ -836,28 +836,12 @@ uninstall-info: uninstall-info-recursive
 @DX_COND_doc_TRUE@     rm -rf @DX_DOCDIR@
 @DX_COND_doc_TRUE@     $(DX_ENV) DX_INCLUDE=$(DX_INCLUDE) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
 
-@DX_COND_doc_TRUE@all-local: shibboleth.spec pkginfo doxygen-doc
-@DX_COND_doc_FALSE@all-local: shibboleth.spec pkginfo
-
-install-data-hook:
-       rm -rf $(DESTDIR)$(datadir)/doc/@PACKAGE@/api
-       cp -r doc/api $(DESTDIR)$(datadir)/doc/@PACKAGE@
+@DX_COND_doc_TRUE@all-local: doxygen-doc
+@DX_COND_doc_FALSE@all-local:
 
 dist-hook:
        rm -rf `find $(distdir)/isapi_shib -name .svn`
        rm -rf `find $(distdir)/doc/api -name .svn`
-
-shibboleth.spec: shibboleth.spec.in Makefile
-       rm -f $@.tmp
-       sed < $@.in > $@.tmp \
-           -e 's:@-VERSION-@:${VERSION}:'
-       mv $@.tmp $@
-
-pkginfo: pkginfo.in Makefile
-       rm -f $@.tmp
-       sed < $@.in > $@.tmp \
-           -e 's:@-VERSION-@:${VERSION}:'
-       mv $@.tmp $@
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/Portfile b/Portfile
new file mode 100644 (file)
index 0000000..50c87a1
--- /dev/null
+++ b/Portfile
@@ -0,0 +1,69 @@
+PortSystem 1.0
+
+name               shibboleth
+version            2.2.1
+categories         security www shibboleth
+maintainers        scantor snc
+description        Shibboleth Native Service Provider
+long_description   Standards-based attribute-based Web SSO system
+homepage           http://shibboleth.internet2.edu/
+master_sites       http://shibboleth.internet2.edu/downloads/${name}/cppsp/${version}/
+distname           ${name}-sp-${version}
+worksrcdir         ${name}-${version}
+checksums          sha1 @CHECKSUM@
+
+depends_lib        port:opensaml \
+                   port:xmltooling \
+                   port:xercesc \
+                   port:xml-security-c \
+                   port:log4shib
+
+pre-fetch {
+    set status 0
+    if {[catch {exec ${prefix}/bin/curl --version | grep SSL} results]} {
+        if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
+            set status [lindex $::errorCode 2]
+        } else {
+            set status [lindex $::errorCode 3]
+        }
+    }
+    if {${status} != 0} {
+        return -code error "\n
+    ${name} requires curl to be installed with SSL support.
+    Please deactivate your current curl installation and
+    install the proper version of curl:
+        sudo port deactivate curl
+        sudo port install curl +ssl\n"
+    }
+}
+
+configure.args     --with-xmltooling=${prefix} \
+                   --with-opensaml=${prefix} \
+                   --with-xerces=${prefix} \
+                   --with-xmlsec=${prefix} \
+                   --with-log4shib=${prefix}
+
+variant odbc {
+    depends_lib-append port:unixODBC
+    configure.args-append --enable-odbc
+}
+
+destroot.keepdirs ${destroot}${prefix}/var/log/${name} ${destroot}${prefix}/var/log/httpd ${destroot}${prefix}/var/run/${name}
+
+destroot.args  NOKEYGEN=1
+
+post-destroot {
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.logger]
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.html]
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.xml]
+    eval file delete [glob ${destroot}${prefix}/etc/${name}/shibd-*]
+       eval file delete [glob ${destroot}${prefix}/lib/${name}/*.la]
+}
+
+startupitem.create      yes
+startupitem.name        shibd
+startupitem.executable  ${prefix}/sbin/shibd -F -f -p ${prefix}/var/run/${name}/shibd.pid
+
+livecheck.check         regex
+livecheck.url           http://shibboleth.internet2.edu/downloads/shibboleth/cppsp/latest/mac/ports/shibboleth/shibboleth/Portfile
+livecheck.regex         "version *(\\d+\\.\\d+(\\.\\d+)?)"
diff --git a/Portfile.in b/Portfile.in
new file mode 100644 (file)
index 0000000..2408f92
--- /dev/null
@@ -0,0 +1,69 @@
+PortSystem 1.0
+
+name               @PACKAGE@
+version            @PACKAGE_VERSION@
+categories         security www shibboleth
+maintainers        scantor snc
+description        Shibboleth Native Service Provider
+long_description   Standards-based attribute-based Web SSO system
+homepage           http://shibboleth.internet2.edu/
+master_sites       http://shibboleth.internet2.edu/downloads/${name}/cppsp/${version}/
+distname           ${name}-sp-${version}
+worksrcdir         ${name}-${version}
+checksums          sha1 @CHECKSUM@
+
+depends_lib        port:opensaml \
+                   port:xmltooling \
+                   port:xercesc \
+                   port:xml-security-c \
+                   port:log4shib
+
+pre-fetch {
+    set status 0
+    if {[catch {exec ${prefix}/bin/curl --version | grep SSL} results]} {
+        if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
+            set status [lindex $::errorCode 2]
+        } else {
+            set status [lindex $::errorCode 3]
+        }
+    }
+    if {${status} != 0} {
+        return -code error "\n
+    ${name} requires curl to be installed with SSL support.
+    Please deactivate your current curl installation and
+    install the proper version of curl:
+        sudo port deactivate curl
+        sudo port install curl +ssl\n"
+    }
+}
+
+configure.args     --with-xmltooling=${prefix} \
+                   --with-opensaml=${prefix} \
+                   --with-xerces=${prefix} \
+                   --with-xmlsec=${prefix} \
+                   --with-log4shib=${prefix}
+
+variant odbc {
+    depends_lib-append port:unixODBC
+    configure.args-append --enable-odbc
+}
+
+destroot.keepdirs ${destroot}${prefix}/var/log/${name} ${destroot}${prefix}/var/log/httpd ${destroot}${prefix}/var/run/${name}
+
+destroot.args  NOKEYGEN=1
+
+post-destroot {
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.logger]
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.html]
+       eval file delete [glob ${destroot}${prefix}/etc/${name}/*.xml]
+    eval file delete [glob ${destroot}${prefix}/etc/${name}/shibd-*]
+       eval file delete [glob ${destroot}${prefix}/lib/${name}/*.la]
+}
+
+startupitem.create      yes
+startupitem.name        shibd
+startupitem.executable  ${prefix}/sbin/shibd -F -f -p ${prefix}/var/run/${name}/shibd.pid
+
+livecheck.check         regex
+livecheck.url           http://shibboleth.internet2.edu/downloads/shibboleth/cppsp/latest/mac/ports/shibboleth/shibboleth/Portfile
+livecheck.regex         "version *(\\d+\\.\\d+(\\.\\d+)?)"
index 8988b06..1fd1708 100644 (file)
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server Modules", "Server Modules", "{26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{FED80230-119E-4B2F-9F53-D2660A5F022B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fastcgi", "fastcgi", "{8E1AF2CF-24E1-4983-8681-394D89DF9AD2}"
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "isapi_shib", "isapi_shib\isapi_shib.vcproj", "{87C25D4E-8D19-4513-B0BA-BC668BC2DEE3}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_shib13", "apache\mod_shib13.vcproj", "{D243B43E-728E-4F32-BDFF-B3A897037C6D}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_shib20", "apache\mod_shib20.vcproj", "{68E9568B-476C-4289-B93C-893432378ADC}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsapi_shib", "nsapi_shib\nsapi_shib.vcproj", "{1396D80A-8672-4224-9B02-95F3F4207CDB}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_shib22", "apache\mod_shib22.vcproj", "{B44C0852-83B8-4FB2-A86E-097C9C8256D0}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server Modules", "Server Modules", "{26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{FED80230-119E-4B2F-9F53-D2660A5F022B}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "odbc-store", "odbc-store\odbc-store.vcproj", "{666A63A7-983F-4C19-8411-207F24305197}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shibsp", "shibsp\shibsp.vcproj", "{81F0F7A6-DC36-46EF-957F-F9E81D4403F6}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shibd", "shibd\shibd.vcproj", "{F13141B5-6C87-40BB-8D4E-5CC56EBB4C59}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F6} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F6}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shibsp-lite", "shibsp\shibsp-lite.vcproj", "{81F0F7A6-DC36-46EF-957F-F9E81D4403F7}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adfs", "adfs\adfs.vcproj", "{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83A}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F6} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F6}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adfs-lite", "adfs\adfs-lite.vcproj", "{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83B}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdquery", "util\mdquery.vcproj", "{F13141B6-6C87-40BB-8D4E-5CC56EBB4C5A}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F6} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F6}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resolvertest", "util\resolvertest.vcproj", "{F13141B6-6C87-40BB-8D4E-5CC56EBB4C59}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F6} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F6}
        EndProjectSection
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fastcgi", "fastcgi", "{8E1AF2CF-24E1-4983-8681-394D89DF9AD2}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shibauthorizer", "fastcgi\shibauthorizer.vcproj", "{8CF7DDFA-EAA0-416E-853E-3DCB210C4AE0}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shibresponder", "fastcgi\shibresponder.vcproj", "{B2423DCE-048D-4BAA-9AB9-F5D1FCDD3D25}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memcache-store", "memcache-store\memcache-store.vcproj", "{666A63A7-983F-4C19-8411-207F24305198}"
-       ProjectSection(WebsiteProperties) = preProject
-               Debug.AspNetCompiler.Debug = "True"
-               Release.AspNetCompiler.Debug = "False"
-       EndProjectSection
        ProjectSection(ProjectDependencies) = postProject
                {81F0F7A6-DC36-46EF-957F-F9E81D4403F6} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F6}
        EndProjectSection
@@ -278,20 +198,22 @@ Global
                {B2423DCE-048D-4BAA-9AB9-F5D1FCDD3D25}.Release|Win32.Build.0 = Release|Win32
                {B2423DCE-048D-4BAA-9AB9-F5D1FCDD3D25}.Release|x64.ActiveCfg = Release|x64
                {666A63A7-983F-4C19-8411-207F24305198}.Debug|Win32.ActiveCfg = Debug|Win32
+               {666A63A7-983F-4C19-8411-207F24305198}.Debug|Win32.Build.0 = Debug|Win32
                {666A63A7-983F-4C19-8411-207F24305198}.Debug|x64.ActiveCfg = Debug|x64
                {666A63A7-983F-4C19-8411-207F24305198}.Release|Win32.ActiveCfg = Release|Win32
+               {666A63A7-983F-4C19-8411-207F24305198}.Release|Win32.Build.0 = Release|Win32
                {666A63A7-983F-4C19-8411-207F24305198}.Release|x64.ActiveCfg = Release|x64
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
        GlobalSection(NestedProjects) = preSolution
+               {8E1AF2CF-24E1-4983-8681-394D89DF9AD2} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
+               {87C25D4E-8D19-4513-B0BA-BC668BC2DEE3} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
                {D243B43E-728E-4F32-BDFF-B3A897037C6D} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
                {68E9568B-476C-4289-B93C-893432378ADC} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
                {1396D80A-8672-4224-9B02-95F3F4207CDB} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
                {B44C0852-83B8-4FB2-A86E-097C9C8256D0} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
-               {87C25D4E-8D19-4513-B0BA-BC668BC2DEE3} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
-               {8E1AF2CF-24E1-4983-8681-394D89DF9AD2} = {26BA8F84-6E42-41FA-9B13-5D3F4B5B2050}
                {666A63A7-983F-4C19-8411-207F24305197} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C}
                {26D4FABF-ACDE-4947-9C4A-7AE1B50CD83A} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C}
                {26D4FABF-ACDE-4947-9C4A-7AE1B50CD83B} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C}
index cbc2a53..5017792 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="adfs-lite"\r
        ProjectGUID="{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83B}"\r
        RootNamespace="adfs-lite"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="SHIBSP_LITE"\r
+                               PreprocessorDefinitions="SHIBSP_LITE;_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               LinkIncremental="2"\r
+                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
-                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="SHIBSP_LITE;_DEBUG"\r
+                               PreprocessorDefinitions="SHIBSP_LITE"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               LinkIncremental="1"\r
+                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
index 0dd273b..bc84c2f 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  Copyright 2001-2005 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.
  * You may obtain a copy of the License at
@@ -87,7 +87,7 @@ namespace {
     public:
         ADFSDecoder() : m_ns(WSTRUST_NS) {}
         virtual ~ADFSDecoder() {}
-        
+
         XMLObject* decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const;
 
     protected:
@@ -121,7 +121,7 @@ namespace {
             }
         }
         virtual ~ADFSSessionInitiator() {}
-        
+
         void setParent(const PropertySet* parent) {
             DOMPropertySet::setParent(parent);
             pair<bool,const char*> loc = getString("Location");
@@ -135,11 +135,13 @@ namespace {
         }
 
         void receive(DDF& in, ostream& out);
+        pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
     private:
         pair<bool,long> doRequest(
             const Application& application,
+            const HTTPRequest* httpRequest,
             HTTPResponse& httpResponse,
             const char* entityID,
             const char* acsLocation,
@@ -194,7 +196,7 @@ namespace {
             }
         }
         virtual ~ADFSLogoutInitiator() {}
-        
+
         void setParent(const PropertySet* parent) {
             DOMPropertySet::setParent(parent);
             pair<bool,const char*> loc = getString("Location");
@@ -228,8 +230,8 @@ namespace {
     public:
         ADFSLogout(const DOMElement* e, const char* appId)
                 : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".Logout.ADFS")), m_login(e, appId) {
-#ifndef SHIBSP_LITE
             m_initiator = false;
+#ifndef SHIBSP_LITE
             m_preserve.push_back("wreply");
             string address = string(appId) + getString("Location").second + "::run::ADFSLO";
             setAddress(address.c_str());
@@ -295,8 +297,8 @@ extern "C" int ADFS_EXPORTS xmltooling_extension_init(void*)
     conf.AssertionConsumerServiceManager.registerFactory(WSFED_NS, ADFSLogoutFactory);
 #ifndef SHIBSP_LITE
     SAMLConfig::getConfig().MessageDecoderManager.registerFactory(WSFED_NS, ADFSDecoderFactory);
-    XMLObjectBuilder::registerBuilder(QName(WSTRUST_NS,"RequestedSecurityToken"), new AnyElementBuilder());
-    XMLObjectBuilder::registerBuilder(QName(WSTRUST_NS,"RequestSecurityTokenResponse"), new AnyElementBuilder());
+    XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestedSecurityToken"), new AnyElementBuilder());
+    XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestSecurityTokenResponse"), new AnyElementBuilder());
 #endif
     return 0;
 }
@@ -328,6 +330,13 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
     const Application& app=request.getApplication();
 
     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");
+        }
+
         option = request.getParameter("target");
         if (option)
             target = option;
@@ -353,29 +362,25 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
     }
 
     // Since we're not passing by index, we need to fully compute the return URL.
-    // Get all the ADFS endpoints.
-    const vector<const Handler*>& handlers = app.getAssertionConsumerServicesByBinding(m_binding.get());
-
-    // Index comes from request, or default set in the handler, or we just pick the first endpoint.
-    pair<bool,unsigned int> index(false,0);
-    if (isHandler) {
-        option = request.getParameter("acsIndex");
-        if (option)
-            index = pair<bool,unsigned int>(true, atoi(option));
-    }
-    if (!index.first)
-        index = getUnsignedInt("defaultACSIndex");
-    if (index.first) {
-        for (vector<const Handler*>::const_iterator h = handlers.begin(); !ACS && h!=handlers.end(); ++h) {
-            if (index.second == (*h)->getUnsignedInt("index").second)
-                ACS = *h;
+    if (!ACS) {
+        pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+        if (index.first) {
+            ACS = app.getAssertionConsumerServiceByIndex(index.second);
+            if (!ACS)
+                request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
         }
+        if (!ACS)
+            ACS = app.getDefaultAssertionConsumerService();
     }
-    else if (!handlers.empty()) {
-        ACS = handlers.front();
+
+    // Validate the ACS for use with this protocol.
+    pair<bool,const XMLCh*> ACSbinding = ACS ? ACS->getXMLString("Binding") : pair<bool,const XMLCh*>(false,NULL);
+    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);
+        }
     }
-    if (!ACS)
-        throw ConfigurationException("Unable to locate ADFS response endpoint.");
 
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
     string ACSloc=request.getHandlerURL(target.c_str());
@@ -393,8 +398,12 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
 
     m_log.debug("attempting to initiate session using ADFS with provider (%s)", entityID.c_str());
 
-    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
-        return doRequest(app, request, entityID.c_str(), ACSloc.c_str(), (acClass.first ? acClass.second : NULL), target);
+    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
+        // Out of process means the POST data via the request can be exposed directly to the private method.
+        // The method will handle POST preservation if necessary *before* issuing the response, but only if
+        // it dispatches to an IdP.
+        return doRequest(app, &request, request, entityID.c_str(), ACSloc.c_str(), (acClass.first ? acClass.second : NULL), target);
+    }
 
     // Remote the call.
     DDF out,in = DDF(m_address.c_str()).structure();
@@ -403,7 +412,7 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
     in.addmember("entity_id").string(entityID.c_str());
     in.addmember("acsLocation").string(ACSloc.c_str());
     if (!target.empty())
-        in.addmember("RelayState").string(target.c_str());
+        in.addmember("RelayState").unsafe_string(target.c_str());
     if (acClass.first)
         in.addmember("authnContextClassRef").string(acClass.second);
 
@@ -412,6 +421,16 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
     return unwrap(request, out);
 }
 
+pair<bool,long> ADFSSessionInitiator::unwrap(SPRequest& request, DDF& out) const
+{
+    // See if there's any response to send back.
+    if (!out["redirect"].isnull() || !out["response"].isnull()) {
+        // If so, we're responsible for handling the POST data, probably by dropping a cookie.
+        preservePostData(request.getApplication(), request, request, out["RelayState"].string());
+    }
+    return RemotedHandler::unwrap(request, out);
+}
+
 void ADFSSessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
@@ -439,12 +458,16 @@ void ADFSSessionInitiator::receive(DDF& in, ostream& out)
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, *http.get(), entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
+    doRequest(*app, NULL, *http.get(), entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
+    if (!ret.isstruct())
+        ret.structure();
+    ret.addmember("RelayState").unsafe_string(relayState.c_str());
     out << ret;
 }
 
 pair<bool,long> ADFSSessionInitiator::doRequest(
     const Application& app,
+    const HTTPRequest* httpRequest,
     HTTPResponse& httpResponse,
     const char* entityID,
     const char* acsLocation,
@@ -463,7 +486,7 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
         throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
     }
     else if (!entity.second) {
-        m_log.warn("unable to locate ADFS-aware identity provider role for provider (%s)", entityID);
+        m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate ADFS-aware identity provider role for provider (%s)", entityID);
         if (getParent())
             return make_pair(false,0L);
         throw MetadataException("Unable to locate ADFS-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
@@ -501,6 +524,11 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
     if (!relayState.empty())
         req += "&wctx=" + urlenc->encode(relayState.c_str());
 
+    if (httpRequest) {
+        // If the request object is available, we're responsible for the POST data.
+        preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
+    }
+
     return make_pair(true, httpResponse.sendRedirect(req.c_str()));
 #else
     return make_pair(false,0L);
@@ -538,7 +566,7 @@ XMLObject* ADFSDecoder::decode(string& relayState, const GenericRequest& generic
     // Parse and bind the document into an XMLObject.
     istringstream is(param);
     DOMDocument* doc = (policy.getValidating() ? XMLToolingConfig::getConfig().getValidatingParser()
-        : XMLToolingConfig::getConfig().getParser()).parse(is); 
+        : XMLToolingConfig::getConfig().getParser()).parse(is);
     XercesJanitor<DOMDocument> janitor(doc);
     auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
     janitor.release();
@@ -548,12 +576,11 @@ XMLObject* ADFSDecoder::decode(string& relayState, const GenericRequest& generic
         throw BindingException("Decoded message was not of the appropriate type.");
     }
 
-    if (!policy.getValidating())
-        SchemaValidators.validate(xmlObject.get());
+    SchemaValidators.validate(xmlObject.get());
 
     // Skip policy step here, there's no security in the wrapper.
     // policy.evaluate(*xmlObject.get(), &genericRequest);
-    
+
     return xmlObject.release();
 }
 
@@ -574,7 +601,7 @@ void ADFSConsumer::implementProtocol(
     const ElementProxy* response = dynamic_cast<const ElementProxy*>(&xmlObject);
     if (!response || !response->hasChildren())
         throw FatalProfileException("Incoming message was not of the proper type or contains no security token.");
-    
+
     const Assertion* token = NULL;
     for (vector<XMLObject*>::const_iterator xo = response->getUnknownXMLObjects().begin(); xo != response->getUnknownXMLObjects().end(); ++xo) {
        // Look for the RequestedSecurityToken element.
@@ -588,20 +615,20 @@ void ADFSConsumer::implementProtocol(
            break;
        }
     }
-    
+
     // Extract message and issuer details from assertion.
     extractMessageDetails(*token, m_protocol.get(), policy);
 
     // Run the policy over the assertion. Handles replay, freshness, and
     // signature verification, assuming the relevant rules are configured.
-    policy.evaluate(*token);
-    
+    policy.evaluate(*token, &httpRequest);
+
     // If no security is in place now, we kick it.
     if (!policy.isAuthenticated())
         throw SecurityPolicyException("Unable to establish security of incoming assertion.");
 
     time_t now = time(NULL);
-    
+
     const PropertySet* sessionProps = application.getPropertySet("Sessions");
     const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
 
@@ -610,7 +637,7 @@ void ADFSConsumer::implementProtocol(
     const XMLCh* authMethod=NULL;
     const XMLCh* authInstant=NULL;
     time_t sessionExp = 0;
-    
+
     const saml1::Assertion* saml1token = dynamic_cast<const saml1::Assertion*>(token);
     if (saml1token) {
         // Now do profile and core semantic validation to ensure we can use it for SSO.
@@ -620,7 +647,7 @@ void ADFSConsumer::implementProtocol(
             throw FatalProfileException("Assertion did not contain time conditions.");
         else if (saml1token->getAuthenticationStatements().empty())
             throw FatalProfileException("Assertion did not contain an authentication statement.");
-        
+
         // authnskew allows rejection of SSO if AuthnInstant is too old.
         pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
 
@@ -659,7 +686,7 @@ void ADFSConsumer::implementProtocol(
             throw FatalProfileException("Assertion did not contain time conditions.");
         else if (saml2token->getAuthnStatements().empty())
             throw FatalProfileException("Assertion did not contain an authentication statement.");
-        
+
         // authnskew allows rejection of SSO if AuthnInstant is too old.
         pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
 
@@ -691,7 +718,7 @@ void ADFSConsumer::implementProtocol(
         else
             sessionExp = min(sessionExp, now + lifetime.second);    // Use the lowest.
     }
-    
+
     m_log.debug("ADFS profile processing completed successfully");
 
     // We've successfully "accepted" the SSO token.
@@ -802,7 +829,7 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
         m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
         throw ConfigurationException("Unable to locate application for logout, deleted?");
     }
-    
+
     // Unpack the request.
     auto_ptr<HTTPRequest> req(getRequest(in));
 
@@ -810,7 +837,7 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-    
+
     Session* session = NULL;
     try {
          session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), NULL, NULL);
@@ -870,7 +897,7 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
                 "Unable to locate ADFS IdP role for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID())
                 );
         }
-        
+
         const EndpointType* ep = EndpointManager<SingleLogoutService>(
             dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleLogoutServices()
             ).getByBinding(m_binding.get());
index 7cd4e1b..7db3d05 100644 (file)
@@ -54,8 +54,8 @@ END
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,1,0,0\r
- PRODUCTVERSION 2,1,0,0\r
+ FILEVERSION 2,2,1,0\r
+ PRODUCTVERSION 2,2,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -73,13 +73,13 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"\r
-            VALUE "FileVersion", "2, 1, 0, 0\0"\r
+            VALUE "FileVersion", "2, 2, 1, 0\0"\r
 #ifdef SHIBSP_LITE\r
             VALUE "InternalName", "adfs-lite\0"\r
 #else\r
             VALUE "InternalName", "adfs\0"\r
 #endif\r
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"\r
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
 #ifdef SHIBSP_LITE\r
             VALUE "OriginalFilename", "adfs-lite.so\0"\r
@@ -87,8 +87,8 @@ BEGIN
             VALUE "OriginalFilename", "adfs.so\0"\r
 #endif\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.1\0"\r
-            VALUE "ProductVersion", "2, 1, 0, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
+            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index efb995f..4a4613b 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="adfs"\r
        ProjectGUID="{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83A}"\r
        RootNamespace="adfs"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib saml2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib saml2D.lib xmltooling1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib saml2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib saml2D.lib xmltooling1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               LinkIncremental="2"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
-                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib saml2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib saml2.lib xmltooling1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               LinkIncremental="1"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib saml2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib saml2.lib xmltooling1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
index 4fd81e8..661b448 100644 (file)
@@ -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.
@@ -91,12 +91,10 @@ namespace {
     char* g_szSchemaDir = NULL;
     char* g_szPrefix = NULL;
     SPConfig* g_Config = NULL;
-    string g_unsetHeaderValue;
+    string g_unsetHeaderValue,g_spoofKey;
     bool g_checkSpoofing = true;
     bool g_catchAll = false;
     static const char* g_UserDataKey = "_shib_check_user_";
-    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);
 }
 
 /* Apache 2.2.x headers must be accumulated and set in the output filter.
@@ -302,7 +300,7 @@ class ShibTargetApache : public AbstractSPRequest
 {
   bool m_handler;
   mutable string m_body;
-  mutable bool m_gotBody;
+  mutable bool m_gotBody,m_firsttime;
   mutable vector<string> m_certs;
   set<string> m_allhttp;
 
@@ -312,13 +310,29 @@ public:
   shib_server_config* m_sc;
   shib_request_config* m_rc;
 
-  ShibTargetApache(request_rec* req, bool handler) : AbstractSPRequest(SHIBSP_LOGCAT".Apache"), m_handler(handler), m_gotBody(false) {
+  ShibTargetApache(request_rec* req, bool handler, bool shib_check_user)
+      : AbstractSPRequest(SHIBSP_LOGCAT".Apache"), m_handler(handler), m_gotBody(false),m_firsttime(true) {
     m_sc = (shib_server_config*)ap_get_module_config(req->server->module_config, &mod_shib);
     m_dc = (shib_dir_config*)ap_get_module_config(req->per_dir_config, &mod_shib);
     m_rc = (shib_request_config*)ap_get_module_config(req->request_config, &mod_shib);
     m_req = req;
 
     setRequestURI(m_req->unparsed_uri);
+
+    if (shib_check_user && m_dc->bUseHeaders == 1) {
+        // Try and see if this request was already processed, to skip spoof checking.
+        if (!ap_is_initial_req(m_req)) {
+            m_firsttime = false;
+        }
+        else if (!g_spoofKey.empty()) {
+            const char* hdr = ap_table_get(m_req->headers_in, "Shib-Spoof-Check");
+            if (hdr && g_spoofKey == hdr)
+                m_firsttime=false;
+        }
+
+        if (!m_firsttime)
+            log(SPDebug, "shib_check_user running more than once");
+    }
   }
   virtual ~ShibTargetApache() {}
 
@@ -342,7 +356,8 @@ public:
       return m_gotBody ? m_body.length() : m_req->remaining;
   }
   string getRemoteAddr() const {
-    return m_req->connection->remote_ip;
+    string ret = AbstractSPRequest::getRemoteAddr();
+    return ret.empty() ? m_req->connection->remote_ip : ret;
   }
   void log(SPLogLevel level, const string& msg) const {
     AbstractSPRequest::log(level,msg);
@@ -421,7 +436,7 @@ public:
   void clearHeader(const char* rawname, const char* cginame) {
     if (m_dc->bUseHeaders == 1) {
        // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_clear_header: hdr\n");
-        if (g_checkSpoofing && ap_is_initial_req(m_req)) {
+        if (g_checkSpoofing && m_firsttime) {
             if (m_allhttp.empty()) {
                 // First time, so populate set with "CGI" versions of client-supplied headers.
 #ifdef SHIB_APACHE_13
@@ -483,10 +498,27 @@ public:
   }
   void setRemoteUser(const char* user) {
       SH_AP_USER(m_req) = user ? ap_pstrdup(m_req->pool, user) : NULL;
+      if (m_dc->bUseHeaders == 1) {
+          if (user) {
+              ap_table_set(m_req->headers_in, "REMOTE_USER", user);
+          }
+          else {
+              ap_table_unset(m_req->headers_in, "REMOTE_USER");
+              ap_table_set(m_req->headers_in, "REMOTE_USER", g_unsetHeaderValue.c_str());
+          }
+      }
   }
   string getRemoteUser() const {
     return string(SH_AP_USER(m_req) ? SH_AP_USER(m_req) : "");
   }
+  void setAuthType(const char* authtype) {
+      if (authtype && m_dc->bBasicHijack == 1)
+          authtype = "Basic";
+      SH_AP_AUTH_TYPE(m_req) = authtype ? ap_pstrdup(m_req->pool, authtype) : NULL;
+  }
+  string getAuthType() const {
+    return string(SH_AP_AUTH_TYPE(m_req) ? SH_AP_AUTH_TYPE(m_req) : "");
+  }
   void setContentType(const char* type) {
       m_req->content_type = ap_psprintf(m_req->pool, type);
   }
@@ -495,8 +527,11 @@ public:
    if (!m_rc)
       // this happens on subrequests
       m_rc = init_request_config(m_req);
-    if (m_handler)
+    if (m_handler) {
+        if (!m_rc->hdr_out)
+            m_rc->hdr_out = ap_make_table(m_req->pool, 5);
         ap_table_add(m_rc->hdr_out, name, value);
+    }
     else
 #endif
     ap_table_add(m_req->err_headers_out, name, value);
@@ -554,11 +589,14 @@ extern "C" int shib_check_user(request_rec* r)
   xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
-    ShibTargetApache sta(r,false);
+    ShibTargetApache sta(r,false,true);
 
     // Check user authentication and export information, then set the handler bypass
     pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta,true);
     apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool);
+    // If directed, install a spoof key to recognize when we've already cleared headers.
+    if (!g_spoofKey.empty() && (((shib_dir_config*)ap_get_module_config(r->per_dir_config, &mod_shib))->bUseHeaders==1))
+        ap_table_set(r->headers_in, "Shib-Spoof-Check", g_spoofKey.c_str());
     if (res.first) return res.second;
 
     // user auth was okay -- export the assertions now
@@ -605,7 +643,7 @@ extern "C" int shib_handler(request_rec* r)
   ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_handler(%d): ENTER: %s", (int)getpid(), r->handler);
 
   try {
-    ShibTargetApache sta(r,true);
+    ShibTargetApache sta(r,true,false);
 
     pair<bool,long> res = sta.getServiceProvider().doHandler(sta);
     if (res.first) return res.second;
@@ -642,7 +680,7 @@ extern "C" int shib_auth_checker(request_rec* r)
   xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
-    ShibTargetApache sta(r,false);
+    ShibTargetApache sta(r,false,false);
 
     pair<bool,long> res = sta.getServiceProvider().doAuthorization(sta);
     if (res.first) return res.second;
@@ -1114,9 +1152,10 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
                         auto_ptr<xercesc::RegularExpression> temp(new xercesc::RegularExpression(trans.get()));
                         re=temp;
                     }
-
-                    for (; !status && attrs.first!=attrs.second; ++attrs.first) {
-                        if (checkAttribute(request, attrs.first->second, w, regexp ? re.get() : NULL)) {
+                    
+                    pair<multimap<string,const Attribute*>::const_iterator,multimap<string,const Attribute*>::const_iterator> attrs2(attrs);
+                    for (; !status && attrs2.first!=attrs2.second; ++attrs2.first) {
+                        if (checkAttribute(request, attrs2.first->second, w, regexp ? re.get() : NULL)) {
                             status = true;
                         }
                     }
@@ -1178,12 +1217,7 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
 static int shib_post_read(request_rec *r)
 {
     shib_request_config* rc = init_request_config(r);
-
-    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_post_read");
-
-#ifdef SHIB_DEFERRED_HEADERS
-    rc->hdr_out = ap_make_table(r->pool, 5);
-#endif
+    //ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_post_read");
     return DECLINED;
 }
 
@@ -1285,13 +1319,18 @@ extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
 
     ServiceProvider* sp=g_Config->getServiceProvider();
     xmltooling::Locker locker(sp);
-    const PropertySet* props=sp->getPropertySet("Local");
+    const PropertySet* props=sp->getPropertySet("InProcess");
     if (props) {
         pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
         if (unsetValue.first)
             g_unsetHeaderValue = unsetValue.second;
         pair<bool,bool> flag=props->getBool("checkSpoofing");
         g_checkSpoofing = !flag.first || flag.second;
+        if (g_checkSpoofing) {
+            unsetValue=props->getString("spoofKey");
+            if (unsetValue.first)
+                g_spoofKey = unsetValue.second;
+        }
         flag=props->getBool("catchAll");
         g_catchAll = flag.first && flag.second;
     }
@@ -1325,11 +1364,11 @@ static apr_status_t do_output_filter(ap_filter_t *f, apr_bucket_brigade *in)
     request_rec *r = f->r;
     shib_request_config *rc = (shib_request_config*) ap_get_module_config(r->request_config, &mod_shib);
 
-    if (rc) {
+    if (rc && rc->hdr_out) {
         ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_out_filter: merging %d headers", apr_table_elts(rc->hdr_out)->nelts);
-        apr_table_do(_table_add,r->headers_out, rc->hdr_out,NULL);
         // can't use overlap call because it will collapse Set-Cookie headers
         //apr_table_overlap(r->headers_out, rc->hdr_out, APR_OVERLAP_TABLES_MERGE);
+        apr_table_do(_table_add,r->headers_out, rc->hdr_out,NULL);
     }
 
     /* remove ourselves from the filter chain */
@@ -1344,11 +1383,11 @@ static apr_status_t do_error_filter(ap_filter_t *f, apr_bucket_brigade *in)
     request_rec *r = f->r;
     shib_request_config *rc = (shib_request_config*) ap_get_module_config(r->request_config, &mod_shib);
 
-    if (rc) {
+    if (rc && rc->hdr_out) {
         ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_err_filter: merging %d headers", apr_table_elts(rc->hdr_out)->nelts);
-        apr_table_do(_table_add,r->err_headers_out, rc->hdr_out,NULL);
         // can't use overlap call because it will collapse Set-Cookie headers
         //apr_table_overlap(r->err_headers_out, rc->hdr_out, APR_OVERLAP_TABLES_MERGE);
+        apr_table_do(_table_add,r->err_headers_out, rc->hdr_out,NULL);
     }
 
     /* remove ourselves from the filter chain */
@@ -1369,7 +1408,7 @@ static command_rec shire_cmds[] = {
   {"ShibPrefix", (config_fn_t)ap_set_global_string_slot, &g_szPrefix,
    RSRC_CONF, TAKE1, "Shibboleth installation directory"},
   {"ShibConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIBConfig,
-   RSRC_CONF, TAKE1, "Path to shibboleth.xml config file"},
+   RSRC_CONF, TAKE1, "Path to shibboleth2.xml config file"},
   {"ShibCatalogs", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
    RSRC_CONF, TAKE1, "Paths of XML schema catalogs"},
 
@@ -1473,7 +1512,7 @@ static command_rec shib_cmds[] = {
     AP_INIT_TAKE1("ShibPrefix", (config_fn_t)ap_set_global_string_slot, &g_szPrefix,
         RSRC_CONF, "Shibboleth installation directory"),
     AP_INIT_TAKE1("ShibConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIBConfig,
-        RSRC_CONF, "Path to shibboleth.xml config file"),
+        RSRC_CONF, "Path to shibboleth2.xml config file"),
     AP_INIT_TAKE1("ShibCatalogs", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
         RSRC_CONF, "Paths of XML schema catalogs"),
 
index 5f207f4..e83f9ad 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="mod_shib13"
        ProjectGUID="{D243B43E-728E-4F32-BDFF-B3A897037C6D}"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib ApacheCore.lib xmltooling-lite1.lib"
+                               AdditionalDependencies="xerces-c_3.lib ApacheCore.lib xmltooling-lite1.lib"
                                OutputFile="$(OutDir)\mod_shib_13.so"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache\libexec"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="1"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-                       IntermediateDirectory="$(ConfigurationName)"
+                       Name="Release|x64"
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="1"
-                               TypeLibraryName=".\Debug/mod_shib13.tlb"
+                               TargetEnvironment="3"
+                               TypeLibraryName=".\Release/mod_shib13.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="0"
+                               Optimization="2"
+                               InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories="..;\Apache\include;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="_WINDOWS;EAPI;WIN32;_DEBUG"
-                               BasicRuntimeChecks="3"
-                               RuntimeLibrary="3"
-                               BrowseInformation="1"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;EAPI"
+                               StringPooling="true"
+                               RuntimeLibrary="2"
+                               EnableFunctionLevelLinking="true"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
-                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib ApacheCore.lib xmltooling-lite1D.lib"
+                               AdditionalDependencies="xerces-c_3.lib ApacheCore.lib xmltooling-lite1.lib"
                                OutputFile="$(OutDir)\mod_shib_13.so"
-                               LinkIncremental="2"
+                               LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache\libexec"
-                               GenerateDebugInformation="true"
-                               TargetMachine="1"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache\libexec"
+                               ProgramDatabaseFile=".\Release/mod_shib_13.pdb"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="17"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Release|x64"
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="3"
-                               TypeLibraryName=".\Release/mod_shib13.tlb"
+                               TargetEnvironment="1"
+                               TypeLibraryName=".\Debug/mod_shib13.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="1"
+                               Optimization="0"
                                AdditionalIncludeDirectories="..;\Apache\include;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;EAPI"
-                               StringPooling="true"
-                               RuntimeLibrary="2"
-                               EnableFunctionLevelLinking="true"
+                               PreprocessorDefinitions="_WINDOWS;EAPI;WIN32;_DEBUG"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
+                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
+                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib ApacheCore.lib xmltooling-lite1.lib"
+                               AdditionalDependencies="xerces-c_3D.lib ApacheCore.lib xmltooling-lite1D.lib"
                                OutputFile="$(OutDir)\mod_shib_13.so"
-                               LinkIncremental="1"
+                               LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache\libexec"
-                               ProgramDatabaseFile=".\Release/mod_shib_13.pdb"
-                               TargetMachine="17"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache\libexec"
+                               GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="1"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib ApacheCore.lib xmltooling-lite1D.lib"
+                               AdditionalDependencies="xerces-c_3D.lib ApacheCore.lib xmltooling-lite1D.lib"
                                OutputFile="$(OutDir)\mod_shib_13.so"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache\libexec"
                                GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="17"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                                />
                        </FileConfiguration>
                        <FileConfiguration
-                               Name="Debug|Win32"
+                               Name="Release|x64"
                                ExcludedFromBuild="true"
                                >
                                <Tool
                                />
                        </FileConfiguration>
                        <FileConfiguration
-                               Name="Release|x64"
+                               Name="Debug|Win32"
                                ExcludedFromBuild="true"
                                >
                                <Tool
index 237bd70..91d85c5 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="mod_shib20"
        ProjectGUID="{68E9568B-476C-4289-B93C-893432378ADC}"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1.lib"
+                               AdditionalDependencies="xerces-c_3.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1.lib"
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2\lib"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="1"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"
+                       Name="Release|x64"
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="1"
-                               TypeLibraryName=".\mod_shib20___Win32_Debug/mod_shib20.tlb"
+                               TargetEnvironment="3"
+                               TypeLibraryName=".\mod_shib20___Win32_Release/mod_shib20.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="0"
+                               Optimization="2"
+                               InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
-                               BasicRuntimeChecks="3"
-                               RuntimeLibrary="3"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+                               StringPooling="true"
+                               RuntimeLibrary="2"
+                               EnableFunctionLevelLinking="true"
                                RuntimeTypeInfo="true"
-                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
-                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1D.lib"
+                               AdditionalDependencies="xerces-c_3.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1.lib"
                                OutputFile="$(OutDir)\mod_shib_20.so"
-                               LinkIncremental="2"
+                               LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2\lib"
-                               GenerateDebugInformation="true"
-                               TargetMachine="1"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2\lib"
+                               ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="17"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Release|x64"
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="3"
-                               TypeLibraryName=".\mod_shib20___Win32_Release/mod_shib20.tlb"
+                               TargetEnvironment="1"
+                               TypeLibraryName=".\mod_shib20___Win32_Debug/mod_shib20.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="1"
+                               Optimization="0"
                                AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
-                               StringPooling="true"
-                               RuntimeLibrary="2"
-                               EnableFunctionLevelLinking="true"
+                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
                                RuntimeTypeInfo="true"
+                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
+                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1.lib"
+                               AdditionalDependencies="xerces-c_3D.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1D.lib"
                                OutputFile="$(OutDir)\mod_shib_20.so"
-                               LinkIncremental="1"
+                               LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2\lib"
-                               ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
-                               TargetMachine="17"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2\lib"
+                               GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="1"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1D.lib"
+                               AdditionalDependencies="xerces-c_3D.lib libapr.lib libaprutil.lib libhttpd.lib xmltooling-lite1D.lib"
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2\lib"
                                GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="17"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                                />
                        </FileConfiguration>
                        <FileConfiguration
-                               Name="Debug|Win32"
+                               Name="Release|x64"
                                ExcludedFromBuild="true"
                                >
                                <Tool
                                />
                        </FileConfiguration>
                        <FileConfiguration
-                               Name="Release|x64"
+                               Name="Debug|Win32"
                                ExcludedFromBuild="true"
                                >
                                <Tool
index 81ed0da..c6e2fd6 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="mod_shib22"\r
        ProjectGUID="{B44C0852-83B8-4FB2-A86E-097C9C8256D0}"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2\lib"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                MkTypLibCompatible="true"\r
                                SuppressStartupBanner="true"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName=".\mod_shib22___Win32_Debug/mod_shib22.tlb"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\mod_shib22___Win32_Release/mod_shib22.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               EnableFunctionLevelLinking="true"\r
                                RuntimeTypeInfo="true"\r
-                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
-                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
-                               LinkIncremental="2"\r
+                               LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2\lib"\r
-                               GenerateDebugInformation="true"\r
-                               TargetMachine="1"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;C:\httpd-2.2-x64\lib&quot;"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                MkTypLibCompatible="true"\r
                                SuppressStartupBanner="true"\r
-                               TargetEnvironment="3"\r
-                               TypeLibraryName=".\mod_shib22___Win32_Release/mod_shib22.tlb"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\mod_shib22___Win32_Debug/mod_shib22.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                RuntimeTypeInfo="true"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
-                               LinkIncremental="1"\r
+                               LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;C:\httpd-2.2-x64\lib&quot;"\r
-                               TargetMachine="17"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2\lib"\r
+                               GenerateDebugInformation="true"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"\r
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;C:\httpd-2.2-x64\lib&quot;"\r
                                GenerateDebugInformation="true"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Debug|Win32"\r
+                               Name="Release|x64"\r
                                ExcludedFromBuild="true"\r
                                >\r
                                <Tool\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Release|x64"\r
+                               Name="Debug|Win32"\r
                                ExcludedFromBuild="true"\r
                                >\r
                                <Tool\r
index d3c7a00..0497568 100644 (file)
@@ -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 @@
 #define SH_AP_CONFIGFILE configfile_t
 #define SH_AP_R(r) r
 #define SH_AP_USER(r) r->connection->user
+#define SH_AP_AUTH_TYPE(r) r->connection->ap_auth_type
 
 #ifdef WIN32
 # define _USE_32BIT_TIME_T
index e6939bb..503cf30 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 1.3 Module\0"
-            VALUE "FileVersion", "2, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "mod_shib_13\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_13.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 065b24e..c4260c1 100644 (file)
@@ -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.
@@ -31,6 +31,7 @@
 
 #define SH_AP_R(r) 0,r
 #define SH_AP_USER(r) r->user
+#define SH_AP_AUTH_TYPE(r) r->ap_auth_type
 
 #define SERVER_ERROR HTTP_INTERNAL_SERVER_ERROR
 #define REDIRECT HTTP_MOVED_TEMPORARILY
index 108338c..d3e619e 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 2.0 Module\0"
-            VALUE "FileVersion", "2, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "mod_shib_20\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_20.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 5cab9e4..fbaf17d 100644 (file)
@@ -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.
@@ -31,6 +31,7 @@
 
 #define SH_AP_R(r) 0,r
 #define SH_AP_USER(r) r->user
+#define SH_AP_AUTH_TYPE(r) r->ap_auth_type
 
 #define SERVER_ERROR HTTP_INTERNAL_SERVER_ERROR
 #define REDIRECT HTTP_MOVED_TEMPORARILY
index ede13f4..5f92326 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 2.2 Module\0"
-            VALUE "FileVersion", "2, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "mod_shib_22\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_22.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 0d29263..e74571c 100644 (file)
 /* Define if log4shib library is used. */
 #undef SHIBSP_LOG4SHIB
 
+/* Define to 1 if Xerces XMLString includes XMLByte release. */
+#undef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+
+/* Define to 1 if Xerces DOMNodeFilter API returns a short. */
+#undef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
index 57a9ec7..04b4dd2 100644 (file)
 /* Define if Xerces-C library was found */
 #define HAVE_LIBXERCESC 1
 
+#include <xercesc/util/XercesVersion.hpp>
+
+#if (XERCES_VERSION_MAJOR < 3)
+# define SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE 1
+# define SHIBSP_XERCESC_SHORT_ACCEPTNODE 1
+#endif
+
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
 #define PACKAGE_NAME "shibboleth"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "shibboleth 2.0"
+#define PACKAGE_STRING "shibboleth 2.2.1"
 
 /* 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.0"
+#define PACKAGE_VERSION "2.2.1"
 
 /* Define to the necessary symbol if this constant uses a non-standard name on
    your system. */
 /* #undef TM_IN_SYS_TIME */
 
 /* Version number of package */
-#define VERSION "2.0"
+#define VERSION "2.2.1"
 
 /* Define to empty if `const' does not conform to ANSI C. */
 /* #undef const */
index d745b5d..cd01d03 100644 (file)
@@ -1,22 +1,24 @@
-## $Id: Makefile.am 2779 2008-03-15 03:54:53Z cantor $ 
+## $Id: Makefile.am 3088 2009-08-10 16:43:09Z cantor $ 
 
 AUTOMAKE_OPTIONS = foreign
 
 pkglibdir = ${libdir}/@PACKAGE@
 pkglogdir = ${localstatedir}/log/@PACKAGE@
-pkgdocdir = ${datadir}/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE@-@PACKAGE_VERSION@
 shirelogdir = ${localstatedir}/log/httpd
 pkgxmldir = $(datadir)/xml/@PACKAGE@
 pkgrundir = $(localstatedir)/run/@PACKAGE@
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
 pkgsysconf_DATA = \
        shibd-redhat \
+       shibd-suse \
        shibd-debian \
        shibd-osx.plist \
        apache.config \
        apache2.config \
        apache22.config \
        keygen.sh \
+       metagen.sh \
        upgrade.xsl
 
 # The config files are installed "special".  Unlike the entries in
@@ -41,6 +43,7 @@ CONFIGFILES = \
        metadataError.html \
        bindingTemplate.html \
        discoveryTemplate.html \
+    postTemplate.html \
        localLogout.html \
        globalLogout.html \
        sslError.html
@@ -74,6 +77,9 @@ apache22.config: ${srcdir}/apache22.config.in Makefile ${top_builddir}/config.st
 shibd-redhat: ${srcdir}/shibd-redhat.in Makefile ${top_builddir}/config.status
        $(MAKE) do-build-file FILE=$@
 
+shibd-suse: ${srcdir}/shibd-suse.in Makefile ${top_builddir}/config.status
+       $(MAKE) do-build-file FILE=$@
+
 shibd-debian: ${srcdir}/shibd-debian.in Makefile ${top_builddir}/config.status
        $(MAKE) do-build-file FILE=$@
 
@@ -109,6 +115,8 @@ install-data-local: all-data-local
         done
 
 install-data-hook:
+       chmod +x $(DESTDIR)$(pkgsysconfdir)/keygen.sh
+       chmod +x $(DESTDIR)$(pkgsysconfdir)/metagen.sh
        if test -z "$(NOKEYGEN)"; then \
                cd $(DESTDIR)$(pkgsysconfdir); \
                sh ./keygen.sh -b ; \
@@ -119,6 +127,7 @@ CLEANFILES = \
        apache2.config \
        apache22.config \
        shibd-redhat \
+       shibd-suse \
        shibd-debian \
        shibd-osx.plist \
        shibd.logger \
@@ -131,10 +140,12 @@ EXTRA_DIST = \
        apache2.config.in \
        apache22.config.in \
        shibd-redhat.in \
+       shibd-suse.in \
        shibd-debian.in \
        shibd-osx.plist.in \
        keygen.bat \
        keygen.sh \
+       metagen.sh \
        upgrade.xsl \
        xsltproc.js \
        $(CONFIGFILES)
index 6a9a049..40939a8 100644 (file)
@@ -258,19 +258,21 @@ target_alias = @target_alias@
 xs = @xs@
 AUTOMAKE_OPTIONS = foreign
 pkglogdir = ${localstatedir}/log/@PACKAGE@
-pkgdocdir = ${datadir}/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE@-@PACKAGE_VERSION@
 shirelogdir = ${localstatedir}/log/httpd
 pkgxmldir = $(datadir)/xml/@PACKAGE@
 pkgrundir = $(localstatedir)/run/@PACKAGE@
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
 pkgsysconf_DATA = \
        shibd-redhat \
+       shibd-suse \
        shibd-debian \
        shibd-osx.plist \
        apache.config \
        apache2.config \
        apache22.config \
        keygen.sh \
+       metagen.sh \
        upgrade.xsl
 
 
@@ -297,6 +299,7 @@ CONFIGFILES = \
        metadataError.html \
        bindingTemplate.html \
        discoveryTemplate.html \
+    postTemplate.html \
        localLogout.html \
        globalLogout.html \
        sslError.html
@@ -306,6 +309,7 @@ CLEANFILES = \
        apache2.config \
        apache22.config \
        shibd-redhat \
+       shibd-suse \
        shibd-debian \
        shibd-osx.plist \
        shibd.logger \
@@ -318,10 +322,12 @@ EXTRA_DIST = \
        apache2.config.in \
        apache22.config.in \
        shibd-redhat.in \
+       shibd-suse.in \
        shibd-debian.in \
        shibd-osx.plist.in \
        keygen.bat \
        keygen.sh \
+       metagen.sh \
        upgrade.xsl \
        xsltproc.js \
        $(CONFIGFILES)
@@ -541,6 +547,9 @@ apache22.config: ${srcdir}/apache22.config.in Makefile ${top_builddir}/config.st
 shibd-redhat: ${srcdir}/shibd-redhat.in Makefile ${top_builddir}/config.status
        $(MAKE) do-build-file FILE=$@
 
+shibd-suse: ${srcdir}/shibd-suse.in Makefile ${top_builddir}/config.status
+       $(MAKE) do-build-file FILE=$@
+
 shibd-debian: ${srcdir}/shibd-debian.in Makefile ${top_builddir}/config.status
        $(MAKE) do-build-file FILE=$@
 
@@ -576,6 +585,8 @@ install-data-local: all-data-local
         done
 
 install-data-hook:
+       chmod +x $(DESTDIR)$(pkgsysconfdir)/keygen.sh
+       chmod +x $(DESTDIR)$(pkgsysconfdir)/metagen.sh
        if test -z "$(NOKEYGEN)"; then \
                cd $(DESTDIR)$(pkgsysconfdir); \
                sh ./keygen.sh -b ; \
index 4f7477c..431db53 100644 (file)
     
     <Attribute name="urn:mace:dir:attribute-def:eduPersonEntitlement" id="entitlement"/>
     <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" id="entitlement"/>
+
+    <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" id="assurance"/>
     
     <!-- A persistent id attribute that supports personalized anonymous access. -->
     
     <!-- First, the deprecated version, decoded as a scoped string: -->
     <Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID" id="targeted-id">
         <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
-        <!-- <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name"/> -->
+        <!-- <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/> -->
     </Attribute>
     
     <!-- Second, an alternate decoder that will turn the deprecated form into the newer form. -->
     <!--
     <Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID" id="persistent-id">
-        <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name"/>
+        <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
     </Attribute>
     -->
     
     <!-- Third, the new version (note the OID-style name): -->
     <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" id="persistent-id">
-        <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name"/>
+        <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
     </Attribute>
 
     <!-- Fourth, the SAML 2.0 NameID Format: -->
     <Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" id="persistent-id">
-        <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name"/>
+        <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
     </Attribute>
     
     <!-- Some more eduPerson attributes, uncomment these to use them... -->
index 1af0518..401269c 100644 (file)
@@ -74,7 +74,7 @@ shift
 goto opt_start\r
 \r
 :opt_years\r
-set DAYS=%2\r
+set YEARS=%2\r
 shift\r
 shift\r
 goto opt_start\r
diff --git a/configs/metagen.sh b/configs/metagen.sh
new file mode 100755 (executable)
index 0000000..faf89af
--- /dev/null
@@ -0,0 +1,211 @@
+#! /bin/sh
+
+while getopts a:c:e:h:n:o:s:t: c
+     do
+         case $c in
+           c)         CERTS[${#CERTS[*]}]=$OPTARG;;
+           e)         ENTITYID=$OPTARG;;
+           h)         HOSTS[${#HOSTS[*]}]=$OPTARG;;
+           n)         NAKEDHOSTS[${#NAKEDHOSTS[*]}]=$OPTARG;;
+           o)         ORGNAME=$OPTARG;;
+           a)         ADMIN[${#ADMIN[*]}]=$OPTARG;;
+           s)         SUP[${#SUP[*]}]=$OPTARG;;
+           t)         TECH[${#TECH[*]}]=$OPTARG;;
+           \?)        echo metagen -c cert1 [-c cert2 ...] -h host1 [-h host2 ...] [-e entityID]
+                      exit 1;;
+         esac
+     done
+
+if [ ${#HOSTS[*]} -eq 0 -a ${#NAKEDHOSTS[*]} -eq 0 ] ; then
+    echo metagen -c cert1 [-c cert2 ...] -h host1 [-h host2 ...] [-e entityID]
+    exit 1
+fi
+
+if [ ${#CERTS[*]} -eq 0 ] ; then
+    CERTS[${#CERTS[*]}]=sp-cert.pem
+fi
+
+for c in ${CERTS[@]}
+do
+    if  [ ! -s $c ] ; then
+        echo Certificate file $c does not exist! 
+        exit 2
+    fi
+done
+
+if [ -z $ENTITYID ] ; then
+    ENTITYID=https://${HOSTS[0]}/shibboleth
+fi
+
+cat <<EOF
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${ENTITYID}">
+  <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol">
+    <md:Extensions>
+EOF
+
+count=1
+for h in ${HOSTS[@]}
+do
+  cat << EOF
+      <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://$h/Shibboleth.sso/DS" index="$count"/>
+EOF
+  let "count++"
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+  cat << EOF
+      <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://$h/Shibboleth.sso/DS" index="$count"/>
+EOF
+  let "count++"
+done
+
+cat << EOF
+    </md:Extensions>
+EOF
+
+for c in ${CERTS[@]}
+do
+cat << EOF
+    <md:KeyDescriptor>
+      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+        <ds:X509Data>
+          <ds:X509Certificate>
+EOF
+grep -v ^- $c
+cat << EOF
+          </ds:X509Certificate>
+        </ds:X509Data>
+      </ds:KeyInfo>
+    </md:KeyDescriptor>
+EOF
+done
+
+cat << EOF
+    <!--
+EOF
+
+for h in ${HOSTS[@]}
+do
+  cat <<EOF
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://$h/Shibboleth.sso/SLO/SOAP"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://$h/Shibboleth.sso/SLO/Redirect"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/SLO/POST"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/SLO/Artifact"/>
+EOF
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+  cat <<EOF
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://$h/Shibboleth.sso/SLO/SOAP"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://$h/Shibboleth.sso/SLO/Redirect"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/SLO/POST"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/SLO/Artifact"/>
+EOF
+done
+
+for h in ${HOSTS[@]}
+do
+  cat <<EOF
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://$h/Shibboleth.sso/NIM/SOAP"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://$h/Shibboleth.sso/NIM/Redirect"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/NIM/POST"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/NIM/Artifact"/>
+EOF
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+  cat <<EOF
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://$h/Shibboleth.sso/NIM/SOAP"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://$h/Shibboleth.sso/NIM/Redirect"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/NIM/POST"/>
+    <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/NIM/Artifact"/>
+EOF
+done
+
+cat <<EOF
+    -->
+EOF
+
+count=0
+for h in ${HOSTS[@]}
+do
+  cat <<EOF
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/SAML2/POST" index="$((count+1))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://$h/Shibboleth.sso/SAML2/POST-SimpleSign" index="$((count+2))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/SAML2/Artifact" index="$((count+3))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://$h/Shibboleth.sso/SAML2/ECP" index="$((count+4))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://$h/Shibboleth.sso/SAML/POST" index="$((count+5))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://$h/Shibboleth.sso/SAML/Artifact" index="$((count+6))"/>
+EOF
+  let "count+=6"
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+  cat <<EOF
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/SAML2/POST" index="$((count+1))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="http://$h/Shibboleth.sso/SAML2/POST-SimpleSign" index="$((count+2))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/SAML2/Artifact" index="$((count+3))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="http://$h/Shibboleth.sso/SAML2/ECP" index="$((count+4))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="http://$h/Shibboleth.sso/SAML/POST" index="$((count+5))"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="http://$h/Shibboleth.sso/SAML/Artifact" index="$((count+6))"/>
+EOF
+  let "count+=6"
+done
+
+cat <<EOF 
+  </md:SPSSODescriptor>
+EOF
+
+if [ -n "$ORGNAME" ] ; then
+  cat <<EOF
+  <md:Organization>
+    <md:OrganizationName xml:lang="en">$ORGNAME</md:OrganizationName>
+    <md:OrganizationDisplayName xml:lang="en">$ORGNAME</md:OrganizationDisplayName>
+    <md:OrganizationURL xml:lang="en">$ENTITYID</md:OrganizationURL>
+  </md:Organization>
+EOF
+fi
+
+for c in ${ADMIN[@]}
+do
+  c=(${c//\// })
+  cat <<EOF
+  <md:ContactPerson contactType="administrative">
+    <md:GivenName>${c[0]}</md:GivenName>
+    <md:SurName>${c[1]}</md:SurName>
+    <md:EmailAddress>${c[2]}</md:EmailAddress>
+  </md:ContactPerson>
+EOF
+done
+
+for c in ${SUP[@]}
+do
+  c=(${c//\// })
+  cat <<EOF
+  <md:ContactPerson contactType="support">
+    <md:GivenName>${c[0]}</md:GivenName>
+    <md:SurName>${c[1]}</md:SurName>
+    <md:EmailAddress>${c[2]}</md:EmailAddress>
+  </md:ContactPerson>
+EOF
+done
+
+for c in ${TECH[@]}
+do
+  c=(${c//\// })
+  cat <<EOF
+  <md:ContactPerson contactType="technical">
+    <md:GivenName>${c[0]}</md:GivenName>
+    <md:SurName>${c[1]}</md:SurName>
+    <md:EmailAddress>${c[2]}</md:EmailAddress>
+  </md:ContactPerson>
+EOF
+done
+
+cat <<EOF 
+</md:EntityDescriptor>
+EOF
diff --git a/configs/postTemplate.html b/configs/postTemplate.html
new file mode 100644 (file)
index 0000000..4883feb
--- /dev/null
@@ -0,0 +1,41 @@
+<html>
+    <head>
+        <title>Login Completed</title>
+        <script language="Javascript">
+        <!--
+        function submitOnce() {
+          if (location.hash.length>0) {
+             if (confirm("Are you sure you want to resubmit this form information a second time?")) {
+                document.forms[0].submit();
+             } else {
+                document.body.innerHTML="<html>Form information was not resubmitted.</html>";
+             }
+          } else {
+             var loc = window.location;
+             window.location = loc + "#submitted";
+             document.forms[0].submit();
+          }
+        }
+        // -->
+        </script>
+    </head>
+    <body onload="submitOnce()">
+        <h2>Login Completed</h2>
+
+        <noscript>
+        <p>A form submission to this site was interrupted by the login process.
+        If you would like to complete it now, submit this form.</p>
+        </noscript>
+        
+        <form method="POST" action="<shibmlp action/>">
+        <shibmlpfor PostedData>
+            <input type="hidden" name="<shibmlp $name/>" value="<shibmlp $value/>"/>
+        </shibmlpfor>
+        <noscript>
+        <div>
+        <input type="submit" name="_shib_continue_" value="Continue"/>
+        </div>
+        </noscript>
+        </form>
+    </body>
+</html>
index afe286d..d02da4c 100644 (file)
     
     <!-- The InProcess section conrains settings affecting web server modules/filters. -->
     <InProcess logger="native.logger">
-        <ISAPI normalizeRequest="true">
+        <ISAPI normalizeRequest="true" safeHeaderNames="true">
             <!--
-            Maps IIS Instance ID values to the host scheme/name/port/sslport. The name is
+            Maps IIS Instance ID values to the host scheme/name/port. The name is
             required so that the proper <Host> in the request map above is found without
             having to cover every possible DNS/IP combination the user might enter.
-            The port and scheme can usually be omitted, so the HTTP request's port and
-            scheme will be used.
             -->
             <Site id="1" name="sp.example.org"/>
+            <!--
+            When the port and scheme are omitted, the HTTP request's port and scheme are used.
+            If these are wrong because of virtualization, they can be explicitly set here to
+            ensure proper redirect generation.
+            -->
+            <!--
+            <Site id="42" name="virtual.example.org" scheme="https" port="443"/>
+            -->
         </ISAPI>
     </InProcess>
 
-    <!-- Only one listener can be defined, to connect in process modules to shibd. -->
+    <!-- Only one listener can be defined, to connect in-process modules to shibd. -->
     <UnixListener address="shibd.sock"/>
     <!-- <TCPListener address="127.0.0.1" port="12345" acl="127.0.0.1"/> -->
     
     -->
     <ApplicationDefaults id="default" policyId="default"
         entityID="https://sp.example.org/shibboleth"
-        homeURL="https://sp.example.org/index.html"
         REMOTE_USER="eppn persistent-id targeted-id"
-        signing="false" encryption="false"
-        >
+        signing="false" encryption="false">
 
         <!--
         Controls session lifetimes, address checks, cookie handling, and the protocol handlers.
             <!-- Default example directs to a specific IdP's SSO service (favoring SAML 2 over Shib 1). -->
             <SessionInitiator type="Chaining" Location="/Login" isDefault="true" id="Intranet"
                     relayState="cookie" entityID="https://idp.example.org/shibboleth">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" acsByIndex="false" template="bindingTemplate.html"/>
+                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
                 <SessionInitiator type="Shib1" defaultACSIndex="5"/>
             </SessionInitiator>
             
             <!-- An example using an old-style WAYF, which means Shib 1 only unless an entityID is provided. -->
             <SessionInitiator type="Chaining" Location="/WAYF" id="WAYF" relayState="cookie">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" acsByIndex="false" template="bindingTemplate.html"/>
+                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
                 <SessionInitiator type="Shib1" defaultACSIndex="5"/>
                 <SessionInitiator type="WAYF" defaultACSIndex="5" URL="https://wayf.example.org/WAYF"/>
             </SessionInitiator>
 
             <!-- An example supporting the new-style of discovery service. -->
             <SessionInitiator type="Chaining" Location="/DS" id="DS" relayState="cookie">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" acsByIndex="false" template="bindingTemplate.html"/>
+                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
                 <SessionInitiator type="Shib1" defaultACSIndex="5"/>
-                <SessionInitiator type="SAMLDS" URL="https://ds.example.org/DS"/>
+                <SessionInitiator type="SAMLDS" URL="https://ds.example.org/DS/WAYF"/>
             </SessionInitiator>
             
             <!--
             <!--
             <MetadataProvider type="XML" uri="http://federation.org/federation-metadata.xml"
                  backingFilePath="federation-metadata.xml" reloadInterval="7200">
-               <SignatureMetadataFilter certificate="fedsigner.pem"/>
+               <MetadataFilter type="RequireValidUntil" maxValidityInterval="2419200"/>
+               <MetadataFilter type="Signature" certificate="fedsigner.pem"/>
             </MetadataProvider>
             -->
 
     
     <!-- Each policy defines a set of rules to use to secure messages. -->
     <SecurityPolicies>
-        <!-- The predefined policy enforces replay/freshness and permits signing and client TLS. -->
+        <!--
+        The predefined policy enforces replay/freshness, standard
+        condition processing, and permits signing and client TLS.
+        -->
         <Policy id="default" validate="false">
-            <Rule type="MessageFlow" checkReplay="true" expires="60"/>
-            <Rule type="ClientCertAuth" errorFatal="true"/>
-            <Rule type="XMLSigning" errorFatal="true"/>
-            <Rule type="SimpleSigning" errorFatal="true"/>
+            <PolicyRule type="MessageFlow" checkReplay="true" expires="60"/>
+            <PolicyRule type="Conditions">
+                <PolicyRule type="Audience"/>
+                <!-- Enable Delegation rule to permit delegated access. -->
+                <!-- <PolicyRule type="Delegation"/> -->
+            </PolicyRule>
+            <PolicyRule type="ClientCertAuth" errorFatal="true"/>
+            <PolicyRule type="XMLSigning" errorFatal="true"/>
+            <PolicyRule type="SimpleSigning" errorFatal="true"/>
         </Policy>
     </SecurityPolicies>
 
-</SPConfig>
-
+</SPConfig>
\ No newline at end of file
index 99ff4d1..13e8240 100644 (file)
@@ -4,7 +4,7 @@
 # Required-Start: $local_fs $remote_fs $network
 # Required-Stop: $local_fs $remote_fs $network
 # Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
+# Default-Stop: 0 1 6
 # Short-Description: Shibboleth 2 Service Provider Daemon
 # Description: Starts the separate daemon used by the Shibboleth
 # Apache module to manage sessions and to retrieve
@@ -56,7 +56,7 @@ start)
         exit 0
     fi
     echo -n "Starting $DESC: "
-    start-stop-daemon --background --start --quiet \
+    start-stop-daemon --start --quiet \
         --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
     echo "$NAME."
     ;;
@@ -71,7 +71,7 @@ restart|force-reload)
     start-stop-daemon --stop --quiet --pidfile $PIDFILE \
         --exec $DAEMON
     sleep 1
-    start-stop-daemon --background --start --quiet \
+    start-stop-daemon --start --quiet \
         --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
     echo "$NAME."
     ;;
index 26c90b1..a05cc9d 100644 (file)
@@ -8,6 +8,7 @@
        <key>ProgramArguments</key>
        <array>
                <string>@-PREFIX-@/sbin/shibd</string>
+        <string>-F</string>
                <string>-f</string>
                <string>-p</string>
                <string>@-PKGRUNDIR-@/shibd.pid</string>
index 496f631..02e3426 100644 (file)
@@ -36,8 +36,7 @@ start() {
        if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
                /sbin/restorecon $pidfile
        fi
-       # daemon function just hangs, so I'm using su directly
-       su - $SHIBD_USER -c "$shibd -p $pidfile -f &"
+       daemon --user $SHIBD_USER --pidfile $pidfile $shibd -p $pidfile -f -w 3
 
        RETVAL=$?
        echo
@@ -48,10 +47,9 @@ start() {
 stop() {
        echo -n $"Stopping $prog: "
        if [ -f $pidfile ]; then
-               read kpid < $pidfile
-               kill $kpid
+               killproc -p $pidfile shibd
        else
-           killproc shibd
+        killproc shibd
        fi
 
        RETVAL=$?
@@ -77,7 +75,7 @@ case "$1" in
        start
        ;;
   *)
-       echo $"Usage: $prog {start|stop|restart}"
+       echo $"Usage: $prog {start|stop|status|restart}"
        exit 1
 esac
 
diff --git a/configs/shibd-suse.in b/configs/shibd-suse.in
new file mode 100644 (file)
index 0000000..1dceeda
--- /dev/null
@@ -0,0 +1,112 @@
+#! /bin/sh
+# Author: Peter Schober <peter.schober@univie.ac.at> and many others
+# based on shibd-debian (from Shibboleth's 1.3.1 SP source distribution)
+# and SUSE's /etc/init.d/cyrus
+#
+# /etc/init.d/shibd
+#
+### BEGIN INIT INFO
+# Provides: shibd
+# Required-Start: network
+# Required-Stop: $null
+# Default-Start: 3 5
+# Short-Description: Shibboleth 2.x Service Provider Daemon
+# Description: Starts the separate daemon used by the Shibboleth
+# Apache module to manage state and SAML interactions.
+### END INIT INFO
+#
+DESC="Shibboleth 2 daemon"
+NAME=shibd
+SHIB_CONFIG=@-PKGSYSCONFDIR-@/shibboleth2.xml
+DAEMON=@-PREFIX-@/sbin/$NAME
+SCRIPTNAME=/etc/init.d/$NAME
+PID_FILE=@-PKGRUNDIR-@/shibd.pid
+DAEMON_OPTS=""
+# Force removal of socket
+DAEMON_OPTS="$DAEMON_OPTS -f"
+# Use defined configuration file
+DAEMON_OPTS="$DAEMON_OPTS -c $SHIB_CONFIG"
+# Specify pid file to use
+DAEMON_OPTS="$DAEMON_OPTS -p $PID_FILE"
+# Exit if the package is not installed.
+test -x "$DAEMON" || exit 5
+. /etc/rc.status
+# First reset status of this service
+rc_reset
+case "$1" in
+    start)
+        echo -n "Starting $DESC ($NAME)"
+        ## Start daemon with startproc(8). If this fails
+        ## the echo return value is set appropriate.
+        # NOTE: startproc return 0, even if service is
+        # already running to match LSB spec.
+        /sbin/startproc -p $PID_FILE $DAEMON $DAEMON_OPTS > /dev/null 2>&1
+        # Remember status and be verbose
+        rc_status -v
+        ;;
+    stop)
+        echo -n "Shutting down $DESC ($NAME)"
+        ## Stop daemon with killproc(8) and if this fails
+        ## set echo the echo return value.
+        /sbin/killproc -p $PID_FILE -TERM $DAEMON > /dev/null 2>&1
+        # Remember status and be verbose
+        rc_status -v
+        ;;
+    try-restart)
+        ## Stop the service and if this succeeds (i.e. the
+        ## service was running before), start it again.
+        ## Note: try-restart is not (yet) part of LSB (as of 0.7.5)
+        $0 status >/dev/null &&  $0 restart
+        # Remember status and be quiet
+        rc_status
+        ;;
+    restart)
+        ## Stop the service and regardless of whether it was
+        ## running or not, start it again.
+        $0 stop
+        $0 start
+        # Remember status and be quiet
+        rc_status
+        ;;
+    configtest)
+        ## Check config files
+        echo -n "Checking config for $DESC ($NAME): "
+        $DAEMON $DAEMON_OPTS -t
+        rc_status -v
+        ;;
+    status)
+        echo -n "Checking for service $DESC ($NAME)"
+        ## Check status with checkproc(8), if process is running
+        ## checkproc will return with exit status 0.
+        # Status has a slightly different for the status command:
+        # 0 - service running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running
+        # NOTE: checkproc returns LSB compliant status values.
+        /sbin/checkproc -p $PID_FILE $DAEMON
+        rc_status -v
+        ;;
+    *)
+        echo "Usage: $0 {start|stop|status|configtest|try-restart|restart}"
+        exit 1
+        ;;
+esac
+rc_exit
index e3cf3b9..cd4b0c2 100755 (executable)
--- 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.1.
+# Generated by GNU Autoconf 2.59 for shibboleth 2.2.1.
 #
 # Report bugs to <shibboleth-users@internet2.edu>.
 #
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='shibboleth'
 PACKAGE_TARNAME='shibboleth'
-PACKAGE_VERSION='2.1'
-PACKAGE_STRING='shibboleth 2.1'
+PACKAGE_VERSION='2.2.1'
+PACKAGE_STRING='shibboleth 2.2.1'
 PACKAGE_BUGREPORT='shibboleth-users@internet2.edu'
 
 # Factoring default headers for most tests.
@@ -464,7 +464,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DX_PROJECT DX_CONFIG DX_DOCDIR DX_ENV DX_FLAG_doc DX_DOXYGEN ac_pt_DX_DOXYGEN DX_FLAG_[]DX_CURRENT_FEATURE DX_PERL ac_pt_DX_PERL DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_doc_TRUE DX_COND_doc_FALSE DX_FLAG_dot DX_FLAG_[]DX_CURRENT_FEATURE DX_DOT ac_pt_DX_DOT DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_dot_TRUE DX_COND_dot_FALSE DX_FLAG_man DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_man_TRUE DX_COND_man_FALSE DX_FLAG_rtf DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_rtf_TRUE DX_COND_rtf_FALSE DX_FLAG_xml DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_xml_TRUE DX_COND_xml_FALSE DX_FLAG_chm DX_FLAG_[]DX_CURRENT_FEATURE DX_HHC ac_pt_DX_HHC DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_chm_TRUE DX_COND_chm_FALSE DX_FLAG_chi DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_chi_TRUE DX_COND_chi_FALSE DX_FLAG_html DX_FLAG_[]DX_CURRENT_FEATURE DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_html_TRUE DX_COND_html_FALSE DX_FLAG_ps DX_FLAG_[]DX_CURRENT_FEATURE DX_LATEX ac_pt_DX_LATEX DX_FLAG_[]DX_CURRENT_FEATURE DX_MAKEINDEX ac_pt_DX_MAKEINDEX DX_FLAG_[]DX_CURRENT_FEATURE DX_DVIPS ac_pt_DX_DVIPS DX_FLAG_[]DX_CURRENT_FEATURE DX_EGREP ac_pt_DX_EGREP DX_FLAG_[]DX_CURRENT_FEATURE DX_COND_ps_TRUE DX_COND_ps_FALSE DX_FLAG_pdf DX_FLAG_[]DX_CURRENT_FEATURE DX_PDFLATEX ac_pt_DX_PDFLATEX DX_FLAG_[]DX_CURRENT_FEATURE DX_FLAG_[]DX_CURRENT_FEATURE DX_FLAG_[]DX_CURRENT_FEATURE 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 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_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.1 to adapt to many kinds of systems.
+\`configure' configures shibboleth 2.2.1 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.1:";;
+     short | recursive ) echo "Configuration of shibboleth 2.2.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1197,7 +1197,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-shibboleth configure 2.1
+shibboleth configure 2.2.1
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1211,7 +1211,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.1, which was
+It was created by shibboleth $as_me 2.2.1, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1856,7 +1856,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=shibboleth
- VERSION=2.1
+ VERSION=2.2.1
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2040,6 +2040,9 @@ DX_ENV=""
 
 
 
+# Compatibility with older autoconf versions.
+
+
 ## --------------- ##
 ## Private macros. ##
 ## --------------- ##
@@ -6097,7 +6100,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6100 "configure"' > conftest.$ac_ext
+  echo '#line 6103 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7205,7 +7208,7 @@ fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:7208:" \
+echo "$as_me:7211:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -8243,11 +8246,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:8246: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8249: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8250: \$? = $ac_status" >&5
+   echo "$as_me:8253: \$? = $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
@@ -8476,11 +8479,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:8479: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8482: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8483: \$? = $ac_status" >&5
+   echo "$as_me:8486: \$? = $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
@@ -8536,11 +8539,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:8539: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8542: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8543: \$? = $ac_status" >&5
+   echo "$as_me:8546: \$? = $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
@@ -9870,7 +9873,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 9873 "configure"' > conftest.$ac_ext
+    echo '#line 9876 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -10741,7 +10744,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10744 "configure"
+#line 10747 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10839,7 +10842,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10842 "configure"
+#line 10845 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13022,11 +13025,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:13025: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13028: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13029: \$? = $ac_status" >&5
+   echo "$as_me:13032: \$? = $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
@@ -13082,11 +13085,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:13085: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13088: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13089: \$? = $ac_status" >&5
+   echo "$as_me:13092: \$? = $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
@@ -13593,7 +13596,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 13596 "configure"' > conftest.$ac_ext
+    echo '#line 13599 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -14464,7 +14467,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 14467 "configure"
+#line 14470 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14562,7 +14565,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 14565 "configure"
+#line 14568 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15389,11 +15392,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:15392: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15395: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15396: \$? = $ac_status" >&5
+   echo "$as_me:15399: \$? = $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
@@ -15449,11 +15452,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:15452: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15455: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15456: \$? = $ac_status" >&5
+   echo "$as_me:15459: \$? = $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
@@ -16763,7 +16766,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 16766 "configure"' > conftest.$ac_ext
+    echo '#line 16769 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -17508,11 +17511,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:17511: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17514: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17515: \$? = $ac_status" >&5
+   echo "$as_me:17518: \$? = $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
@@ -17741,11 +17744,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:17744: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17747: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17748: \$? = $ac_status" >&5
+   echo "$as_me:17751: \$? = $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
@@ -17801,11 +17804,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:17804: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17807: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17808: \$? = $ac_status" >&5
+   echo "$as_me:17811: \$? = $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
@@ -19135,7 +19138,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 19138 "configure"' > conftest.$ac_ext
+    echo '#line 19141 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -20006,7 +20009,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 20009 "configure"
+#line 20012 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -20104,7 +20107,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 20107 "configure"
+#line 20110 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -22392,129 +22395,6 @@ _ACEOF
     CXXFLAGS="$PTHREAD_CFLAGS $CXXFLAGS"
 fi
 
-# Thank you Solaris, really.
-echo "$as_me:$LINENO: checking for ctime_r" >&5
-echo $ECHO_N "checking for ctime_r... $ECHO_C" >&6
- if test -z "$ac_cv_ctime_args"; then
-     cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <time.h>
-int
-main ()
-{
-
-         time_t clock;
-         char buf[26];
-         ctime_r(&clock, buf);
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 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_c_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_objext'
-  { (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
-  ac_cv_ctime_args=2
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-     cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <time.h>
-int
-main ()
-{
-
-         time_t clock;
-         char buf[26];
-         ctime_r(&clock, buf, 26);
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 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_c_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_objext'
-  { (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
-  ac_cv_ctime_args=3
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- fi
- if test -z "$ac_cv_ctime_args"; then
-     echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
- else
-     if test "$ac_cv_ctime_args" = 2; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CTIME_R_2 1
-_ACEOF
-
-     elif test "$ac_cv_ctime_args" = 3; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CTIME_R_3 1
-_ACEOF
-
-     fi
-     echo "$as_me:$LINENO: result: yes, and it takes $ac_cv_ctime_args arguments" >&5
-echo "${ECHO_T}yes, and it takes $ac_cv_ctime_args arguments" >&6
- fi
-
 # OpenSSL settings
 
 # Check whether --with-openssl or --without-openssl was given.
@@ -22970,6 +22850,129 @@ _ACEOF
 fi
 
 
+# Thank you Solaris, really.
+echo "$as_me:$LINENO: checking for ctime_r" >&5
+echo $ECHO_N "checking for ctime_r... $ECHO_C" >&6
+ if test -z "$ac_cv_ctime_args"; then
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <time.h>
+int
+main ()
+{
+
+         time_t clock;
+         char buf[26];
+         ctime_r(&clock, buf);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 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_objext'
+  { (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
+  ac_cv_ctime_args=2
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <time.h>
+int
+main ()
+{
+
+         time_t clock;
+         char buf[26];
+         ctime_r(&clock, buf, 26);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 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_objext'
+  { (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
+  ac_cv_ctime_args=3
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test -z "$ac_cv_ctime_args"; then
+     echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ else
+     if test "$ac_cv_ctime_args" = 2; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CTIME_R_2 1
+_ACEOF
+
+     elif test "$ac_cv_ctime_args" = 3; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CTIME_R_3 1
+_ACEOF
+
+     fi
+     echo "$as_me:$LINENO: result: yes, and it takes $ac_cv_ctime_args arguments" >&5
+echo "${ECHO_T}yes, and it takes $ac_cv_ctime_args arguments" >&6
+ fi
+
 # log4shib settings (favor this version over the log4cpp code)
 # Extract the first word of "log4shib-config", so it can be a program name with args.
 set dummy log4shib-config; ac_word=$2
 rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 
+echo "$as_me:$LINENO: checking whether Xerces XMLString::release(XMLByte**) exists" >&5
+echo $ECHO_N "checking whether Xerces XMLString::release(XMLByte**) exists... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <xercesc/util/XMLString.hpp>
+int
+main ()
+{
+using namespace XERCES_CPP_NAMESPACE;
+      XMLByte* buf=NULL;
+      XMLString::release(&buf);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 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_objext'
+  { (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
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking whether Xerces DOMNodeFilter API returns a short" >&5
+echo $ECHO_N "checking whether Xerces DOMNodeFilter API returns a short... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <xercesc/dom/DOM.hpp>
+int
+main ()
+{
+using namespace XERCES_CPP_NAMESPACE;
+      class Blocker : public DOMNodeFilter {
+      public:
+        short acceptNode(const DOMNode* node) const {
+            return FILTER_REJECT;
+        }
+      };
+      static Blocker g_Blocker;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 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_objext'
+  { (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
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define SHIBSP_XERCESC_SHORT_ACCEPTNODE 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
 #XML-Tooling settings
 
@@ -24377,10 +24500,10 @@ cat >>conftest.$ac_ext <<_ACEOF
 int
 main ()
 {
-#if _OPENSAML_VERSION >= 20000
+#if _OPENSAML_VERSION >= 20200
 opensaml::SAMLConfig::getConfig();
 #else
-#error Need OpenSAML version 2.0 or higher
+#error Need OpenSAML version 2.2 or higher
 #endif
   ;
   return 0;
@@ -24452,6 +24575,9 @@ OPENSAMLXMLDIR="$OPENSAMLXMLDIR/share/xml/opensaml"
 
 
 
+                              ac_config_files="$ac_config_files shibboleth.spec pkginfo Portfile"
+
+
 # output the underlying makefiles
 WANT_SUBDIRS="doc schemas configs shibsp shibd util"
                                                                                 ac_config_files="$ac_config_files Makefile doc/Makefile schemas/Makefile configs/Makefile shibsp/Makefile shibd/Makefile util/Makefile selinux/Makefile"
@@ -26765,7 +26891,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by shibboleth $as_me 2.1, which was
+This file was extended by shibboleth $as_me 2.2.1, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -26828,7 +26954,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-shibboleth config.status 2.1
+shibboleth config.status 2.2.1
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -26938,6 +27064,9 @@ for ac_config_target in $ac_config_targets
 do
   case "$ac_config_target" in
   # Handling of arguments.
+  "shibboleth.spec" ) CONFIG_FILES="$CONFIG_FILES shibboleth.spec" ;;
+  "pkginfo" ) CONFIG_FILES="$CONFIG_FILES pkginfo" ;;
+  "Portfile" ) CONFIG_FILES="$CONFIG_FILES Portfile" ;;
   "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
   "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
   "schemas/Makefile" ) CONFIG_FILES="$CONFIG_FILES schemas/Makefile" ;;
@@ -27068,70 +27197,49 @@ s,@DX_ENV@,$DX_ENV,;t t
 s,@DX_FLAG_doc@,$DX_FLAG_doc,;t t
 s,@DX_DOXYGEN@,$DX_DOXYGEN,;t t
 s,@ac_pt_DX_DOXYGEN@,$ac_pt_DX_DOXYGEN,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_PERL@,$DX_PERL,;t t
 s,@ac_pt_DX_PERL@,$ac_pt_DX_PERL,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_doc_TRUE@,$DX_COND_doc_TRUE,;t t
 s,@DX_COND_doc_FALSE@,$DX_COND_doc_FALSE,;t t
 s,@DX_FLAG_dot@,$DX_FLAG_dot,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_DOT@,$DX_DOT,;t t
 s,@ac_pt_DX_DOT@,$ac_pt_DX_DOT,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_dot_TRUE@,$DX_COND_dot_TRUE,;t t
 s,@DX_COND_dot_FALSE@,$DX_COND_dot_FALSE,;t t
 s,@DX_FLAG_man@,$DX_FLAG_man,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_man_TRUE@,$DX_COND_man_TRUE,;t t
 s,@DX_COND_man_FALSE@,$DX_COND_man_FALSE,;t t
 s,@DX_FLAG_rtf@,$DX_FLAG_rtf,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_rtf_TRUE@,$DX_COND_rtf_TRUE,;t t
 s,@DX_COND_rtf_FALSE@,$DX_COND_rtf_FALSE,;t t
 s,@DX_FLAG_xml@,$DX_FLAG_xml,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_xml_TRUE@,$DX_COND_xml_TRUE,;t t
 s,@DX_COND_xml_FALSE@,$DX_COND_xml_FALSE,;t t
 s,@DX_FLAG_chm@,$DX_FLAG_chm,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_HHC@,$DX_HHC,;t t
 s,@ac_pt_DX_HHC@,$ac_pt_DX_HHC,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_chm_TRUE@,$DX_COND_chm_TRUE,;t t
 s,@DX_COND_chm_FALSE@,$DX_COND_chm_FALSE,;t t
 s,@DX_FLAG_chi@,$DX_FLAG_chi,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_chi_TRUE@,$DX_COND_chi_TRUE,;t t
 s,@DX_COND_chi_FALSE@,$DX_COND_chi_FALSE,;t t
 s,@DX_FLAG_html@,$DX_FLAG_html,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_html_TRUE@,$DX_COND_html_TRUE,;t t
 s,@DX_COND_html_FALSE@,$DX_COND_html_FALSE,;t t
 s,@DX_FLAG_ps@,$DX_FLAG_ps,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_LATEX@,$DX_LATEX,;t t
 s,@ac_pt_DX_LATEX@,$ac_pt_DX_LATEX,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_MAKEINDEX@,$DX_MAKEINDEX,;t t
 s,@ac_pt_DX_MAKEINDEX@,$ac_pt_DX_MAKEINDEX,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_DVIPS@,$DX_DVIPS,;t t
 s,@ac_pt_DX_DVIPS@,$ac_pt_DX_DVIPS,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_EGREP@,$DX_EGREP,;t t
 s,@ac_pt_DX_EGREP@,$ac_pt_DX_EGREP,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_ps_TRUE@,$DX_COND_ps_TRUE,;t t
 s,@DX_COND_ps_FALSE@,$DX_COND_ps_FALSE,;t t
 s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_PDFLATEX@,$DX_PDFLATEX,;t t
 s,@ac_pt_DX_PDFLATEX@,$ac_pt_DX_PDFLATEX,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s,@DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
 s,@DX_COND_pdf_TRUE@,$DX_COND_pdf_TRUE,;t t
 s,@DX_COND_pdf_FALSE@,$DX_COND_pdf_FALSE,;t t
 s,@DX_COND_latex_TRUE@,$DX_COND_latex_TRUE,;t t
@@ -27943,4 +28051,3 @@ if test "$no_create" != yes; then
   $ac_cs_success || { (exit 1); exit 1; }
 fi
 
-
index effa6af..fd07125 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.50])
-AC_INIT([shibboleth], [2.1], [shibboleth-users@internet2.edu], [shibboleth])
+AC_INIT([shibboleth], [2.2.1], [shibboleth-users@internet2.edu], [shibboleth])
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE([shibboleth],[2.1])
+AM_INIT_AUTOMAKE([shibboleth],[2.2.1])
 
 sinclude(doxygen.m4)
 sinclude(acx_pthread.m4)
@@ -85,36 +85,6 @@ else
     CXXFLAGS="$PTHREAD_CFLAGS $CXXFLAGS"
 fi
 
-# Thank you Solaris, really.
-AC_MSG_CHECKING(for ctime_r)
- if test -z "$ac_cv_ctime_args"; then
-     AC_TRY_COMPILE(
-     [#include <time.h>],
-     [
-         time_t clock;
-         char buf[26];
-         ctime_r(&clock, buf);
-     ], ac_cv_ctime_args=2)
-
-     AC_TRY_COMPILE(
-     [#include <time.h>],
-     [
-         time_t clock;
-         char buf[26];
-         ctime_r(&clock, buf, 26);
-     ], ac_cv_ctime_args=3)
- fi
- if test -z "$ac_cv_ctime_args"; then
-     AC_MSG_RESULT(no)
- else
-     if test "$ac_cv_ctime_args" = 2; then
-         AC_DEFINE(HAVE_CTIME_R_2,1,[Define if ctime_r is present with 2 parameters.])
-     elif test "$ac_cv_ctime_args" = 3; then
-         AC_DEFINE(HAVE_CTIME_R_3,1,[Define if ctime_r is present with 3 parameters.])
-     fi
-     AC_MSG_RESULT([yes, and it takes $ac_cv_ctime_args arguments])
- fi 
-
 # OpenSSL settings
 AC_ARG_WITH(openssl,
     AC_HELP_STRING([--with-openssl=PATH], [where openssl is installed]),
@@ -146,6 +116,36 @@ AC_LANG(C++)
 AC_CXX_REQUIRE_STL
 AC_CXX_NAMESPACES
 
+# Thank you Solaris, really.
+AC_MSG_CHECKING(for ctime_r)
+ if test -z "$ac_cv_ctime_args"; then
+     AC_TRY_COMPILE(
+     [#include <time.h>],
+     [
+         time_t clock;
+         char buf[26];
+         ctime_r(&clock, buf);
+     ], ac_cv_ctime_args=2)
+
+     AC_TRY_COMPILE(
+     [#include <time.h>],
+     [
+         time_t clock;
+         char buf[26];
+         ctime_r(&clock, buf, 26);
+     ], ac_cv_ctime_args=3)
+ fi
+ if test -z "$ac_cv_ctime_args"; then
+     AC_MSG_RESULT(no)
+ else
+     if test "$ac_cv_ctime_args" = 2; then
+         AC_DEFINE(HAVE_CTIME_R_2,1,[Define if ctime_r is present with 2 parameters.])
+     elif test "$ac_cv_ctime_args" = 3; then
+         AC_DEFINE(HAVE_CTIME_R_3,1,[Define if ctime_r is present with 3 parameters.])
+     fi
+     AC_MSG_RESULT([yes, and it takes $ac_cv_ctime_args arguments])
+ fi 
+
 # log4shib settings (favor this version over the log4cpp code)
 AC_PATH_PROG(LOG4SHIB_CONFIG,log4shib-config)
 AC_ARG_WITH(log4shib,
@@ -222,6 +222,30 @@ AC_TRY_LINK(
         [AC_DEFINE(HAVE_LIBXERCESC,1,[Define if Xerces-C library was found])],
         [AC_MSG_ERROR([unable to link with Xerces])])
 
+AC_MSG_CHECKING([whether Xerces XMLString::release(XMLByte**) exists])
+AC_TRY_COMPILE([#include <xercesc/util/XMLString.hpp>],
+    [using namespace XERCES_CPP_NAMESPACE;
+      XMLByte* buf=NULL;
+      XMLString::release(&buf);
+    ],
+    [AC_MSG_RESULT([yes])]
+    [AC_DEFINE([SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE], [1], [Define to 1 if Xerces XMLString includes XMLByte release.])],
+    [AC_MSG_RESULT([no])])
+
+AC_MSG_CHECKING([whether Xerces DOMNodeFilter API returns a short])
+AC_TRY_COMPILE([#include <xercesc/dom/DOM.hpp>],
+    [using namespace XERCES_CPP_NAMESPACE;
+      class Blocker : public DOMNodeFilter {
+      public:
+        short acceptNode(const DOMNode* node) const {
+            return FILTER_REJECT;
+        }
+      };
+      static Blocker g_Blocker;
+    ],
+    [AC_MSG_RESULT([yes])]
+    [AC_DEFINE([SHIBSP_XERCESC_SHORT_ACCEPTNODE], [1], [Define to 1 if Xerces DOMNodeFilter API returns a short.])],
+    [AC_MSG_RESULT([no])])
 
 #XML-Tooling settings
 AC_ARG_WITH(xmltooling,
@@ -305,10 +329,10 @@ AC_CHECK_HEADER([saml/saml2/metadata/Metadata.h],,
 AC_TRY_LINK(
        [#include <saml/SAMLConfig.h>
 #include <saml/version.h>],
-       [#if _OPENSAML_VERSION >= 20000
+       [#if _OPENSAML_VERSION >= 20200
 opensaml::SAMLConfig::getConfig();
 #else
-#error Need OpenSAML version 2.0 or higher
+#error Need OpenSAML version 2.2 or higher
 #endif],
         [AC_DEFINE(HAVE_SAML,1,[Define if saml library was found])],
         [AC_MSG_ERROR([unable to link with OpenSAML, or version was too old])])
@@ -339,6 +363,8 @@ AC_SUBST(OPENSAMLXMLDIR)
 AC_SUBST(LITE_LIBS)
 AC_SUBST(XMLSEC_LIBS)
 
+AC_CONFIG_FILES([shibboleth.spec pkginfo Portfile])
+
 # output the underlying makefiles
 WANT_SUBDIRS="doc schemas configs shibsp shibd util"
 AC_CONFIG_FILES([Makefile doc/Makefile schemas/Makefile \
@@ -921,4 +947,3 @@ fi
 LIBTOOL="$LIBTOOL --silent"
 
 AC_OUTPUT
-
diff --git a/depend b/depend
index 5cd3481..e14a6ee 100644 (file)
--- a/depend
+++ b/depend
@@ -5,8 +5,8 @@ P SHIBxerces xerces-c
 P SHIBxmlsec xml-security-c
        1.4.0
 P SHIBxmltool xmltooling-c
-    1.1
+    1.2
 P SHIBosaml opensaml-c
-       2.1
+       2.2
 P SHIBlog4shib log4shib
     1.0
index 55dde7c..7e6bdfd 100644 (file)
@@ -1,28 +1,28 @@
-This FastCGI application library source and object code (the\r
-"Software") and its documentation (the "Documentation") are\r
-copyrighted by Open Market, Inc ("Open Market").  The following terms\r
-apply to all files associated with the Software and Documentation\r
-unless explicitly disclaimed in individual files.\r
-\r
-Open Market permits you to use, copy, modify, distribute, and license\r
-this Software and the Documentation for any purpose, provided that\r
-existing copyright notices are retained in all copies and that this\r
-notice is included verbatim in any distributions.  No written\r
-agreement, license, or royalty fee is required for any of the\r
-authorized uses.  Modifications to this Software and Documentation may\r
-be copyrighted by their authors and need not follow the licensing\r
-terms described here.  If modifications to this Software and\r
-Documentation have new licensing terms, the new terms must be clearly\r
-indicated on the first page of each file where they apply.\r
-\r
-OPEN MARKET MAKES NO EXPRESS OR IMPLIED WARRANTY WITH RESPECT TO THE\r
-SOFTWARE OR THE DOCUMENTATION, INCLUDING WITHOUT LIMITATION ANY\r
-WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN\r
-NO EVENT SHALL OPEN MARKET BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY\r
-DAMAGES ARISING FROM OR RELATING TO THIS SOFTWARE OR THE\r
-DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY INDIRECT, SPECIAL OR\r
-CONSEQUENTIAL DAMAGES OR SIMILAR DAMAGES, INCLUDING LOST PROFITS OR\r
-LOST DATA, EVEN IF OPEN MARKET HAS BEEN ADVISED OF THE POSSIBILITY OF\r
-SUCH DAMAGES.  THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS".\r
-OPEN MARKET HAS NO LIABILITY IN CONTRACT, TORT, NEGLIGENCE OR\r
-OTHERWISE ARISING OUT OF THIS SOFTWARE OR THE DOCUMENTATION.\r
+This FastCGI application library source and object code (the
+"Software") and its documentation (the "Documentation") are
+copyrighted by Open Market, Inc ("Open Market").  The following terms
+apply to all files associated with the Software and Documentation
+unless explicitly disclaimed in individual files.
+
+Open Market permits you to use, copy, modify, distribute, and license
+this Software and the Documentation for any purpose, provided that
+existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions.  No written
+agreement, license, or royalty fee is required for any of the
+authorized uses.  Modifications to this Software and Documentation may
+be copyrighted by their authors and need not follow the licensing
+terms described here.  If modifications to this Software and
+Documentation have new licensing terms, the new terms must be clearly
+indicated on the first page of each file where they apply.
+
+OPEN MARKET MAKES NO EXPRESS OR IMPLIED WARRANTY WITH RESPECT TO THE
+SOFTWARE OR THE DOCUMENTATION, INCLUDING WITHOUT LIMITATION ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN
+NO EVENT SHALL OPEN MARKET BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY
+DAMAGES ARISING FROM OR RELATING TO THIS SOFTWARE OR THE
+DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY INDIRECT, SPECIAL OR
+CONSEQUENTIAL DAMAGES OR SIMILAR DAMAGES, INCLUDING LOST PROFITS OR
+LOST DATA, EVEN IF OPEN MARKET HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.  THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS".
+OPEN MARKET HAS NO LIABILITY IN CONTRACT, TORT, NEGLIGENCE OR
+OTHERWISE ARISING OUT OF THIS SOFTWARE OR THE DOCUMENTATION.
index cbee875..b1e3f5a 100644 (file)
-                 GNU LESSER GENERAL PUBLIC LICENSE\r
-                      Version 2.1, February 1999\r
-\r
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.\r
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- Everyone is permitted to copy and distribute verbatim copies\r
- of this license document, but changing it is not allowed.\r
-\r
-[This is the first released version of the Lesser GPL.  It also counts\r
- as the successor of the GNU Library Public License, version 2, hence\r
- the version number 2.1.]\r
-\r
-                           Preamble\r
-\r
-  The licenses for most software are designed to take away your\r
-freedom to share and change it.  By contrast, the GNU General Public\r
-Licenses are intended to guarantee your freedom to share and change\r
-free software--to make sure the software is free for all its users.\r
-\r
-  This license, the Lesser General Public License, applies to some\r
-specially designated software packages--typically libraries--of the\r
-Free Software Foundation and other authors who decide to use it.  You\r
-can use it too, but we suggest you first think carefully about whether\r
-this license or the ordinary General Public License is the better\r
-strategy to use in any particular case, based on the explanations below.\r
-\r
-  When we speak of free software, we are referring to freedom of use,\r
-not price.  Our General Public Licenses are designed to make sure that\r
-you have the freedom to distribute copies of free software (and charge\r
-for this service if you wish); that you receive source code or can get\r
-it if you want it; that you can change the software and use pieces of\r
-it in new free programs; and that you are informed that you can do\r
-these things.\r
-\r
-  To protect your rights, we need to make restrictions that forbid\r
-distributors to deny you these rights or to ask you to surrender these\r
-rights.  These restrictions translate to certain responsibilities for\r
-you if you distribute copies of the library or if you modify it.\r
-\r
-  For example, if you distribute copies of the library, whether gratis\r
-or for a fee, you must give the recipients all the rights that we gave\r
-you.  You must make sure that they, too, receive or can get the source\r
-code.  If you link other code with the library, you must provide\r
-complete object files to the recipients, so that they can relink them\r
-with the library after making changes to the library and recompiling\r
-it.  And you must show them these terms so they know their rights.\r
-\r
-  We protect your rights with a two-step method: (1) we copyright the\r
-library, and (2) we offer you this license, which gives you legal\r
-permission to copy, distribute and/or modify the library.\r
-\r
-  To protect each distributor, we want to make it very clear that\r
-there is no warranty for the free library.  Also, if the library is\r
-modified by someone else and passed on, the recipients should know\r
-that what they have is not the original version, so that the original\r
-author's reputation will not be affected by problems that might be\r
-introduced by others.\r
-\f\r
-  Finally, software patents pose a constant threat to the existence of\r
-any free program.  We wish to make sure that a company cannot\r
-effectively restrict the users of a free program by obtaining a\r
-restrictive license from a patent holder.  Therefore, we insist that\r
-any patent license obtained for a version of the library must be\r
-consistent with the full freedom of use specified in this license.\r
-\r
-  Most GNU software, including some libraries, is covered by the\r
-ordinary GNU General Public License.  This license, the GNU Lesser\r
-General Public License, applies to certain designated libraries, and\r
-is quite different from the ordinary General Public License.  We use\r
-this license for certain libraries in order to permit linking those\r
-libraries into non-free programs.\r
-\r
-  When a program is linked with a library, whether statically or using\r
-a shared library, the combination of the two is legally speaking a\r
-combined work, a derivative of the original library.  The ordinary\r
-General Public License therefore permits such linking only if the\r
-entire combination fits its criteria of freedom.  The Lesser General\r
-Public License permits more lax criteria for linking other code with\r
-the library.\r
-\r
-  We call this license the "Lesser" General Public License because it\r
-does Less to protect the user's freedom than the ordinary General\r
-Public License.  It also provides other free software developers Less\r
-of an advantage over competing non-free programs.  These disadvantages\r
-are the reason we use the ordinary General Public License for many\r
-libraries.  However, the Lesser license provides advantages in certain\r
-special circumstances.\r
-\r
-  For example, on rare occasions, there may be a special need to\r
-encourage the widest possible use of a certain library, so that it becomes\r
-a de-facto standard.  To achieve this, non-free programs must be\r
-allowed to use the library.  A more frequent case is that a free\r
-library does the same job as widely used non-free libraries.  In this\r
-case, there is little to gain by limiting the free library to free\r
-software only, so we use the Lesser General Public License.\r
-\r
-  In other cases, permission to use a particular library in non-free\r
-programs enables a greater number of people to use a large body of\r
-free software.  For example, permission to use the GNU C Library in\r
-non-free programs enables many more people to use the whole GNU\r
-operating system, as well as its variant, the GNU/Linux operating\r
-system.\r
-\r
-  Although the Lesser General Public License is Less protective of the\r
-users' freedom, it does ensure that the user of a program that is\r
-linked with the Library has the freedom and the wherewithal to run\r
-that program using a modified version of the Library.\r
-\r
-  The precise terms and conditions for copying, distribution and\r
-modification follow.  Pay close attention to the difference between a\r
-"work based on the library" and a "work that uses the library".  The\r
-former contains code derived from the library, whereas the latter must\r
-be combined with the library in order to run.\r
-\f\r
-                 GNU LESSER GENERAL PUBLIC LICENSE\r
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
-\r
-  0. This License Agreement applies to any software library or other\r
-program which contains a notice placed by the copyright holder or\r
-other authorized party saying it may be distributed under the terms of\r
-this Lesser General Public License (also called "this License").\r
-Each licensee is addressed as "you".\r
-\r
-  A "library" means a collection of software functions and/or data\r
-prepared so as to be conveniently linked with application programs\r
-(which use some of those functions and data) to form executables.\r
-\r
-  The "Library", below, refers to any such software library or work\r
-which has been distributed under these terms.  A "work based on the\r
-Library" means either the Library or any derivative work under\r
-copyright law: that is to say, a work containing the Library or a\r
-portion of it, either verbatim or with modifications and/or translated\r
-straightforwardly into another language.  (Hereinafter, translation is\r
-included without limitation in the term "modification".)\r
-\r
-  "Source code" for a work means the preferred form of the work for\r
-making modifications to it.  For a library, complete source code means\r
-all the source code for all modules it contains, plus any associated\r
-interface definition files, plus the scripts used to control compilation\r
-and installation of the library.\r
-\r
-  Activities other than copying, distribution and modification are not\r
-covered by this License; they are outside its scope.  The act of\r
-running a program using the Library is not restricted, and output from\r
-such a program is covered only if its contents constitute a work based\r
-on the Library (independent of the use of the Library in a tool for\r
-writing it).  Whether that is true depends on what the Library does\r
-and what the program that uses the Library does.\r
-  \r
-  1. You may copy and distribute verbatim copies of the Library's\r
-complete source code as you receive it, in any medium, provided that\r
-you conspicuously and appropriately publish on each copy an\r
-appropriate copyright notice and disclaimer of warranty; keep intact\r
-all the notices that refer to this License and to the absence of any\r
-warranty; and distribute a copy of this License along with the\r
-Library.\r
-\r
-  You may charge a fee for the physical act of transferring a copy,\r
-and you may at your option offer warranty protection in exchange for a\r
-fee.\r
-\f\r
-  2. You may modify your copy or copies of the Library or any portion\r
-of it, thus forming a work based on the Library, and copy and\r
-distribute such modifications or work under the terms of Section 1\r
-above, provided that you also meet all of these conditions:\r
-\r
-    a) The modified work must itself be a software library.\r
-\r
-    b) You must cause the files modified to carry prominent notices\r
-    stating that you changed the files and the date of any change.\r
-\r
-    c) You must cause the whole of the work to be licensed at no\r
-    charge to all third parties under the terms of this License.\r
-\r
-    d) If a facility in the modified Library refers to a function or a\r
-    table of data to be supplied by an application program that uses\r
-    the facility, other than as an argument passed when the facility\r
-    is invoked, then you must make a good faith effort to ensure that,\r
-    in the event an application does not supply such function or\r
-    table, the facility still operates, and performs whatever part of\r
-    its purpose remains meaningful.\r
-\r
-    (For example, a function in a library to compute square roots has\r
-    a purpose that is entirely well-defined independent of the\r
-    application.  Therefore, Subsection 2d requires that any\r
-    application-supplied function or table used by this function must\r
-    be optional: if the application does not supply it, the square\r
-    root function must still compute square roots.)\r
-\r
-These requirements apply to the modified work as a whole.  If\r
-identifiable sections of that work are not derived from the Library,\r
-and can be reasonably considered independent and separate works in\r
-themselves, then this License, and its terms, do not apply to those\r
-sections when you distribute them as separate works.  But when you\r
-distribute the same sections as part of a whole which is a work based\r
-on the Library, the distribution of the whole must be on the terms of\r
-this License, whose permissions for other licensees extend to the\r
-entire whole, and thus to each and every part regardless of who wrote\r
-it.\r
-\r
-Thus, it is not the intent of this section to claim rights or contest\r
-your rights to work written entirely by you; rather, the intent is to\r
-exercise the right to control the distribution of derivative or\r
-collective works based on the Library.\r
-\r
-In addition, mere aggregation of another work not based on the Library\r
-with the Library (or with a work based on the Library) on a volume of\r
-a storage or distribution medium does not bring the other work under\r
-the scope of this License.\r
-\r
-  3. You may opt to apply the terms of the ordinary GNU General Public\r
-License instead of this License to a given copy of the Library.  To do\r
-this, you must alter all the notices that refer to this License, so\r
-that they refer to the ordinary GNU General Public License, version 2,\r
-instead of to this License.  (If a newer version than version 2 of the\r
-ordinary GNU General Public License has appeared, then you can specify\r
-that version instead if you wish.)  Do not make any other change in\r
-these notices.\r
-\f\r
-  Once this change is made in a given copy, it is irreversible for\r
-that copy, so the ordinary GNU General Public License applies to all\r
-subsequent copies and derivative works made from that copy.\r
-\r
-  This option is useful when you wish to copy part of the code of\r
-the Library into a program that is not a library.\r
-\r
-  4. You may copy and distribute the Library (or a portion or\r
-derivative of it, under Section 2) in object code or executable form\r
-under the terms of Sections 1 and 2 above provided that you accompany\r
-it with the complete corresponding machine-readable source code, which\r
-must be distributed under the terms of Sections 1 and 2 above on a\r
-medium customarily used for software interchange.\r
-\r
-  If distribution of object code is made by offering access to copy\r
-from a designated place, then offering equivalent access to copy the\r
-source code from the same place satisfies the requirement to\r
-distribute the source code, even though third parties are not\r
-compelled to copy the source along with the object code.\r
-\r
-  5. A program that contains no derivative of any portion of the\r
-Library, but is designed to work with the Library by being compiled or\r
-linked with it, is called a "work that uses the Library".  Such a\r
-work, in isolation, is not a derivative work of the Library, and\r
-therefore falls outside the scope of this License.\r
-\r
-  However, linking a "work that uses the Library" with the Library\r
-creates an executable that is a derivative of the Library (because it\r
-contains portions of the Library), rather than a "work that uses the\r
-library".  The executable is therefore covered by this License.\r
-Section 6 states terms for distribution of such executables.\r
-\r
-  When a "work that uses the Library" uses material from a header file\r
-that is part of the Library, the object code for the work may be a\r
-derivative work of the Library even though the source code is not.\r
-Whether this is true is especially significant if the work can be\r
-linked without the Library, or if the work is itself a library.  The\r
-threshold for this to be true is not precisely defined by law.\r
-\r
-  If such an object file uses only numerical parameters, data\r
-structure layouts and accessors, and small macros and small inline\r
-functions (ten lines or less in length), then the use of the object\r
-file is unrestricted, regardless of whether it is legally a derivative\r
-work.  (Executables containing this object code plus portions of the\r
-Library will still fall under Section 6.)\r
-\r
-  Otherwise, if the work is a derivative of the Library, you may\r
-distribute the object code for the work under the terms of Section 6.\r
-Any executables containing that work also fall under Section 6,\r
-whether or not they are linked directly with the Library itself.\r
-\f\r
-  6. As an exception to the Sections above, you may also combine or\r
-link a "work that uses the Library" with the Library to produce a\r
-work containing portions of the Library, and distribute that work\r
-under terms of your choice, provided that the terms permit\r
-modification of the work for the customer's own use and reverse\r
-engineering for debugging such modifications.\r
-\r
-  You must give prominent notice with each copy of the work that the\r
-Library is used in it and that the Library and its use are covered by\r
-this License.  You must supply a copy of this License.  If the work\r
-during execution displays copyright notices, you must include the\r
-copyright notice for the Library among them, as well as a reference\r
-directing the user to the copy of this License.  Also, you must do one\r
-of these things:\r
-\r
-    a) Accompany the work with the complete corresponding\r
-    machine-readable source code for the Library including whatever\r
-    changes were used in the work (which must be distributed under\r
-    Sections 1 and 2 above); and, if the work is an executable linked\r
-    with the Library, with the complete machine-readable "work that\r
-    uses the Library", as object code and/or source code, so that the\r
-    user can modify the Library and then relink to produce a modified\r
-    executable containing the modified Library.  (It is understood\r
-    that the user who changes the contents of definitions files in the\r
-    Library will not necessarily be able to recompile the application\r
-    to use the modified definitions.)\r
-\r
-    b) Use a suitable shared library mechanism for linking with the\r
-    Library.  A suitable mechanism is one that (1) uses at run time a\r
-    copy of the library already present on the user's computer system,\r
-    rather than copying library functions into the executable, and (2)\r
-    will operate properly with a modified version of the library, if\r
-    the user installs one, as long as the modified version is\r
-    interface-compatible with the version that the work was made with.\r
-\r
-    c) Accompany the work with a written offer, valid for at\r
-    least three years, to give the same user the materials\r
-    specified in Subsection 6a, above, for a charge no more\r
-    than the cost of performing this distribution.\r
-\r
-    d) If distribution of the work is made by offering access to copy\r
-    from a designated place, offer equivalent access to copy the above\r
-    specified materials from the same place.\r
-\r
-    e) Verify that the user has already received a copy of these\r
-    materials or that you have already sent this user a copy.\r
-\r
-  For an executable, the required form of the "work that uses the\r
-Library" must include any data and utility programs needed for\r
-reproducing the executable from it.  However, as a special exception,\r
-the materials to be distributed need not include anything that is\r
-normally distributed (in either source or binary form) with the major\r
-components (compiler, kernel, and so on) of the operating system on\r
-which the executable runs, unless that component itself accompanies\r
-the executable.\r
-\r
-  It may happen that this requirement contradicts the license\r
-restrictions of other proprietary libraries that do not normally\r
-accompany the operating system.  Such a contradiction means you cannot\r
-use both them and the Library together in an executable that you\r
-distribute.\r
-\f\r
-  7. You may place library facilities that are a work based on the\r
-Library side-by-side in a single library together with other library\r
-facilities not covered by this License, and distribute such a combined\r
-library, provided that the separate distribution of the work based on\r
-the Library and of the other library facilities is otherwise\r
-permitted, and provided that you do these two things:\r
-\r
-    a) Accompany the combined library with a copy of the same work\r
-    based on the Library, uncombined with any other library\r
-    facilities.  This must be distributed under the terms of the\r
-    Sections above.\r
-\r
-    b) Give prominent notice with the combined library of the fact\r
-    that part of it is a work based on the Library, and explaining\r
-    where to find the accompanying uncombined form of the same work.\r
-\r
-  8. You may not copy, modify, sublicense, link with, or distribute\r
-the Library except as expressly provided under this License.  Any\r
-attempt otherwise to copy, modify, sublicense, link with, or\r
-distribute the Library is void, and will automatically terminate your\r
-rights under this License.  However, parties who have received copies,\r
-or rights, from you under this License will not have their licenses\r
-terminated so long as such parties remain in full compliance.\r
-\r
-  9. You are not required to accept this License, since you have not\r
-signed it.  However, nothing else grants you permission to modify or\r
-distribute the Library or its derivative works.  These actions are\r
-prohibited by law if you do not accept this License.  Therefore, by\r
-modifying or distributing the Library (or any work based on the\r
-Library), you indicate your acceptance of this License to do so, and\r
-all its terms and conditions for copying, distributing or modifying\r
-the Library or works based on it.\r
-\r
-  10. Each time you redistribute the Library (or any work based on the\r
-Library), the recipient automatically receives a license from the\r
-original licensor to copy, distribute, link with or modify the Library\r
-subject to these terms and conditions.  You may not impose any further\r
-restrictions on the recipients' exercise of the rights granted herein.\r
-You are not responsible for enforcing compliance by third parties with\r
-this License.\r
-\f\r
-  11. If, as a consequence of a court judgment or allegation of patent\r
-infringement or for any other reason (not limited to patent issues),\r
-conditions are imposed on you (whether by court order, agreement or\r
-otherwise) that contradict the conditions of this License, they do not\r
-excuse you from the conditions of this License.  If you cannot\r
-distribute so as to satisfy simultaneously your obligations under this\r
-License and any other pertinent obligations, then as a consequence you\r
-may not distribute the Library at all.  For example, if a patent\r
-license would not permit royalty-free redistribution of the Library by\r
-all those who receive copies directly or indirectly through you, then\r
-the only way you could satisfy both it and this License would be to\r
-refrain entirely from distribution of the Library.\r
-\r
-If any portion of this section is held invalid or unenforceable under any\r
-particular circumstance, the balance of the section is intended to apply,\r
-and the section as a whole is intended to apply in other circumstances.\r
-\r
-It is not the purpose of this section to induce you to infringe any\r
-patents or other property right claims or to contest validity of any\r
-such claims; this section has the sole purpose of protecting the\r
-integrity of the free software distribution system which is\r
-implemented by public license practices.  Many people have made\r
-generous contributions to the wide range of software distributed\r
-through that system in reliance on consistent application of that\r
-system; it is up to the author/donor to decide if he or she is willing\r
-to distribute software through any other system and a licensee cannot\r
-impose that choice.\r
-\r
-This section is intended to make thoroughly clear what is believed to\r
-be a consequence of the rest of this License.\r
-\r
-  12. If the distribution and/or use of the Library is restricted in\r
-certain countries either by patents or by copyrighted interfaces, the\r
-original copyright holder who places the Library under this License may add\r
-an explicit geographical distribution limitation excluding those countries,\r
-so that distribution is permitted only in or among countries not thus\r
-excluded.  In such case, this License incorporates the limitation as if\r
-written in the body of this License.\r
-\r
-  13. The Free Software Foundation may publish revised and/or new\r
-versions of the Lesser General Public License from time to time.\r
-Such new versions will be similar in spirit to the present version,\r
-but may differ in detail to address new problems or concerns.\r
-\r
-Each version is given a distinguishing version number.  If the Library\r
-specifies a version number of this License which applies to it and\r
-"any later version", you have the option of following the terms and\r
-conditions either of that version or of any later version published by\r
-the Free Software Foundation.  If the Library does not specify a\r
-license version number, you may choose any version ever published by\r
-the Free Software Foundation.\r
-\f\r
-  14. If you wish to incorporate parts of the Library into other free\r
-programs whose distribution conditions are incompatible with these,\r
-write to the author to ask for permission.  For software which is\r
-copyrighted by the Free Software Foundation, write to the Free\r
-Software Foundation; we sometimes make exceptions for this.  Our\r
-decision will be guided by the two goals of preserving the free status\r
-of all derivatives of our free software and of promoting the sharing\r
-and reuse of software generally.\r
-\r
-                           NO WARRANTY\r
-\r
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\r
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\r
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\r
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY\r
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\r
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\r
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\r
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
-\r
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\r
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\r
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\r
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\r
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\r
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\r
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\r
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\r
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
-DAMAGES.\r
-\r
-                    END OF TERMS AND CONDITIONS\r
-\f\r
-           How to Apply These Terms to Your New Libraries\r
-\r
-  If you develop a new library, and you want it to be of the greatest\r
-possible use to the public, we recommend making it free software that\r
-everyone can redistribute and change.  You can do so by permitting\r
-redistribution under these terms (or, alternatively, under the terms of the\r
-ordinary General Public License).\r
-\r
-  To apply these terms, attach the following notices to the library.  It is\r
-safest to attach them to the start of each source file to most effectively\r
-convey the exclusion of warranty; and each file should have at least the\r
-"copyright" line and a pointer to where the full notice is found.\r
-\r
-    <one line to give the library's name and a brief idea of what it does.>\r
-    Copyright (C) <year>  <name of author>\r
-\r
-    This library is free software; you can redistribute it and/or\r
-    modify it under the terms of the GNU Lesser General Public\r
-    License as published by the Free Software Foundation; either\r
-    version 2.1 of the License, or (at your option) any later version.\r
-\r
-    This library is distributed in the hope that it will be useful,\r
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-    Lesser General Public License for more details.\r
-\r
-    You should have received a copy of the GNU Lesser General Public\r
-    License along with this library; if not, write to the Free Software\r
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-Also add information on how to contact you by electronic and paper mail.\r
-\r
-You should also get your employer (if you work as a programmer) or your\r
-school, if any, to sign a "copyright disclaimer" for the library, if\r
-necessary.  Here is a sample; alter the names:\r
-\r
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the\r
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\r
-\r
-  <signature of Ty Coon>, 1 April 1990\r
-  Ty Coon, President of Vice\r
-\r
-That's all there is to it!\r
-\r
-\r
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
index 3b312ee..03f93ee 100644 (file)
@@ -1,6 +1,10 @@
 AUTOMAKE_OPTIONS = foreign
 
-pkgdocdir = $(datadir)/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE@-@PACKAGE_VERSION@
+
+install-data-hook:
+       cp -r api $(DESTDIR)$(pkgdocdir)
+       rm -rf `find $(DESTDIR)$(pkgdocdir)/api -name .svn`
 
 docfiles = \
        CREDITS.txt \
index 7e4107e..ab75e34 100644 (file)
@@ -257,7 +257,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 xs = @xs@
 AUTOMAKE_OPTIONS = foreign
-pkgdocdir = $(datadir)/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE@-@PACKAGE_VERSION@
 docfiles = \
        CREDITS.txt \
        LICENSE.txt \
@@ -415,6 +415,8 @@ info: info-am
 info-am:
 
 install-data-am: install-pkgdocDATA
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
 
 install-exec-am:
 
@@ -445,13 +447,18 @@ uninstall-am: uninstall-info-am uninstall-pkgdocDATA
 .PHONY: all all-am check check-am clean clean-generic clean-libtool \
        distclean distclean-generic distclean-libtool distdir dvi \
        dvi-am html html-am info info-am install install-am \
-       install-data install-data-am install-exec install-exec-am \
-       install-info install-info-am install-man install-pkgdocDATA \
-       install-strip installcheck installcheck-am installdirs \
-       maintainer-clean maintainer-clean-generic mostlyclean \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       uninstall uninstall-am uninstall-info-am uninstall-pkgdocDATA
-
+       install-data install-data-am install-data-hook install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-pkgdocDATA install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+       ps ps-am uninstall uninstall-am uninstall-info-am \
+       uninstall-pkgdocDATA
+
+
+install-data-hook:
+       cp -r api $(DESTDIR)$(pkgdocdir)
+       rm -rf `find $(DESTDIR)$(pkgdocdir)/api -name .svn`
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index cdc9ade..4027788 100644 (file)
-\r
-  LICENSE ISSUES\r
-  ==============\r
-\r
-  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of\r
-  the OpenSSL License and the original SSLeay license apply to the toolkit.\r
-  See below for the actual license texts. Actually both licenses are BSD-style\r
-  Open Source licenses. In case of any license issues related to OpenSSL\r
-  please contact openssl-core@openssl.org.\r
-\r
-  OpenSSL License\r
-  ---------------\r
-\r
-/* ====================================================================\r
- * Copyright (c) 1998-2004 The OpenSSL Project.  All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- *\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer. \r
- *\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in\r
- *    the documentation and/or other materials provided with the\r
- *    distribution.\r
- *\r
- * 3. All advertising materials mentioning features or use of this\r
- *    software must display the following acknowledgment:\r
- *    "This product includes software developed by the OpenSSL Project\r
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"\r
- *\r
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to\r
- *    endorse or promote products derived from this software without\r
- *    prior written permission. For written permission, please contact\r
- *    openssl-core@openssl.org.\r
- *\r
- * 5. Products derived from this software may not be called "OpenSSL"\r
- *    nor may "OpenSSL" appear in their names without prior written\r
- *    permission of the OpenSSL Project.\r
- *\r
- * 6. Redistributions of any form whatsoever must retain the following\r
- *    acknowledgment:\r
- *    "This product includes software developed by the OpenSSL Project\r
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\r
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\r
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * ====================================================================\r
- *\r
- * This product includes cryptographic software written by Eric Young\r
- * (eay@cryptsoft.com).  This product includes software written by Tim\r
- * Hudson (tjh@cryptsoft.com).\r
- *\r
- */\r
-\r
- Original SSLeay License\r
- -----------------------\r
-\r
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\r
- * All rights reserved.\r
- *\r
- * This package is an SSL implementation written\r
- * by Eric Young (eay@cryptsoft.com).\r
- * The implementation was written so as to conform with Netscapes SSL.\r
- * \r
- * This library is free for commercial and non-commercial use as long as\r
- * the following conditions are aheared to.  The following conditions\r
- * apply to all code found in this distribution, be it the RC4, RSA,\r
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\r
- * included with this distribution is covered by the same copyright terms\r
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).\r
- * \r
- * Copyright remains Eric Young's, and as such any Copyright notices in\r
- * the code are not to be removed.\r
- * If this package is used in a product, Eric Young should be given attribution\r
- * as the author of the parts of the library used.\r
- * This can be in the form of a textual message at program startup or\r
- * in documentation (online or textual) provided with the package.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- * 3. All advertising materials mentioning features or use of this software\r
- *    must display the following acknowledgement:\r
- *    "This product includes cryptographic software written by\r
- *     Eric Young (eay@cryptsoft.com)"\r
- *    The word 'cryptographic' can be left out if the rouines from the library\r
- *    being used are not cryptographic related :-).\r
- * 4. If you include any Windows specific code (or a derivative thereof) from \r
- *    the apps directory (application code) you must include an acknowledgement:\r
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"\r
- * \r
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\r
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
- * SUCH DAMAGE.\r
- * \r
- * The licence and distribution terms for any publically available version or\r
- * derivative of this code cannot be changed.  i.e. this code cannot simply be\r
- * copied and put under another distribution licence\r
- * [including the GNU Public Licence.]\r
- */\r
-\r
+
+  LICENSE ISSUES
+  ==============
+
+  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+  the OpenSSL License and the original SSLeay license apply to the toolkit.
+  See below for the actual license texts. Actually both licenses are BSD-style
+  Open Source licenses. In case of any license issues related to OpenSSL
+  please contact openssl-core@openssl.org.
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
index 7b15351..6443108 100644 (file)
@@ -1,5 +1,4 @@
-August 8, 2008
-Version 2.1
+Version 2.2.1
 
 Welcome to Internet2's Shibboleth
 
index 3efe64b..66ee2a7 100644 (file)
@@ -1,14 +1,14 @@
 Release Notes
 
 Shibboleth Native SP
-2.1
-8/8/2008
+2.2.1
 
 NOTE: The shibboleth2.xml configuration format in this release
-is fully compatible with the 2.0 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=10129&status=5&status=6&sorter/field=issuekey&sorter/order=ASC
+https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC
 
 Fully Supported
 
@@ -38,7 +38,8 @@ Fully Supported
 - Metadata Providers
        - Bulk resolution via local file, or URL with local file backup
        - Dynamic resolution and caching based on entityID 
-       - Filtering based on whitelist, blacklist, or signature verification  
+       - Filtering based on whitelist, blacklist, or signature verification
+       - Support for enhanced PKI processing in transport and signature verification
 
 - Metadata Generation Handler
     - Generates and optionally signs SAML metadata based on SP configuration
@@ -58,6 +59,7 @@ Fully Supported
        - XML signing
        - Simple "blob" signing
        - TLS X.509 certificate authentication
+       - SAML condition handling
 
 - Client transport authentication to SOAP endpoints via libcurl
        - TLS X.509 client certificates
@@ -74,6 +76,10 @@ Fully Supported
                - Strings
                - Value/scope pairs (legacy and value@scope syntaxes supported)
                - NameIDs
+        - XML to base64-encoded XML
+               - DOM to internal data structure
+               - KeyInfo-based data, including metadata-derived KeyDescriptors
+               - Metadata EntityAttributes extension "tags"
 
 - Attribute Filtering
        - Policy language compatible with IdP filtering, except that references
@@ -89,7 +95,7 @@ Fully Supported
 
 - Enhanced Spoofing Detection
        - Detects and blocks client headers that would match known attribute headers
-       - Does not support Apache mod_rewrite, but can be disabled when necessary
+       - Key-based mechanism to handle internal server redirection while maintaining protection
 
 - ODBC Clustering Support
        - Tested against a few different servers with various drivers
@@ -102,6 +108,9 @@ Fully Supported
     - Reporting of SAML status errors
     - Optional redirection to custom error handler
 
+- Form POST data preservation
+    - Support on Apache for preserving URL-encoded form data across SSO 
+
 - Apache module enhancements
     - "OR" coexistence with other authorization modules
     - htaccess-based override of any valid RequestMap property 
index a3eb681..a11cebe 100644 (file)
@@ -1,39 +1,39 @@
-body {\r
-       background-color: #FFFFFF;\r
-       font-family : Geneva, Arial, Helvetica, sans-serif;\r
-       text-align: center;\r
-       letter-spacing: 0px;\r
-       color: black;\r
-       text-align: left;\r
-}\r
-\r
-p {\r
-       font-size: 10pt;\r
-       margin-top: 20px;\r
-       margin-bottom: 20px;\r
-}\r
-\r
-\r
-li {\r
-\r
-       font-size: 10pt;\r
-}\r
-\r
-h1 {\r
-       font-size: 14pt;\r
-       font-weight: bold;\r
-}\r
-\r
-h2 { \r
-       font-size: 12pt;\r
-       font-weight: bold;\r
-}\r
-\r
-.error {\r
-       font-size: 10pt;\r
-       font-weight: bold;\r
-}\r
-\r
-img {\r
-       margin-bottom: 15px;\r
+body {
+       background-color: #FFFFFF;
+       font-family : Geneva, Arial, Helvetica, sans-serif;
+       text-align: center;
+       letter-spacing: 0px;
+       color: black;
+       text-align: left;
+}
+
+p {
+       font-size: 10pt;
+       margin-top: 20px;
+       margin-bottom: 20px;
+}
+
+
+li {
+
+       font-size: 10pt;
+}
+
+h1 {
+       font-size: 14pt;
+       font-weight: bold;
+}
+
+h2 { 
+       font-size: 12pt;
+       font-weight: bold;
+}
+
+.error {
+       font-size: 10pt;
+       font-weight: bold;
+}
+
+img {
+       margin-bottom: 15px;
 }
\ No newline at end of file
index e4688de..9bda4f6 100644 (file)
@@ -51,6 +51,9 @@ AC_DEFUN([DX_FEATURE_xml],  OFF)
 AC_DEFUN([DX_FEATURE_pdf],  ON)
 AC_DEFUN([DX_FEATURE_ps],   ON)
 
+# Compatibility with older autoconf versions.
+m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))])
+
 ## --------------- ##
 ## Private macros. ##
 ## --------------- ##
@@ -78,7 +81,7 @@ AC_DEFUN([DX_REQUIRE_PROG], [
 AC_PATH_TOOL([$1], [$2])
 if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
     AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
-    AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0)
+    AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
 fi
 ])
 
@@ -101,7 +104,7 @@ test "$DX_FLAG_$1" = "$2" \
 # ----------------------------------------------------------
 # Turn off the DX_CURRENT_FEATURE if the required feature is off.
 AC_DEFUN([DX_CLEAR_DEPEND], [
-test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0)
+test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
 ])
 
 # DX_FEATURE_ARG(FEATURE, DESCRIPTION,
index 282dad9..59f4417 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -115,6 +115,9 @@ public:
         return s ? atol(s) : 0;\r
     }\r
     string getRemoteAddr() const {\r
+        string ret = AbstractSPRequest::getRemoteAddr();\r
+        if (!ret.empty())\r
+            return ret;\r
         const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
         return s ? s : "";\r
     }\r
@@ -172,6 +175,23 @@ public:
         }\r
         return "";\r
     }\r
+    void setAuthType(const char* authtype) {\r
+        if (authtype)\r
+            m_request_headers["AUTH_TYPE"] = authtype;\r
+        else\r
+            m_request_headers.erase("AUTH_TYPE");\r
+    }\r
+    string getAuthType() const {\r
+        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
+        if (i != m_request_headers.end())\r
+            return i->second;\r
+        else {\r
+            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
+            if (auth_type)\r
+                return auth_type;\r
+        }\r
+        return "";\r
+    }\r
     void setResponseHeader(const char* name, const char* value) {\r
         // Set for later.\r
         if (value)\r
index 4a2069a..c9b4c1d 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,1,0,0\r
- PRODUCTVERSION 2,1,0,0\r
+ FILEVERSION 2,2,1,0\r
+ PRODUCTVERSION 2,2,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth FastCGI Authorizer\0"\r
-            VALUE "FileVersion", "2, 1, 0, 0\0"\r
+            VALUE "FileVersion", "2, 2, 1, 0\0"\r
             VALUE "InternalName", "shibauthorizer\0"\r
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"\r
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibauthorizer.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.1\0"\r
-            VALUE "ProductVersion", "2, 1, 0, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
+            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index e8f395a..56e1896 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="shibauthorizer"\r
        ProjectGUID="{8CF7DDFA-EAA0-416E-853E-3DCB210C4AE0}"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)&quot;"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TypeLibraryName=".\shibauthorizer___Win32_Debug/shibauthorizer.tlb"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\shibauthorizer___Win32_Release/shibauthorizer.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
-                               BrowseInformation="1"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               EnableFunctionLevelLinking="true"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
-                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"\r
-                               LinkIncremental="2"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"\r
+                               LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)&quot;"\r
+                               ProgramDatabaseFile=".\shibauthorizer___Win32_Release/shibauthorizer.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
-                               TypeLibraryName=".\shibauthorizer___Win32_Release/shibauthorizer.tlb"\r
+                               TypeLibraryName=".\shibauthorizer___Win32_Debug/shibauthorizer.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
+                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"\r
-                               LinkIncremental="1"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"\r
+                               LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
-                               ProgramDatabaseFile=".\shibauthorizer___Win32_Release/shibauthorizer.pdb"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)&quot;"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               TargetMachine="17"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)&quot;"\r
                                GenerateDebugInformation="true"\r
-                               ProgramDatabaseFile=".\shibauthorizer___Win32_Debug/shibauthorizer.pdb"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Debug|Win32"\r
+                               Name="Release|x64"\r
                                >\r
                                <Tool\r
                                        Name="VCCLCompilerTool"\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Release|x64"\r
+                               Name="Debug|Win32"\r
                                >\r
                                <Tool\r
                                        Name="VCCLCompilerTool"\r
index 3582833..1537e33 100644 (file)
@@ -120,6 +120,9 @@ public:
         return s ? s : "";\r
     }\r
     string getRemoteAddr() const {\r
+        string ret = AbstractSPRequest::getRemoteAddr();\r
+        if (!ret.empty())\r
+            return ret;\r
         const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
         return s ? s : "";\r
     }\r
index c8bded3..4bccb0f 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,1,0,0\r
- PRODUCTVERSION 2,1,0,0\r
+ FILEVERSION 2,2,1,0\r
+ PRODUCTVERSION 2,2,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth FastCGI Responder\0"\r
-            VALUE "FileVersion", "2, 1, 0, 0\0"\r
+            VALUE "FileVersion", "2, 2, 1, 0\0"\r
             VALUE "InternalName", "shibresponder\0"\r
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"\r
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibresponder.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.1\0"\r
-            VALUE "ProductVersion", "2, 1, 0, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
+            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index 0d6518f..164fa25 100644 (file)
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="shibresponder"\r
        ProjectGUID="{B2423DCE-048D-4BAA-9AB9-F5D1FCDD3D25}"\r
+       RootNamespace="shibresponder"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)&quot;"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TypeLibraryName=".\shibresponder___Win32_Debug/shibresponder.tlb"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\shibresponder___Win32_Release/shibresponder.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
-                               BrowseInformation="1"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               EnableFunctionLevelLinking="true"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
-                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"\r
-                               LinkIncremental="2"\r
+                               AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"\r
+                               LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)&quot;"\r
+                               ProgramDatabaseFile=".\shibresponder___Win32_Release/shibresponder.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
                        UseOfMFC="0"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
-                               TypeLibraryName=".\shibresponder___Win32_Release/shibresponder.tlb"\r
+                               TypeLibraryName=".\shibresponder___Win32_Debug/shibresponder.tlb"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
+                               DebugInformationFormat="4"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"\r
-                               LinkIncremental="1"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"\r
+                               LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
-                               ProgramDatabaseFile=".\shibresponder___Win32_Release/shibresponder.pdb"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)&quot;"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               TargetMachine="17"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"\r
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;,\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;&quot;\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)&quot;"\r
                                GenerateDebugInformation="true"\r
-                               ProgramDatabaseFile=".\shibresponder___Win32_Debug/shibresponder.pdb"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Debug|Win32"\r
+                               Name="Release|x64"\r
                                >\r
                                <Tool\r
                                        Name="VCCLCompilerTool"\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
-                               Name="Release|x64"\r
+                               Name="Debug|Win32"\r
                                >\r
                                <Tool\r
                                        Name="VCCLCompilerTool"\r
index 38ea0c2..148a079 100644 (file)
@@ -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 @@
 
 #define _CRT_NONSTDC_NO_DEPRECATE 1
 #define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_RAND_S
 
 #include <shibsp/AbstractSPRequest.h>
 #include <shibsp/SPConfig.h>
@@ -88,18 +89,14 @@ namespace {
         set<string> m_aliases;
     };
 
-    struct context_t {
-       char* m_user;
-       bool m_checked;
-    };
-
     HINSTANCE g_hinstDLL;
     SPConfig* g_Config = NULL;
     map<string,site_t> g_Sites;
     bool g_bNormalizeRequest = true;
-    string g_unsetHeaderValue;
+    string g_unsetHeaderValue,g_spoofKey;
     bool g_checkSpoofing = true;
     bool g_catchAll = false;
+    bool g_bSafeHeaderNames = false;
     vector<string> g_NoCerts;
 }
 
@@ -117,6 +114,17 @@ BOOL LogEvent(
     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)
@@ -189,18 +197,72 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
     Locker locker(sp);
     const PropertySet* props=sp->getPropertySet("InProcess");
     if (props) {
-        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
-        if (unsetValue.first)
-            g_unsetHeaderValue = unsetValue.second;
         pair<bool,bool> flag=props->getBool("checkSpoofing");
         g_checkSpoofing = !flag.first || flag.second;
         flag=props->getBool("catchAll");
         g_catchAll = flag.first && flag.second;
 
+<<<<<<< .mine
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        if (unsetValue.first)
+            g_unsetHeaderValue = unsetValue.second;
+        if (g_checkSpoofing) {
+            unsetValue = props->getString("spoofKey");
+            if (unsetValue.first)
+                g_spoofKey = unsetValue.second;
+            else {
+                unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
+                if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
+                    ostringstream keystr;
+                    keystr << randkey << randkey2 << randkey3 << randkey4;
+                    g_spoofKey = keystr.str();
+                }
+                else {
+                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
+                    g_Config->term();
+                    g_Config=NULL;
+                    return FALSE;
+                }
+            }
+        }
+
+=======
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        if (unsetValue.first)
+            g_unsetHeaderValue = unsetValue.second;
+        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;
+                }
+            }
+        }
+
+>>>>>>> .r3097
         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));
@@ -348,10 +410,11 @@ class ShibTargetIsapiF : public AbstractSPRequest
   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) {
+      : 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);
@@ -382,13 +445,14 @@ public:
     if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
         m_hostname=site.m_name;
 
-    if (!pfc->pFilterContext) {
-        pfc->pFilterContext = pfc->AllocMem(pfc, sizeof(context_t), NULL);
-        if (static_cast<context_t*>(pfc->pFilterContext)) {
-            static_cast<context_t*>(pfc->pFilterContext)->m_user = NULL;
-            static_cast<context_t*>(pfc->pFilterContext)->m_checked = false;
-        }
+    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() { }
 
@@ -401,10 +465,15 @@ public:
   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,"REQUEST_METHOD",var,5,false);
+        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
         if (!var.empty())
             m_method = var;
     }
@@ -413,16 +482,14 @@ public:
   string getContentType() const {
     if (m_content_type.empty()) {
         dynabuf var(32);
-        GetServerVariable(m_pfc,"CONTENT_TYPE",var,32,false);
+        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
         if (!var.empty())
             m_content_type = var;
     }
     return m_content_type;
   }
-  long getContentLength() const {
-      return 0;
-  }
   string getRemoteAddr() const {
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();
     if (m_remote_addr.empty()) {
         dynabuf var(16);
         GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
@@ -433,43 +500,64 @@ public:
   }
   void log(SPLogLevel level, const string& msg) {
     AbstractSPRequest::log(level,msg);
-    if (level >= SPError)
+    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_pfc->pFilterContext && !static_cast<context_t*>(m_pfc->pFilterContext)->m_checked) {
+    if (g_checkSpoofing && m_firsttime) {
         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));
+               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()));
     }
-    string hdr(!strcmp(rawname,"REMOTE_USER") ? "remote-user" : rawname);
-    hdr += ':';
-    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+    if (g_bSafeHeaderNames) {
+        string hdr = makeSafeHeader(rawname);
+        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+    }
+    else if (!strcmp(rawname,"REMOTE_USER")) {
+           m_pn->SetHeader(m_pfc, "remote-user:", const_cast<char*>(g_unsetHeaderValue.c_str()));
+        m_pn->SetHeader(m_pfc, "remote_user:", const_cast<char*>(g_unsetHeaderValue.c_str()));
+       }
+       else {
+           string hdr = string(rawname) + ':';
+           m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+       }
   }
   void setHeader(const char* name, const char* value) {
-    string hdr(name);
-    hdr += ':';
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
     m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
   }
+  string getSecureHeader(const char* name) const {
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
+    dynabuf buf(256);
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
+    return string(buf.empty() ? "" : buf);
+  }
   string getHeader(const char* name) const {
     string hdr(name);
     hdr += ':';
     dynabuf buf(256);
     GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf);
+    return string(buf.empty() ? "" : buf);
   }
   void setRemoteUser(const char* user) {
     setHeader("remote-user", user);
-    if (m_pfc->pFilterContext) {
-        if (!user || !*user)
-            static_cast<context_t*>(m_pfc->pFilterContext)->m_user = NULL;
-        else if (static_cast<context_t*>(m_pfc->pFilterContext)->m_user = (char*)m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
-            strcpy(static_cast<context_t*>(m_pfc->pFilterContext)->m_user, user);
-    }
+    if (!user || !*user)
+        m_pfc->pFilterContext = NULL;
+    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
+        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
   }
   string getRemoteUser() const {
-    return getHeader("remote-user");
+    return getSecureHeader("remote-user");
   }
   void setResponseHeader(const char* name, const char* value) {
     // Set for later.
@@ -527,8 +615,8 @@ public:
   }
 
   // The filter never processes the POST, so stub these methods.
-  const char* getQueryString() const { throw IOException("getQueryString not implemented"); }
-  const char* getRequestBody() const { throw IOException("getRequestBody not implemented"); }
+  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)
@@ -552,8 +640,8 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
 {
     // Is this a log notification?
     if (notificationType==SF_NOTIFY_LOG) {
-        if (pfc->pFilterContext && static_cast<context_t*>(pfc->pFilterContext)->m_user)
-               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=static_cast<context_t*>(pfc->pFilterContext)->m_user;
+        if (pfc->pFilterContext)
+               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);
         return SF_STATUS_REQ_NEXT_NOTIFICATION;
     }
 
@@ -577,8 +665,8 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
 
         // "false" because we don't override the Shib settings
         pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
-        if (pfc->pFilterContext)
-            static_cast<context_t*>(pfc->pFilterContext)->m_checked = true;
+        if (!g_spoofKey.empty())
+            pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast<char*>(g_spoofKey.c_str()));
         if (res.first) return res.second;
 
         // "false" because we don't override the Shib settings
@@ -754,6 +842,7 @@ public:
     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);
@@ -764,7 +853,7 @@ public:
   }
   void log(SPLogLevel level, const string& msg) const {
       AbstractSPRequest::log(level,msg);
-      if (level >= SPError)
+      if (level >= SPCrit)
           LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
   }
   string getHeader(const char* name) const {
@@ -796,13 +885,19 @@ public:
         throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
     else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
       m_gotBody=true;
-      char buf[8192];
       DWORD datalen=m_lpECB->cbTotalBytes;
+      if (m_lpECB->cbAvailable > 0) {
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
+        datalen-=m_lpECB->cbAvailable;
+      }
+      char buf[8192];
       while (datalen) {
         DWORD buflen=8192;
         BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
-        if (!ret || !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;
       }
@@ -872,10 +967,14 @@ public:
 
         if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {
             if (ccex.CertContext.cbCertEncoded) {
-                unsigned int outlen;
+                xsecsize_t outlen;
                 XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
                 m_certs.push_back(reinterpret_cast<char*>(serialized));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
                 XMLString::release(&serialized);
+#else
+                XMLString::release((char**)&serialized);
+#endif
             }
         }
       }
diff --git a/isapi_shib/isapi_shib.cpp.mine b/isapi_shib/isapi_shib.cpp.mine
new file mode 100644 (file)
index 0000000..9d2278e
--- /dev/null
@@ -0,0 +1,993 @@
+/*\r
+ *  Copyright 2001-2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * isapi_shib.cpp\r
+ *\r
+ * Shibboleth ISAPI filter\r
+ */\r
+\r
+#define SHIBSP_LITE\r
+#include "config_win32.h"\r
+\r
+#define _CRT_NONSTDC_NO_DEPRECATE 1\r
+#define _CRT_SECURE_NO_DEPRECATE 1\r
+#define _CRT_RAND_S\r
+\r
+#include <shibsp/AbstractSPRequest.h>\r
+#include <shibsp/SPConfig.h>\r
+#include <shibsp/ServiceProvider.h>\r
+#include <xmltooling/unicode.h>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/NDC.h>\r
+#include <xmltooling/util/XMLConstants.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/Base64.hpp>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+#include <set>\r
+#include <sstream>\r
+#include <fstream>\r
+#include <stdexcept>\r
+#include <process.h>\r
+\r
+#include <windows.h>\r
+#include <httpfilt.h>\r
+#include <httpext.h>\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace xercesc;\r
+using namespace std;\r
+\r
+// globals\r
+namespace {\r
+    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);\r
+    static const XMLCh validate[] =         UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
+    static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);\r
+    static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);\r
+    static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);\r
+    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);\r
+    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);\r
+    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);\r
+    static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);\r
+\r
+    struct site_t {\r
+        site_t(const DOMElement* e)\r
+        {\r
+            auto_ptr_char n(e->getAttributeNS(NULL,name));\r
+            auto_ptr_char s(e->getAttributeNS(NULL,scheme));\r
+            auto_ptr_char p(e->getAttributeNS(NULL,port));\r
+            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));\r
+            if (n.get()) m_name=n.get();\r
+            if (s.get()) m_scheme=s.get();\r
+            if (p.get()) m_port=p.get();\r
+            if (p2.get()) m_sslport=p2.get();\r
+            e = XMLHelper::getFirstChildElement(e, Alias);\r
+            while (e) {\r
+                if (e->hasChildNodes()) {\r
+                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());\r
+                    m_aliases.insert(alias.get());\r
+                }\r
+                e = XMLHelper::getNextSiblingElement(e, Alias);\r
+            }\r
+        }\r
+        string m_scheme,m_port,m_sslport,m_name;\r
+        set<string> m_aliases;\r
+    };\r
+\r
+    HINSTANCE g_hinstDLL;\r
+    SPConfig* g_Config = NULL;\r
+    map<string,site_t> g_Sites;\r
+    bool g_bNormalizeRequest = true;\r
+    string g_unsetHeaderValue,g_spoofKey;\r
+    bool g_checkSpoofing = true;\r
+    bool g_catchAll = false;\r
+    bool g_bSafeHeaderNames = false;\r
+    vector<string> g_NoCerts;\r
+}\r
+\r
+BOOL LogEvent(\r
+    LPCSTR  lpUNCServerName,\r
+    WORD  wType,\r
+    DWORD  dwEventID,\r
+    PSID  lpUserSid,\r
+    LPCSTR  message)\r
+{\r
+    LPCSTR  messages[] = {message, NULL};\r
+\r
+    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");\r
+    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
+    return (DeregisterEventSource(hElog) && res);\r
+}\r
+\r
+extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)\r
+{\r
+    if (fdwReason==DLL_PROCESS_ATTACH)\r
+        g_hinstDLL=hinstDLL;\r
+    return TRUE;\r
+}\r
+\r
+extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)\r
+{\r
+    if (!pVer)\r
+        return FALSE;\r
+\r
+    if (!g_Config) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
+                "Extension mode startup not possible, is the DLL loaded as a filter?");\r
+        return FALSE;\r
+    }\r
+\r
+    pVer->dwExtensionVersion=HSE_VERSION;\r
+    strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);\r
+    return TRUE;\r
+}\r
+\r
+extern "C" BOOL WINAPI TerminateExtension(DWORD)\r
+{\r
+    return TRUE;    // cleanup should happen when filter unloads\r
+}\r
+\r
+extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)\r
+{\r
+    if (!pVer)\r
+        return FALSE;\r
+    else if (g_Config) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
+                "Reentrant filter initialization, ignoring...");\r
+        return TRUE;\r
+    }\r
+\r
+    g_Config=&SPConfig::getConfig();\r
+    g_Config->setFeatures(\r
+        SPConfig::Listener |\r
+        SPConfig::Caching |\r
+        SPConfig::RequestMapping |\r
+        SPConfig::InProcess |\r
+        SPConfig::Logging |\r
+        SPConfig::Handlers\r
+        );\r
+    if (!g_Config->init()) {\r
+        g_Config=NULL;\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
+                "Filter startup failed during library initialization, check native log for help.");\r
+        return FALSE;\r
+    }\r
+\r
+    try {\r
+        if (!g_Config->instantiate(NULL, true))\r
+            throw runtime_error("unknown error");\r
+    }\r
+    catch (exception& ex) {\r
+        g_Config->term();\r
+        g_Config=NULL;\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
+                "Filter startup failed to load configuration, check native log for details.");\r
+        return FALSE;\r
+    }\r
+\r
+    // Access implementation-specifics and site mappings.\r
+    ServiceProvider* sp=g_Config->getServiceProvider();\r
+    Locker locker(sp);\r
+    const PropertySet* props=sp->getPropertySet("InProcess");\r
+    if (props) {\r
+        pair<bool,bool> flag=props->getBool("checkSpoofing");\r
+        g_checkSpoofing = !flag.first || flag.second;\r
+        flag=props->getBool("catchAll");\r
+        g_catchAll = flag.first && flag.second;\r
+\r
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");\r
+        if (unsetValue.first)\r
+            g_unsetHeaderValue = unsetValue.second;\r
+        if (g_checkSpoofing) {\r
+            unsetValue = props->getString("spoofKey");\r
+            if (unsetValue.first)\r
+                g_spoofKey = unsetValue.second;\r
+            else {\r
+                unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;\r
+                if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {\r
+                    ostringstream keystr;\r
+                    keystr << randkey << randkey2 << randkey3 << randkey4;\r
+                    g_spoofKey = keystr.str();\r
+                }\r
+                else {\r
+                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
+                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");\r
+                    g_Config->term();\r
+                    g_Config=NULL;\r
+                    return FALSE;\r
+                }\r
+            }\r
+        }\r
+\r
+        props = props->getPropertySet("ISAPI");\r
+        if (props) {\r
+            flag = props->getBool("normalizeRequest");\r
+            g_bNormalizeRequest = !flag.first || flag.second;\r
+            flag = props->getBool("safeHeaderNames");\r
+            g_bSafeHeaderNames = flag.first && flag.second;\r
+            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);\r
+            while (child) {\r
+                auto_ptr_char id(child->getAttributeNS(NULL,id));\r
+                if (id.get())\r
+                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));\r
+                child=XMLHelper::getNextSiblingElement(child,Site);\r
+            }\r
+        }\r
+    }\r
+\r
+    pVer->dwFilterVersion=HTTP_FILTER_REVISION;\r
+    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);\r
+    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |\r
+                   SF_NOTIFY_SECURE_PORT |\r
+                   SF_NOTIFY_NONSECURE_PORT |\r
+                   SF_NOTIFY_PREPROC_HEADERS |\r
+                   SF_NOTIFY_LOG);\r
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");\r
+    return TRUE;\r
+}\r
+\r
+extern "C" BOOL WINAPI TerminateFilter(DWORD)\r
+{\r
+    if (g_Config)\r
+        g_Config->term();\r
+    g_Config = NULL;\r
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");\r
+    return TRUE;\r
+}\r
+\r
+/* Next up, some suck-free versions of various APIs.\r
+\r
+   You DON'T require people to guess the buffer size and THEN tell them the right size.\r
+   Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that\r
+   constant strings aren't typed as such, making it just that much harder. These versions\r
+   are now updated to use a special growable buffer object, modeled after the standard\r
+   string class. The standard string won't work because they left out the option to\r
+   pre-allocate a non-constant buffer.\r
+*/\r
+\r
+class dynabuf\r
+{\r
+public:\r
+    dynabuf() { bufptr=NULL; buflen=0; }\r
+    dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }\r
+    ~dynabuf() { delete[] bufptr; }\r
+    size_t length() const { return bufptr ? strlen(bufptr) : 0; }\r
+    size_t size() const { return buflen; }\r
+    bool empty() const { return length()==0; }\r
+    void reserve(size_t s, bool keep=false);\r
+    void erase() { if (bufptr) memset(bufptr,0,buflen); }\r
+    operator char*() { return bufptr; }\r
+    bool operator ==(const char* s) const;\r
+    bool operator !=(const char* s) const { return !(*this==s); }\r
+private:\r
+    char* bufptr;\r
+    size_t buflen;\r
+};\r
+\r
+void dynabuf::reserve(size_t s, bool keep)\r
+{\r
+    if (s<=buflen)\r
+        return;\r
+    char* p=new char[s];\r
+    if (keep)\r
+        while (buflen--)\r
+            p[buflen]=bufptr[buflen];\r
+    buflen=s;\r
+    delete[] bufptr;\r
+    bufptr=p;\r
+}\r
+\r
+bool dynabuf::operator==(const char* s) const\r
+{\r
+    if (buflen==NULL || s==NULL)\r
+        return (buflen==NULL && s==NULL);\r
+    else\r
+        return strcmp(bufptr,s)==0;\r
+}\r
+\r
+void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
+{\r
+    s.reserve(size);\r
+    s.erase();\r
+    size=s.size();\r
+\r
+    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {\r
+        // Grumble. Check the error.\r
+        DWORD e=GetLastError();\r
+        if (e==ERROR_INSUFFICIENT_BUFFER)\r
+            s.reserve(size);\r
+        else\r
+            break;\r
+    }\r
+    if (bRequired && s.empty())\r
+        throw ERROR_NO_DATA;\r
+}\r
+\r
+void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
+{\r
+    s.reserve(size);\r
+    s.erase();\r
+    size=s.size();\r
+\r
+    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {\r
+        // Grumble. Check the error.\r
+        DWORD e=GetLastError();\r
+        if (e==ERROR_INSUFFICIENT_BUFFER)\r
+            s.reserve(size);\r
+        else\r
+            break;\r
+    }\r
+    if (bRequired && s.empty())\r
+        throw ERROR_NO_DATA;\r
+}\r
+\r
+void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,\r
+               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)\r
+{\r
+    s.reserve(size);\r
+    s.erase();\r
+    size=s.size();\r
+\r
+    while (!pn->GetHeader(pfc,lpszName,s,&size)) {\r
+        // Grumble. Check the error.\r
+        DWORD e=GetLastError();\r
+        if (e==ERROR_INSUFFICIENT_BUFFER)\r
+            s.reserve(size);\r
+        else\r
+            break;\r
+    }\r
+    if (bRequired && s.empty())\r
+        throw ERROR_NO_DATA;\r
+}\r
+\r
+/****************************************************************************/\r
+// ISAPI Filter\r
+\r
+class ShibTargetIsapiF : public AbstractSPRequest\r
+{\r
+  PHTTP_FILTER_CONTEXT m_pfc;\r
+  PHTTP_FILTER_PREPROC_HEADERS m_pn;\r
+  multimap<string,string> m_headers;\r
+  int m_port;\r
+  string m_scheme,m_hostname;\r
+  mutable string m_remote_addr,m_content_type,m_method;\r
+  dynabuf m_allhttp;\r
+  bool m_firsttime;\r
+\r
+public:\r
+  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)\r
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {\r
+\r
+    // URL path always come from IIS.\r
+    dynabuf var(256);\r
+    GetHeader(pn,pfc,"url",var,256,false);\r
+    setRequestURI(var);\r
+\r
+    // Port may come from IIS or from site def.\r
+    if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {\r
+        GetServerVariable(pfc,"SERVER_PORT",var,10);\r
+        m_port = atoi(var);\r
+    }\r
+    else if (pfc->fIsSecurePort) {\r
+        m_port = atoi(site.m_sslport.c_str());\r
+    }\r
+    else {\r
+        m_port = atoi(site.m_port.c_str());\r
+    }\r
+\r
+    // Scheme may come from site def or be derived from IIS.\r
+    m_scheme=site.m_scheme;\r
+    if (m_scheme.empty() || !g_bNormalizeRequest)\r
+        m_scheme=pfc->fIsSecurePort ? "https" : "http";\r
+\r
+    GetServerVariable(pfc,"SERVER_NAME",var,32);\r
+\r
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
+    m_hostname = var;\r
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
+        m_hostname=site.m_name;\r
+\r
+    if (!g_spoofKey.empty()) {\r
+        GetHeader(pn, pfc, "ShibSpoofCheck:", var, 32, false);\r
+        if (!var.empty() && g_spoofKey == (char*)var)\r
+            m_firsttime = false;\r
+    }\r
+\r
+    if (!m_firsttime)\r
+        log(SPDebug, "ISAPI filter running more than once");\r
+  }\r
+  ~ShibTargetIsapiF() { }\r
+\r
+  const char* getScheme() const {\r
+    return m_scheme.c_str();\r
+  }\r
+  const char* getHostname() const {\r
+    return m_hostname.c_str();\r
+  }\r
+  int getPort() const {\r
+    return m_port;\r
+  }\r
+  const char* getQueryString() const {\r
+      const char* uri = getRequestURI();\r
+      uri = (uri ? strchr(uri, '?') : NULL);\r
+      return uri ? (uri + 1) : NULL;\r
+  }\r
+  const char* getMethod() const {\r
+    if (m_method.empty()) {\r
+        dynabuf var(5);\r
+        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);\r
+        if (!var.empty())\r
+            m_method = var;\r
+    }\r
+    return m_method.c_str();\r
+  }\r
+  string getContentType() const {\r
+    if (m_content_type.empty()) {\r
+        dynabuf var(32);\r
+        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);\r
+        if (!var.empty())\r
+            m_content_type = var;\r
+    }\r
+    return m_content_type;\r
+  }\r
+  string getRemoteAddr() const {\r
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
+    if (m_remote_addr.empty()) {\r
+        dynabuf var(16);\r
+        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);\r
+        if (!var.empty())\r
+            m_remote_addr = var;\r
+    }\r
+    return m_remote_addr;\r
+  }\r
+  void log(SPLogLevel level, const string& msg) {\r
+    AbstractSPRequest::log(level,msg);\r
+    if (level >= SPCrit)\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
+  }\r
+  string makeSafeHeader(const char* rawname) const {\r
+      string hdr;\r
+      for (; *rawname; ++rawname) {\r
+          if (isalnum(*rawname))\r
+              hdr += *rawname;\r
+      }\r
+      return (hdr + ':');\r
+  }\r
+  void clearHeader(const char* rawname, const char* cginame) {\r
+    if (g_checkSpoofing && m_firsttime) {\r
+        if (m_allhttp.empty())\r
+               GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);\r
+        string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');\r
+        if (strstr(m_allhttp, hdr.c_str()))\r
+            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));\r
+    }\r
+    if (g_bSafeHeaderNames) {\r
+        string hdr = makeSafeHeader(rawname);\r
+        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
+    }\r
+    else if (!strcmp(rawname,"REMOTE_USER")) {\r
+           m_pn->SetHeader(m_pfc, "remote-user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
+        m_pn->SetHeader(m_pfc, "remote_user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
+       }\r
+       else {\r
+           string hdr = string(rawname) + ':';\r
+           m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
+       }\r
+  }\r
+  void setHeader(const char* name, const char* value) {\r
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
+    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));\r
+  }\r
+  string getSecureHeader(const char* name) const {\r
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
+    dynabuf buf(256);\r
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
+    return string(buf.empty() ? "" : buf);\r
+  }\r
+  string getHeader(const char* name) const {\r
+    string hdr(name);\r
+    hdr += ':';\r
+    dynabuf buf(256);\r
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
+    return string(buf.empty() ? "" : buf);\r
+  }\r
+  void setRemoteUser(const char* user) {\r
+    setHeader("remote-user", user);\r
+    if (!user || !*user)\r
+        m_pfc->pFilterContext = NULL;\r
+    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))\r
+        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);\r
+  }\r
+  string getRemoteUser() const {\r
+    return getSecureHeader("remote-user");\r
+  }\r
+  void setResponseHeader(const char* name, const char* value) {\r
+    // Set for later.\r
+    if (value)\r
+        m_headers.insert(make_pair(name,value));\r
+    else\r
+        m_headers.erase(name);\r
+  }\r
+  long sendResponse(istream& in, long status) {\r
+    string hdr = string("Connection: close\r\n");\r
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
+        hdr += i->first + ": " + i->second + "\r\n";\r
+    hdr += "\r\n";\r
+    const char* codestr="200 OK";\r
+    switch (status) {\r
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;\r
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;\r
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;\r
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;\r
+    }\r
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);\r
+    char buf[1024];\r
+    while (in) {\r
+        in.read(buf,1024);\r
+        DWORD resplen = in.gcount();\r
+        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);\r
+    }\r
+    return SF_STATUS_REQ_FINISHED;\r
+  }\r
+  long sendRedirect(const char* url) {\r
+    // XXX: Don't support the httpRedirect option, yet.\r
+    string hdr=string("Location: ") + url + "\r\n"\r
+      "Content-Type: text/html\r\n"\r
+      "Content-Length: 40\r\n"\r
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
+      "Cache-Control: private,no-store,no-cache\r\n";\r
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
+        hdr += i->first + ": " + i->second + "\r\n";\r
+    hdr += "\r\n";\r
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);\r
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
+    DWORD resplen=40;\r
+    m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);\r
+    return SF_STATUS_REQ_FINISHED;\r
+  }\r
+  long returnDecline() {\r
+      return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
+  }\r
+  long returnOK() {\r
+    return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
+  }\r
+\r
+  const vector<string>& getClientCertificates() const {\r
+      return g_NoCerts;\r
+  }\r
+\r
+  // The filter never processes the POST, so stub these methods.\r
+  long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }\r
+  const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }\r
+};\r
+\r
+DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)\r
+{\r
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
+    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);\r
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"\r
+                            "<H1>Shibboleth Filter Error</H1>";\r
+    DWORD resplen=strlen(xmsg);\r
+    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);\r
+    resplen=strlen(msg);\r
+    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);\r
+    static const char* xmsg2="</BODY></HTML>";\r
+    resplen=strlen(xmsg2);\r
+    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);\r
+    return SF_STATUS_REQ_FINISHED;\r
+}\r
+\r
+extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)\r
+{\r
+    // Is this a log notification?\r
+    if (notificationType==SF_NOTIFY_LOG) {\r
+        if (pfc->pFilterContext)\r
+               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);\r
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
+    }\r
+\r
+    PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;\r
+    try\r
+    {\r
+        // Determine web site number. This can't really fail, I don't think.\r
+        dynabuf buf(128);\r
+        GetServerVariable(pfc,"INSTANCE_ID",buf,10);\r
+\r
+        // Match site instance to host name, skip if no match.\r
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
+        if (map_i==g_Sites.end())\r
+            return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
+\r
+        ostringstream threadid;\r
+        threadid << "[" << getpid() << "] isapi_shib" << '\0';\r
+        xmltooling::NDC ndc(threadid.str().c_str());\r
+\r
+        ShibTargetIsapiF stf(pfc, pn, map_i->second);\r
+\r
+        // "false" because we don't override the Shib settings\r
+        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);\r
+        if (!g_spoofKey.empty())\r
+            pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast<char*>(g_spoofKey.c_str()));\r
+        if (res.first) return res.second;\r
+\r
+        // "false" because we don't override the Shib settings\r
+        res = stf.getServiceProvider().doExport(stf);\r
+        if (res.first) return res.second;\r
+\r
+        res = stf.getServiceProvider().doAuthorization(stf);\r
+        if (res.first) return res.second;\r
+\r
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
+    }\r
+    catch(bad_alloc) {\r
+        return WriteClientError(pfc,"Out of Memory");\r
+    }\r
+    catch(long e) {\r
+        if (e==ERROR_NO_DATA)\r
+            return WriteClientError(pfc,"A required variable or header was empty.");\r
+        else\r
+            return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");\r
+    }\r
+    catch (exception& e) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
+        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");\r
+    }\r
+    catch(...) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw an unknown exception.");\r
+        if (g_catchAll)\r
+            return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");\r
+        throw;\r
+    }\r
+\r
+    return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");\r
+}\r
+\r
+\r
+/****************************************************************************/\r
+// ISAPI Extension\r
+\r
+DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)\r
+{\r
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
+    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);\r
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";\r
+    DWORD resplen=strlen(xmsg);\r
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);\r
+    resplen=strlen(msg);\r
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);\r
+    static const char* xmsg2="</BODY></HTML>";\r
+    resplen=strlen(xmsg2);\r
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);\r
+    return HSE_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+class ShibTargetIsapiE : public AbstractSPRequest\r
+{\r
+  LPEXTENSION_CONTROL_BLOCK m_lpECB;\r
+  multimap<string,string> m_headers;\r
+  mutable vector<string> m_certs;\r
+  mutable string m_body;\r
+  mutable bool m_gotBody;\r
+  int m_port;\r
+  string m_scheme,m_hostname,m_uri;\r
+  mutable string m_remote_addr,m_remote_user;\r
+\r
+public:\r
+  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)\r
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {\r
+    dynabuf ssl(5);\r
+    GetServerVariable(lpECB,"HTTPS",ssl,5);\r
+    bool SSL=(ssl=="on" || ssl=="ON");\r
+\r
+    // Scheme may come from site def or be derived from IIS.\r
+    m_scheme=site.m_scheme;\r
+    if (m_scheme.empty() || !g_bNormalizeRequest)\r
+        m_scheme = SSL ? "https" : "http";\r
+\r
+    // URL path always come from IIS.\r
+    dynabuf url(256);\r
+    GetServerVariable(lpECB,"URL",url,255);\r
+\r
+    // Port may come from IIS or from site def.\r
+    dynabuf port(11);\r
+    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))\r
+        GetServerVariable(lpECB,"SERVER_PORT",port,10);\r
+    else if (SSL) {\r
+        strncpy(port,site.m_sslport.c_str(),10);\r
+        static_cast<char*>(port)[10]=0;\r
+    }\r
+    else {\r
+        strncpy(port,site.m_port.c_str(),10);\r
+        static_cast<char*>(port)[10]=0;\r
+    }\r
+    m_port = atoi(port);\r
+\r
+    dynabuf var(32);\r
+    GetServerVariable(lpECB, "SERVER_NAME", var, 32);\r
+\r
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
+    m_hostname=var;\r
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
+        m_hostname=site.m_name;\r
+\r
+    /*\r
+     * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if\r
+     * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",\r
+     * which is the default. No perfect way to tell, but we can take a good guess by checking\r
+     * whether the URL is a substring of the PATH_INFO:\r
+     *\r
+     * e.g. for /Shibboleth.sso/SAML/POST\r
+     *\r
+     *  Bad mode (default):\r
+     *      URL:        /Shibboleth.sso\r
+     *      PathInfo:   /Shibboleth.sso/SAML/POST\r
+     *\r
+     *  Good mode:\r
+     *      URL:        /Shibboleth.sso\r
+     *      PathInfo:   /SAML/POST\r
+     */\r
+\r
+    string uri;\r
+\r
+    // Clearly we're only in bad mode if path info exists at all.\r
+    if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {\r
+        if (strstr(lpECB->lpszPathInfo,url))\r
+            // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.\r
+            uri = lpECB->lpszPathInfo;\r
+        else {\r
+            uri = url;\r
+            uri += lpECB->lpszPathInfo;\r
+        }\r
+    }\r
+    else {\r
+        uri = url;\r
+    }\r
+\r
+    // For consistency with Apache, let's add the query string.\r
+    if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {\r
+        uri += '?';\r
+        uri += lpECB->lpszQueryString;\r
+    }\r
+\r
+    setRequestURI(uri.c_str());\r
+  }\r
+  ~ShibTargetIsapiE() { }\r
+\r
+  const char* getScheme() const {\r
+    return m_scheme.c_str();\r
+  }\r
+  const char* getHostname() const {\r
+    return m_hostname.c_str();\r
+  }\r
+  int getPort() const {\r
+    return m_port;\r
+  }\r
+  const char* getMethod() const {\r
+    return m_lpECB->lpszMethod;\r
+  }\r
+  string getContentType() const {\r
+    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";\r
+  }\r
+  long getContentLength() const {\r
+      return m_lpECB->cbTotalBytes;\r
+  }\r
+  string getRemoteUser() const {\r
+    if (m_remote_user.empty()) {\r
+        dynabuf var(16);\r
+        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);\r
+        if (!var.empty())\r
+            m_remote_user = var;\r
+    }\r
+    return m_remote_user;\r
+  }\r
+  string getRemoteAddr() const {\r
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
+    if (m_remote_addr.empty()) {\r
+        dynabuf var(16);\r
+        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);\r
+        if (!var.empty())\r
+            m_remote_addr = var;\r
+    }\r
+    return m_remote_addr;\r
+  }\r
+  void log(SPLogLevel level, const string& msg) const {\r
+      AbstractSPRequest::log(level,msg);\r
+      if (level >= SPCrit)\r
+          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
+  }\r
+  string getHeader(const char* name) const {\r
+    string hdr("HTTP_");\r
+    for (; *name; ++name) {\r
+        if (*name=='-')\r
+            hdr += '_';\r
+        else\r
+            hdr += toupper(*name);\r
+    }\r
+    dynabuf buf(128);\r
+    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);\r
+    return buf.empty() ? "" : buf;\r
+  }\r
+  void setResponseHeader(const char* name, const char* value) {\r
+    // Set for later.\r
+    if (value)\r
+        m_headers.insert(make_pair(name,value));\r
+    else\r
+        m_headers.erase(name);\r
+  }\r
+  const char* getQueryString() const {\r
+    return m_lpECB->lpszQueryString;\r
+  }\r
+  const char* getRequestBody() const {\r
+    if (m_gotBody)\r
+        return m_body.c_str();\r
+    if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?\r
+        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");\r
+    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {\r
+      m_gotBody=true;\r
+      DWORD datalen=m_lpECB->cbTotalBytes;\r
+      if (m_lpECB->cbAvailable > 0) {\r
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
+        datalen-=m_lpECB->cbAvailable;\r
+      }\r
+      char buf[8192];\r
+      while (datalen) {\r
+        DWORD buflen=8192;\r
+        BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);\r
+        if (!ret)\r
+            throw IOException("Error reading request body from browser.");\r
+        else if (!buflen)\r
+            throw IOException("Socket closed while reading request body from browser.");\r
+        m_body.append(buf, buflen);\r
+        datalen-=buflen;\r
+      }\r
+    }\r
+    else if (m_lpECB->cbAvailable) {\r
+        m_gotBody=true;\r
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
+    }\r
+    return m_body.c_str();\r
+  }\r
+  long sendResponse(istream& in, long status) {\r
+    string hdr = string("Connection: close\r\n");\r
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
+        hdr += i->first + ": " + i->second + "\r\n";\r
+    hdr += "\r\n";\r
+    const char* codestr="200 OK";\r
+    switch (status) {\r
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;\r
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;\r
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;\r
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;\r
+    }\r
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());\r
+    char buf[1024];\r
+    while (in) {\r
+        in.read(buf,1024);\r
+        DWORD resplen = in.gcount();\r
+        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);\r
+    }\r
+    return HSE_STATUS_SUCCESS;\r
+  }\r
+  long sendRedirect(const char* url) {\r
+    string hdr=string("Location: ") + url + "\r\n"\r
+      "Content-Type: text/html\r\n"\r
+      "Content-Length: 40\r\n"\r
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
+      "Cache-Control: private,no-store,no-cache\r\n";\r
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
+        hdr += i->first + ": " + i->second + "\r\n";\r
+    hdr += "\r\n";\r
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());\r
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
+    DWORD resplen=40;\r
+    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);\r
+    return HSE_STATUS_SUCCESS;\r
+  }\r
+  // Decline happens in the POST processor if this isn't the shire url\r
+  // Note that it can also happen with HTAccess, but we don't support that, yet.\r
+  long returnDecline() {\r
+    return WriteClientError(\r
+        m_lpECB,\r
+        "ISAPI extension can only be invoked to process Shibboleth protocol requests."\r
+               "Make sure the mapped file extension doesn't match actual content."\r
+        );\r
+  }\r
+  long returnOK() {\r
+      return HSE_STATUS_SUCCESS;\r
+  }\r
+\r
+  const vector<string>& getClientCertificates() const {\r
+      if (m_certs.empty()) {\r
+        char CertificateBuf[8192];\r
+        CERT_CONTEXT_EX ccex;\r
+        ccex.cbAllocated = sizeof(CertificateBuf);\r
+        ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;\r
+        DWORD dwSize = sizeof(ccex);\r
+\r
+        if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {\r
+            if (ccex.CertContext.cbCertEncoded) {\r
+                xsecsize_t outlen;\r
+                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);\r
+                m_certs.push_back(reinterpret_cast<char*>(serialized));\r
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE\r
+                XMLString::release(&serialized);\r
+#else\r
+                XMLString::release((char**)&serialized);\r
+#endif\r
+            }\r
+        }\r
+      }\r
+      return m_certs;\r
+  }\r
+\r
+  // Not used in the extension.\r
+  void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }\r
+  void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }\r
+  void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }\r
+};\r
+\r
+extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)\r
+{\r
+    try {\r
+        ostringstream threadid;\r
+        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';\r
+        xmltooling::NDC ndc(threadid.str().c_str());\r
+\r
+        // Determine web site number. This can't really fail, I don't think.\r
+        dynabuf buf(128);\r
+        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);\r
+\r
+        // Match site instance to host name, skip if no match.\r
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
+        if (map_i==g_Sites.end())\r
+            return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check <ISAPI> mappings in configuration).");\r
+\r
+        ShibTargetIsapiE ste(lpECB, map_i->second);\r
+        pair<bool,long> res = ste.getServiceProvider().doHandler(ste);\r
+        if (res.first) return res.second;\r
+\r
+        return WriteClientError(lpECB, "Shibboleth Extension failed to process request");\r
+\r
+    }\r
+    catch(bad_alloc) {\r
+        return WriteClientError(lpECB,"Out of Memory");\r
+    }\r
+    catch(long e) {\r
+        if (e==ERROR_NO_DATA)\r
+            return WriteClientError(lpECB,"A required variable or header was empty.");\r
+        else\r
+            return WriteClientError(lpECB,"Server detected unexpected IIS error.");\r
+    }\r
+    catch (exception& e) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
+        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");\r
+    }\r
+    catch(...) {\r
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw an unknown exception.");\r
+        if (g_catchAll)\r
+            return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");\r
+        throw;\r
+    }\r
+\r
+    // If we get here we've got an error.\r
+    return HSE_STATUS_ERROR;\r
+}\r
diff --git a/isapi_shib/isapi_shib.cpp.r3059 b/isapi_shib/isapi_shib.cpp.r3059
new file mode 100644 (file)
index 0000000..73fb7a0
--- /dev/null
@@ -0,0 +1,950 @@
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * isapi_shib.cpp
+ *
+ * Shibboleth ISAPI filter
+ */
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/Base64.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <set>
+#include <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <process.h>
+
+#include <windows.h>
+#include <httpfilt.h>
+#include <httpext.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+// globals
+namespace {
+    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);
+    static const XMLCh validate[] =         UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+    static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);
+    static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);
+    static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);
+    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);
+    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);
+    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);
+    static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);
+
+    struct site_t {
+        site_t(const DOMElement* e)
+        {
+            auto_ptr_char n(e->getAttributeNS(NULL,name));
+            auto_ptr_char s(e->getAttributeNS(NULL,scheme));
+            auto_ptr_char p(e->getAttributeNS(NULL,port));
+            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
+            if (n.get()) m_name=n.get();
+            if (s.get()) m_scheme=s.get();
+            if (p.get()) m_port=p.get();
+            if (p2.get()) m_sslport=p2.get();
+            e = XMLHelper::getFirstChildElement(e, Alias);
+            while (e) {
+                if (e->hasChildNodes()) {
+                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());
+                    m_aliases.insert(alias.get());
+                }
+                e = XMLHelper::getNextSiblingElement(e, Alias);
+            }
+        }
+        string m_scheme,m_port,m_sslport,m_name;
+        set<string> m_aliases;
+    };
+
+    struct context_t {
+       char* m_user;
+       bool m_checked;
+    };
+
+    HINSTANCE g_hinstDLL;
+    SPConfig* g_Config = NULL;
+    map<string,site_t> g_Sites;
+    bool g_bNormalizeRequest = true;
+    string g_unsetHeaderValue;
+    bool g_checkSpoofing = true;
+    bool g_catchAll = false;
+    vector<string> g_NoCerts;
+}
+
+BOOL LogEvent(
+    LPCSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCSTR  message)
+{
+    LPCSTR  messages[] = {message, NULL};
+
+    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
+    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
+    return (DeregisterEventSource(hElog) && res);
+}
+
+extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
+{
+    if (fdwReason==DLL_PROCESS_ATTACH)
+        g_hinstDLL=hinstDLL;
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
+{
+    if (!pVer)
+        return FALSE;
+
+    if (!g_Config) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Extension mode startup not possible, is the DLL loaded as a filter?");
+        return FALSE;
+    }
+
+    pVer->dwExtensionVersion=HSE_VERSION;
+    strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI TerminateExtension(DWORD)
+{
+    return TRUE;    // cleanup should happen when filter unloads
+}
+
+extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
+{
+    if (!pVer)
+        return FALSE;
+    else if (g_Config) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Reentrant filter initialization, ignoring...");
+        return TRUE;
+    }
+
+    g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed during library initialization, check native log for help.");
+        return FALSE;
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed to load configuration, check native log for details.");
+        return FALSE;
+    }
+
+    // Access implementation-specifics and site mappings.
+    ServiceProvider* sp=g_Config->getServiceProvider();
+    Locker locker(sp);
+    const PropertySet* props=sp->getPropertySet("InProcess");
+    if (props) {
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        if (unsetValue.first)
+            g_unsetHeaderValue = unsetValue.second;
+        pair<bool,bool> flag=props->getBool("checkSpoofing");
+        g_checkSpoofing = !flag.first || flag.second;
+        flag=props->getBool("catchAll");
+        g_catchAll = flag.first && flag.second;
+
+        props = props->getPropertySet("ISAPI");
+        if (props) {
+            flag = props->getBool("normalizeRequest");
+            g_bNormalizeRequest = !flag.first || flag.second;
+            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
+            while (child) {
+                auto_ptr_char id(child->getAttributeNS(NULL,id));
+                if (id.get())
+                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
+                child=XMLHelper::getNextSiblingElement(child,Site);
+            }
+        }
+    }
+
+    pVer->dwFilterVersion=HTTP_FILTER_REVISION;
+    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
+    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
+                   SF_NOTIFY_SECURE_PORT |
+                   SF_NOTIFY_NONSECURE_PORT |
+                   SF_NOTIFY_PREPROC_HEADERS |
+                   SF_NOTIFY_LOG);
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI TerminateFilter(DWORD)
+{
+    if (g_Config)
+        g_Config->term();
+    g_Config = NULL;
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");
+    return TRUE;
+}
+
+/* Next up, some suck-free versions of various APIs.
+
+   You DON'T require people to guess the buffer size and THEN tell them the right size.
+   Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that
+   constant strings aren't typed as such, making it just that much harder. These versions
+   are now updated to use a special growable buffer object, modeled after the standard
+   string class. The standard string won't work because they left out the option to
+   pre-allocate a non-constant buffer.
+*/
+
+class dynabuf
+{
+public:
+    dynabuf() { bufptr=NULL; buflen=0; }
+    dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }
+    ~dynabuf() { delete[] bufptr; }
+    size_t length() const { return bufptr ? strlen(bufptr) : 0; }
+    size_t size() const { return buflen; }
+    bool empty() const { return length()==0; }
+    void reserve(size_t s, bool keep=false);
+    void erase() { if (bufptr) memset(bufptr,0,buflen); }
+    operator char*() { return bufptr; }
+    bool operator ==(const char* s) const;
+    bool operator !=(const char* s) const { return !(*this==s); }
+private:
+    char* bufptr;
+    size_t buflen;
+};
+
+void dynabuf::reserve(size_t s, bool keep)
+{
+    if (s<=buflen)
+        return;
+    char* p=new char[s];
+    if (keep)
+        while (buflen--)
+            p[buflen]=bufptr[buflen];
+    buflen=s;
+    delete[] bufptr;
+    bufptr=p;
+}
+
+bool dynabuf::operator==(const char* s) const
+{
+    if (buflen==NULL || s==NULL)
+        return (buflen==NULL && s==NULL);
+    else
+        return strcmp(bufptr,s)==0;
+}
+
+void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
+               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!pn->GetHeader(pfc,lpszName,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+/****************************************************************************/
+// ISAPI Filter
+
+class ShibTargetIsapiF : public AbstractSPRequest
+{
+  PHTTP_FILTER_CONTEXT m_pfc;
+  PHTTP_FILTER_PREPROC_HEADERS m_pn;
+  multimap<string,string> m_headers;
+  int m_port;
+  string m_scheme,m_hostname;
+  mutable string m_remote_addr,m_content_type,m_method;
+  dynabuf m_allhttp;
+
+public:
+  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096) {
+
+    // URL path always come from IIS.
+    dynabuf var(256);
+    GetHeader(pn,pfc,"url",var,256,false);
+    setRequestURI(var);
+
+    // Port may come from IIS or from site def.
+    if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {
+        GetServerVariable(pfc,"SERVER_PORT",var,10);
+        m_port = atoi(var);
+    }
+    else if (pfc->fIsSecurePort) {
+        m_port = atoi(site.m_sslport.c_str());
+    }
+    else {
+        m_port = atoi(site.m_port.c_str());
+    }
+
+    // Scheme may come from site def or be derived from IIS.
+    m_scheme=site.m_scheme;
+    if (m_scheme.empty() || !g_bNormalizeRequest)
+        m_scheme=pfc->fIsSecurePort ? "https" : "http";
+
+    GetServerVariable(pfc,"SERVER_NAME",var,32);
+
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
+    m_hostname = var;
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
+        m_hostname=site.m_name;
+
+    if (!pfc->pFilterContext) {
+        pfc->pFilterContext = pfc->AllocMem(pfc, sizeof(context_t), NULL);
+        if (static_cast<context_t*>(pfc->pFilterContext)) {
+            static_cast<context_t*>(pfc->pFilterContext)->m_user = NULL;
+            static_cast<context_t*>(pfc->pFilterContext)->m_checked = false;
+        }
+    }
+  }
+  ~ShibTargetIsapiF() { }
+
+  const char* getScheme() const {
+    return m_scheme.c_str();
+  }
+  const char* getHostname() const {
+    return m_hostname.c_str();
+  }
+  int getPort() const {
+    return m_port;
+  }
+  const char* getQueryString() const {
+      const char* uri = getRequestURI();
+      uri = (uri ? strchr(uri, '?') : NULL);
+      return uri ? (uri + 1) : NULL;
+  }
+  const char* getMethod() const {
+    if (m_method.empty()) {
+        dynabuf var(5);
+        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
+        if (!var.empty())
+            m_method = var;
+    }
+    return m_method.c_str();
+  }
+  string getContentType() const {
+    if (m_content_type.empty()) {
+        dynabuf var(32);
+        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
+        if (!var.empty())
+            m_content_type = var;
+    }
+    return m_content_type;
+  }
+  string getRemoteAddr() const {
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();
+    if (m_remote_addr.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
+        if (!var.empty())
+            m_remote_addr = var;
+    }
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) {
+    AbstractSPRequest::log(level,msg);
+    if (level >= SPError)
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  }
+  void clearHeader(const char* rawname, const char* cginame) {
+       if (g_checkSpoofing && m_pfc->pFilterContext && !static_cast<context_t*>(m_pfc->pFilterContext)->m_checked) {
+        if (m_allhttp.empty())
+               GetServerVariable(m_pfc,"ALL_HTTP",m_allhttp,4096);
+        if (strstr(m_allhttp, cginame))
+            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
+    }
+    string hdr(!strcmp(rawname,"REMOTE_USER") ? "remote-user" : rawname);
+    hdr += ':';
+    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+  }
+  void setHeader(const char* name, const char* value) {
+    string hdr(name);
+    hdr += ':';
+    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
+  }
+  string getHeader(const char* name) const {
+    string hdr(name);
+    hdr += ':';
+    dynabuf buf(256);
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
+    return string(buf);
+  }
+  void setRemoteUser(const char* user) {
+    setHeader("remote-user", user);
+    if (m_pfc->pFilterContext) {
+        if (!user || !*user)
+            static_cast<context_t*>(m_pfc->pFilterContext)->m_user = NULL;
+        else if (static_cast<context_t*>(m_pfc->pFilterContext)->m_user = (char*)m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
+            strcpy(static_cast<context_t*>(m_pfc->pFilterContext)->m_user, user);
+    }
+  }
+  string getRemoteUser() const {
+    return getHeader("remote-user");
+  }
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers.insert(make_pair(name,value));
+    else
+        m_headers.erase(name);
+  }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    const char* codestr="200 OK";
+    switch (status) {
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;
+    }
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);
+    }
+    return SF_STATUS_REQ_FINISHED;
+  }
+  long sendRedirect(const char* url) {
+    // XXX: Don't support the httpRedirect option, yet.
+    string hdr=string("Location: ") + url + "\r\n"
+      "Content-Type: text/html\r\n"
+      "Content-Length: 40\r\n"
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+    DWORD resplen=40;
+    m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
+    return SF_STATUS_REQ_FINISHED;
+  }
+  long returnDecline() {
+      return SF_STATUS_REQ_NEXT_NOTIFICATION;
+  }
+  long returnOK() {
+    return SF_STATUS_REQ_NEXT_NOTIFICATION;
+  }
+
+  const vector<string>& getClientCertificates() const {
+      return g_NoCerts;
+  }
+
+  // The filter never processes the POST, so stub these methods.
+  long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }
+  const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }
+};
+
+DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
+{
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
+                            "<H1>Shibboleth Filter Error</H1>";
+    DWORD resplen=strlen(xmsg);
+    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
+    resplen=strlen(msg);
+    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
+    static const char* xmsg2="</BODY></HTML>";
+    resplen=strlen(xmsg2);
+    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
+    return SF_STATUS_REQ_FINISHED;
+}
+
+extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
+{
+    // Is this a log notification?
+    if (notificationType==SF_NOTIFY_LOG) {
+        if (pfc->pFilterContext && static_cast<context_t*>(pfc->pFilterContext)->m_user)
+               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=static_cast<context_t*>(pfc->pFilterContext)->m_user;
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;
+    }
+
+    PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;
+    try
+    {
+        // Determine web site number. This can't really fail, I don't think.
+        dynabuf buf(128);
+        GetServerVariable(pfc,"INSTANCE_ID",buf,10);
+
+        // Match site instance to host name, skip if no match.
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+        if (map_i==g_Sites.end())
+            return SF_STATUS_REQ_NEXT_NOTIFICATION;
+
+        ostringstream threadid;
+        threadid << "[" << getpid() << "] isapi_shib" << '\0';
+        xmltooling::NDC ndc(threadid.str().c_str());
+
+        ShibTargetIsapiF stf(pfc, pn, map_i->second);
+
+        // "false" because we don't override the Shib settings
+        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
+        if (pfc->pFilterContext)
+            static_cast<context_t*>(pfc->pFilterContext)->m_checked = true;
+        if (res.first) return res.second;
+
+        // "false" because we don't override the Shib settings
+        res = stf.getServiceProvider().doExport(stf);
+        if (res.first) return res.second;
+
+        res = stf.getServiceProvider().doAuthorization(stf);
+        if (res.first) return res.second;
+
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;
+    }
+    catch(bad_alloc) {
+        return WriteClientError(pfc,"Out of Memory");
+    }
+    catch(long e) {
+        if (e==ERROR_NO_DATA)
+            return WriteClientError(pfc,"A required variable or header was empty.");
+        else
+            return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");
+    }
+    catch (exception& e) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
+        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
+    }
+    catch(...) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw an unknown exception.");
+        if (g_catchAll)
+            return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");
+        throw;
+    }
+
+    return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");
+}
+
+
+/****************************************************************************/
+// ISAPI Extension
+
+DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
+{
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
+    DWORD resplen=strlen(xmsg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
+    resplen=strlen(msg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
+    static const char* xmsg2="</BODY></HTML>";
+    resplen=strlen(xmsg2);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
+    return HSE_STATUS_SUCCESS;
+}
+
+
+class ShibTargetIsapiE : public AbstractSPRequest
+{
+  LPEXTENSION_CONTROL_BLOCK m_lpECB;
+  multimap<string,string> m_headers;
+  mutable vector<string> m_certs;
+  mutable string m_body;
+  mutable bool m_gotBody;
+  int m_port;
+  string m_scheme,m_hostname,m_uri;
+  mutable string m_remote_addr,m_remote_user;
+
+public:
+  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {
+    dynabuf ssl(5);
+    GetServerVariable(lpECB,"HTTPS",ssl,5);
+    bool SSL=(ssl=="on" || ssl=="ON");
+
+    // Scheme may come from site def or be derived from IIS.
+    m_scheme=site.m_scheme;
+    if (m_scheme.empty() || !g_bNormalizeRequest)
+        m_scheme = SSL ? "https" : "http";
+
+    // URL path always come from IIS.
+    dynabuf url(256);
+    GetServerVariable(lpECB,"URL",url,255);
+
+    // Port may come from IIS or from site def.
+    dynabuf port(11);
+    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
+        GetServerVariable(lpECB,"SERVER_PORT",port,10);
+    else if (SSL) {
+        strncpy(port,site.m_sslport.c_str(),10);
+        static_cast<char*>(port)[10]=0;
+    }
+    else {
+        strncpy(port,site.m_port.c_str(),10);
+        static_cast<char*>(port)[10]=0;
+    }
+    m_port = atoi(port);
+
+    dynabuf var(32);
+    GetServerVariable(lpECB, "SERVER_NAME", var, 32);
+
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
+    m_hostname=var;
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
+        m_hostname=site.m_name;
+
+    /*
+     * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if
+     * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",
+     * which is the default. No perfect way to tell, but we can take a good guess by checking
+     * whether the URL is a substring of the PATH_INFO:
+     *
+     * e.g. for /Shibboleth.sso/SAML/POST
+     *
+     *  Bad mode (default):
+     *      URL:        /Shibboleth.sso
+     *      PathInfo:   /Shibboleth.sso/SAML/POST
+     *
+     *  Good mode:
+     *      URL:        /Shibboleth.sso
+     *      PathInfo:   /SAML/POST
+     */
+
+    string uri;
+
+    // Clearly we're only in bad mode if path info exists at all.
+    if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {
+        if (strstr(lpECB->lpszPathInfo,url))
+            // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.
+            uri = lpECB->lpszPathInfo;
+        else {
+            uri = url;
+            uri += lpECB->lpszPathInfo;
+        }
+    }
+    else {
+        uri = url;
+    }
+
+    // For consistency with Apache, let's add the query string.
+    if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {
+        uri += '?';
+        uri += lpECB->lpszQueryString;
+    }
+
+    setRequestURI(uri.c_str());
+  }
+  ~ShibTargetIsapiE() { }
+
+  const char* getScheme() const {
+    return m_scheme.c_str();
+  }
+  const char* getHostname() const {
+    return m_hostname.c_str();
+  }
+  int getPort() const {
+    return m_port;
+  }
+  const char* getMethod() const {
+    return m_lpECB->lpszMethod;
+  }
+  string getContentType() const {
+    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";
+  }
+  long getContentLength() const {
+      return m_lpECB->cbTotalBytes;
+  }
+  string getRemoteUser() const {
+    if (m_remote_user.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
+        if (!var.empty())
+            m_remote_user = var;
+    }
+    return m_remote_user;
+  }
+  string getRemoteAddr() const {
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();
+    if (m_remote_addr.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
+        if (!var.empty())
+            m_remote_addr = var;
+    }
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) const {
+      AbstractSPRequest::log(level,msg);
+      if (level >= SPError)
+          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  }
+  string getHeader(const char* name) const {
+    string hdr("HTTP_");
+    for (; *name; ++name) {
+        if (*name=='-')
+            hdr += '_';
+        else
+            hdr += toupper(*name);
+    }
+    dynabuf buf(128);
+    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
+    return buf.empty() ? "" : buf;
+  }
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers.insert(make_pair(name,value));
+    else
+        m_headers.erase(name);
+  }
+  const char* getQueryString() const {
+    return m_lpECB->lpszQueryString;
+  }
+  const char* getRequestBody() const {
+    if (m_gotBody)
+        return m_body.c_str();
+    if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
+        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
+    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
+      m_gotBody=true;
+      DWORD datalen=m_lpECB->cbTotalBytes;
+      if (m_lpECB->cbAvailable > 0) {
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
+        datalen-=m_lpECB->cbAvailable;
+      }
+      char buf[8192];
+      while (datalen) {
+        DWORD buflen=8192;
+        BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
+        if (!ret)
+            throw IOException("Error reading request body from browser.");
+        else if (!buflen)
+            throw IOException("Socket closed while reading request body from browser.");
+        m_body.append(buf, buflen);
+        datalen-=buflen;
+      }
+    }
+    else if (m_lpECB->cbAvailable) {
+        m_gotBody=true;
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
+    }
+    return m_body.c_str();
+  }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    const char* codestr="200 OK";
+    switch (status) {
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;
+    }
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);
+    }
+    return HSE_STATUS_SUCCESS;
+  }
+  long sendRedirect(const char* url) {
+    string hdr=string("Location: ") + url + "\r\n"
+      "Content-Type: text/html\r\n"
+      "Content-Length: 40\r\n"
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+    DWORD resplen=40;
+    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
+    return HSE_STATUS_SUCCESS;
+  }
+  // Decline happens in the POST processor if this isn't the shire url
+  // Note that it can also happen with HTAccess, but we don't support that, yet.
+  long returnDecline() {
+    return WriteClientError(
+        m_lpECB,
+        "ISAPI extension can only be invoked to process Shibboleth protocol requests."
+               "Make sure the mapped file extension doesn't match actual content."
+        );
+  }
+  long returnOK() {
+      return HSE_STATUS_SUCCESS;
+  }
+
+  const vector<string>& getClientCertificates() const {
+      if (m_certs.empty()) {
+        char CertificateBuf[8192];
+        CERT_CONTEXT_EX ccex;
+        ccex.cbAllocated = sizeof(CertificateBuf);
+        ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;
+        DWORD dwSize = sizeof(ccex);
+
+        if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {
+            if (ccex.CertContext.cbCertEncoded) {
+                xsecsize_t outlen;
+                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
+                m_certs.push_back(reinterpret_cast<char*>(serialized));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&serialized);
+#else
+                XMLString::release((char**)&serialized);
+#endif
+            }
+        }
+      }
+      return m_certs;
+  }
+
+  // Not used in the extension.
+  void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }
+  void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
+  void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
+};
+
+extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
+{
+    try {
+        ostringstream threadid;
+        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
+        xmltooling::NDC ndc(threadid.str().c_str());
+
+        // Determine web site number. This can't really fail, I don't think.
+        dynabuf buf(128);
+        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
+
+        // Match site instance to host name, skip if no match.
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+        if (map_i==g_Sites.end())
+            return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check <ISAPI> mappings in configuration).");
+
+        ShibTargetIsapiE ste(lpECB, map_i->second);
+        pair<bool,long> res = ste.getServiceProvider().doHandler(ste);
+        if (res.first) return res.second;
+
+        return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
+
+    }
+    catch(bad_alloc) {
+        return WriteClientError(lpECB,"Out of Memory");
+    }
+    catch(long e) {
+        if (e==ERROR_NO_DATA)
+            return WriteClientError(lpECB,"A required variable or header was empty.");
+        else
+            return WriteClientError(lpECB,"Server detected unexpected IIS error.");
+    }
+    catch (exception& e) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
+        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
+    }
+    catch(...) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw an unknown exception.");
+        if (g_catchAll)
+            return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");
+        throw;
+    }
+
+    // If we get here we've got an error.
+    return HSE_STATUS_ERROR;
+}
diff --git a/isapi_shib/isapi_shib.cpp.r3097 b/isapi_shib/isapi_shib.cpp.r3097
new file mode 100644 (file)
index 0000000..2a1130d
--- /dev/null
@@ -0,0 +1,1008 @@
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * isapi_shib.cpp
+ *
+ * Shibboleth ISAPI filter
+ */
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_RAND_S
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/Base64.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <set>
+#include <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <process.h>
+
+#include <windows.h>
+#include <httpfilt.h>
+#include <httpext.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+// globals
+namespace {
+    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);
+    static const XMLCh validate[] =         UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+    static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);
+    static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);
+    static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);
+    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);
+    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);
+    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);
+    static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);
+
+    struct site_t {
+        site_t(const DOMElement* e)
+        {
+            auto_ptr_char n(e->getAttributeNS(NULL,name));
+            auto_ptr_char s(e->getAttributeNS(NULL,scheme));
+            auto_ptr_char p(e->getAttributeNS(NULL,port));
+            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
+            if (n.get()) m_name=n.get();
+            if (s.get()) m_scheme=s.get();
+            if (p.get()) m_port=p.get();
+            if (p2.get()) m_sslport=p2.get();
+            e = XMLHelper::getFirstChildElement(e, Alias);
+            while (e) {
+                if (e->hasChildNodes()) {
+                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());
+                    m_aliases.insert(alias.get());
+                }
+                e = XMLHelper::getNextSiblingElement(e, Alias);
+            }
+        }
+        string m_scheme,m_port,m_sslport,m_name;
+        set<string> m_aliases;
+    };
+
+    HINSTANCE g_hinstDLL;
+    SPConfig* g_Config = NULL;
+    map<string,site_t> g_Sites;
+    bool g_bNormalizeRequest = true;
+    string g_unsetHeaderValue,g_spoofKey;
+    bool g_checkSpoofing = true;
+    bool g_catchAll = false;
+    bool g_bSafeHeaderNames = false;
+    vector<string> g_NoCerts;
+}
+
+BOOL LogEvent(
+    LPCSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCSTR  message)
+{
+    LPCSTR  messages[] = {message, NULL};
+
+    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
+    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
+    return (DeregisterEventSource(hElog) && res);
+}
+
+void _my_invalid_parameter_handler(
+   const wchar_t * expression,
+   const wchar_t * function,
+   const wchar_t * file,
+   unsigned int line,
+   uintptr_t pReserved
+   )
+{
+    return;
+}
+
+extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
+{
+    if (fdwReason==DLL_PROCESS_ATTACH)
+        g_hinstDLL=hinstDLL;
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
+{
+    if (!pVer)
+        return FALSE;
+
+    if (!g_Config) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Extension mode startup not possible, is the DLL loaded as a filter?");
+        return FALSE;
+    }
+
+    pVer->dwExtensionVersion=HSE_VERSION;
+    strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI TerminateExtension(DWORD)
+{
+    return TRUE;    // cleanup should happen when filter unloads
+}
+
+extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
+{
+    if (!pVer)
+        return FALSE;
+    else if (g_Config) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Reentrant filter initialization, ignoring...");
+        return TRUE;
+    }
+
+    g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed during library initialization, check native log for help.");
+        return FALSE;
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed to load configuration, check native log for details.");
+        return FALSE;
+    }
+
+    // Access implementation-specifics and site mappings.
+    ServiceProvider* sp=g_Config->getServiceProvider();
+    Locker locker(sp);
+    const PropertySet* props=sp->getPropertySet("InProcess");
+    if (props) {
+        pair<bool,bool> flag=props->getBool("checkSpoofing");
+        g_checkSpoofing = !flag.first || flag.second;
+        flag=props->getBool("catchAll");
+        g_catchAll = flag.first && flag.second;
+
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        if (unsetValue.first)
+            g_unsetHeaderValue = unsetValue.second;
+        if (g_checkSpoofing) {
+            unsetValue = props->getString("spoofKey");
+            if (unsetValue.first)
+                g_spoofKey = unsetValue.second;
+            else {
+                _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
+                unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
+                if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
+                    _set_invalid_parameter_handler(old);
+                    ostringstream keystr;
+                    keystr << randkey << randkey2 << randkey3 << randkey4;
+                    g_spoofKey = keystr.str();
+                }
+                else {
+                    _set_invalid_parameter_handler(old);
+                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
+                    locker.assign();    // pops lock on SP config
+                    g_Config->term();
+                    g_Config=NULL;
+                    return FALSE;
+                }
+            }
+        }
+
+        props = props->getPropertySet("ISAPI");
+        if (props) {
+            flag = props->getBool("normalizeRequest");
+            g_bNormalizeRequest = !flag.first || flag.second;
+            flag = props->getBool("safeHeaderNames");
+            g_bSafeHeaderNames = flag.first && flag.second;
+            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
+            while (child) {
+                auto_ptr_char id(child->getAttributeNS(NULL,id));
+                if (id.get())
+                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
+                child=XMLHelper::getNextSiblingElement(child,Site);
+            }
+        }
+    }
+
+    pVer->dwFilterVersion=HTTP_FILTER_REVISION;
+    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
+    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
+                   SF_NOTIFY_SECURE_PORT |
+                   SF_NOTIFY_NONSECURE_PORT |
+                   SF_NOTIFY_PREPROC_HEADERS |
+                   SF_NOTIFY_LOG);
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
+    return TRUE;
+}
+
+extern "C" BOOL WINAPI TerminateFilter(DWORD)
+{
+    if (g_Config)
+        g_Config->term();
+    g_Config = NULL;
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");
+    return TRUE;
+}
+
+/* Next up, some suck-free versions of various APIs.
+
+   You DON'T require people to guess the buffer size and THEN tell them the right size.
+   Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that
+   constant strings aren't typed as such, making it just that much harder. These versions
+   are now updated to use a special growable buffer object, modeled after the standard
+   string class. The standard string won't work because they left out the option to
+   pre-allocate a non-constant buffer.
+*/
+
+class dynabuf
+{
+public:
+    dynabuf() { bufptr=NULL; buflen=0; }
+    dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }
+    ~dynabuf() { delete[] bufptr; }
+    size_t length() const { return bufptr ? strlen(bufptr) : 0; }
+    size_t size() const { return buflen; }
+    bool empty() const { return length()==0; }
+    void reserve(size_t s, bool keep=false);
+    void erase() { if (bufptr) memset(bufptr,0,buflen); }
+    operator char*() { return bufptr; }
+    bool operator ==(const char* s) const;
+    bool operator !=(const char* s) const { return !(*this==s); }
+private:
+    char* bufptr;
+    size_t buflen;
+};
+
+void dynabuf::reserve(size_t s, bool keep)
+{
+    if (s<=buflen)
+        return;
+    char* p=new char[s];
+    if (keep)
+        while (buflen--)
+            p[buflen]=bufptr[buflen];
+    buflen=s;
+    delete[] bufptr;
+    bufptr=p;
+}
+
+bool dynabuf::operator==(const char* s) const
+{
+    if (buflen==NULL || s==NULL)
+        return (buflen==NULL && s==NULL);
+    else
+        return strcmp(bufptr,s)==0;
+}
+
+void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
+               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
+{
+    s.reserve(size);
+    s.erase();
+    size=s.size();
+
+    while (!pn->GetHeader(pfc,lpszName,s,&size)) {
+        // Grumble. Check the error.
+        DWORD e=GetLastError();
+        if (e==ERROR_INSUFFICIENT_BUFFER)
+            s.reserve(size);
+        else
+            break;
+    }
+    if (bRequired && s.empty())
+        throw ERROR_NO_DATA;
+}
+
+/****************************************************************************/
+// ISAPI Filter
+
+class ShibTargetIsapiF : public AbstractSPRequest
+{
+  PHTTP_FILTER_CONTEXT m_pfc;
+  PHTTP_FILTER_PREPROC_HEADERS m_pn;
+  multimap<string,string> m_headers;
+  int m_port;
+  string m_scheme,m_hostname;
+  mutable string m_remote_addr,m_content_type,m_method;
+  dynabuf m_allhttp;
+  bool m_firsttime;
+
+public:
+  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {
+
+    // URL path always come from IIS.
+    dynabuf var(256);
+    GetHeader(pn,pfc,"url",var,256,false);
+    setRequestURI(var);
+
+    // Port may come from IIS or from site def.
+    if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {
+        GetServerVariable(pfc,"SERVER_PORT",var,10);
+        m_port = atoi(var);
+    }
+    else if (pfc->fIsSecurePort) {
+        m_port = atoi(site.m_sslport.c_str());
+    }
+    else {
+        m_port = atoi(site.m_port.c_str());
+    }
+
+    // Scheme may come from site def or be derived from IIS.
+    m_scheme=site.m_scheme;
+    if (m_scheme.empty() || !g_bNormalizeRequest)
+        m_scheme=pfc->fIsSecurePort ? "https" : "http";
+
+    GetServerVariable(pfc,"SERVER_NAME",var,32);
+
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
+    m_hostname = var;
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
+        m_hostname=site.m_name;
+
+    if (!g_spoofKey.empty()) {
+        GetHeader(pn, pfc, "ShibSpoofCheck:", var, 32, false);
+        if (!var.empty() && g_spoofKey == (char*)var)
+            m_firsttime = false;
+    }
+
+    if (!m_firsttime)
+        log(SPDebug, "ISAPI filter running more than once");
+  }
+  ~ShibTargetIsapiF() { }
+
+  const char* getScheme() const {
+    return m_scheme.c_str();
+  }
+  const char* getHostname() const {
+    return m_hostname.c_str();
+  }
+  int getPort() const {
+    return m_port;
+  }
+  const char* getQueryString() const {
+      const char* uri = getRequestURI();
+      uri = (uri ? strchr(uri, '?') : NULL);
+      return uri ? (uri + 1) : NULL;
+  }
+  const char* getMethod() const {
+    if (m_method.empty()) {
+        dynabuf var(5);
+        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
+        if (!var.empty())
+            m_method = var;
+    }
+    return m_method.c_str();
+  }
+  string getContentType() const {
+    if (m_content_type.empty()) {
+        dynabuf var(32);
+        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
+        if (!var.empty())
+            m_content_type = var;
+    }
+    return m_content_type;
+  }
+  string getRemoteAddr() const {
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();
+    if (m_remote_addr.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
+        if (!var.empty())
+            m_remote_addr = var;
+    }
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) {
+    AbstractSPRequest::log(level,msg);
+    if (level >= SPCrit)
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  }
+  string makeSafeHeader(const char* rawname) const {
+      string hdr;
+      for (; *rawname; ++rawname) {
+          if (isalnum(*rawname))
+              hdr += *rawname;
+      }
+      return (hdr + ':');
+  }
+  void clearHeader(const char* rawname, const char* cginame) {
+    if (g_checkSpoofing && m_firsttime) {
+        if (m_allhttp.empty())
+               GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);
+        string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');
+        if (strstr(m_allhttp, hdr.c_str()))
+            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));
+    }
+    if (g_bSafeHeaderNames) {
+        string hdr = makeSafeHeader(rawname);
+        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+    }
+    else if (!strcmp(rawname,"REMOTE_USER")) {
+           m_pn->SetHeader(m_pfc, "remote-user:", const_cast<char*>(g_unsetHeaderValue.c_str()));
+        m_pn->SetHeader(m_pfc, "remote_user:", const_cast<char*>(g_unsetHeaderValue.c_str()));
+       }
+       else {
+           string hdr = string(rawname) + ':';
+           m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
+       }
+  }
+  void setHeader(const char* name, const char* value) {
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
+    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
+  }
+  string getSecureHeader(const char* name) const {
+    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
+    dynabuf buf(256);
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
+    return string(buf.empty() ? "" : buf);
+  }
+  string getHeader(const char* name) const {
+    string hdr(name);
+    hdr += ':';
+    dynabuf buf(256);
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
+    return string(buf.empty() ? "" : buf);
+  }
+  void setRemoteUser(const char* user) {
+    setHeader("remote-user", user);
+    if (!user || !*user)
+        m_pfc->pFilterContext = NULL;
+    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
+        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
+  }
+  string getRemoteUser() const {
+    return getSecureHeader("remote-user");
+  }
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers.insert(make_pair(name,value));
+    else
+        m_headers.erase(name);
+  }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    const char* codestr="200 OK";
+    switch (status) {
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;
+    }
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);
+    }
+    return SF_STATUS_REQ_FINISHED;
+  }
+  long sendRedirect(const char* url) {
+    // XXX: Don't support the httpRedirect option, yet.
+    string hdr=string("Location: ") + url + "\r\n"
+      "Content-Type: text/html\r\n"
+      "Content-Length: 40\r\n"
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+    DWORD resplen=40;
+    m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
+    return SF_STATUS_REQ_FINISHED;
+  }
+  long returnDecline() {
+      return SF_STATUS_REQ_NEXT_NOTIFICATION;
+  }
+  long returnOK() {
+    return SF_STATUS_REQ_NEXT_NOTIFICATION;
+  }
+
+  const vector<string>& getClientCertificates() const {
+      return g_NoCerts;
+  }
+
+  // The filter never processes the POST, so stub these methods.
+  long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }
+  const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }
+};
+
+DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
+{
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
+                            "<H1>Shibboleth Filter Error</H1>";
+    DWORD resplen=strlen(xmsg);
+    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
+    resplen=strlen(msg);
+    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
+    static const char* xmsg2="</BODY></HTML>";
+    resplen=strlen(xmsg2);
+    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
+    return SF_STATUS_REQ_FINISHED;
+}
+
+extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
+{
+    // Is this a log notification?
+    if (notificationType==SF_NOTIFY_LOG) {
+        if (pfc->pFilterContext)
+               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;
+    }
+
+    PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;
+    try
+    {
+        // Determine web site number. This can't really fail, I don't think.
+        dynabuf buf(128);
+        GetServerVariable(pfc,"INSTANCE_ID",buf,10);
+
+        // Match site instance to host name, skip if no match.
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+        if (map_i==g_Sites.end())
+            return SF_STATUS_REQ_NEXT_NOTIFICATION;
+
+        ostringstream threadid;
+        threadid << "[" << getpid() << "] isapi_shib" << '\0';
+        xmltooling::NDC ndc(threadid.str().c_str());
+
+        ShibTargetIsapiF stf(pfc, pn, map_i->second);
+
+        // "false" because we don't override the Shib settings
+        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
+        if (!g_spoofKey.empty())
+            pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast<char*>(g_spoofKey.c_str()));
+        if (res.first) return res.second;
+
+        // "false" because we don't override the Shib settings
+        res = stf.getServiceProvider().doExport(stf);
+        if (res.first) return res.second;
+
+        res = stf.getServiceProvider().doAuthorization(stf);
+        if (res.first) return res.second;
+
+        return SF_STATUS_REQ_NEXT_NOTIFICATION;
+    }
+    catch(bad_alloc) {
+        return WriteClientError(pfc,"Out of Memory");
+    }
+    catch(long e) {
+        if (e==ERROR_NO_DATA)
+            return WriteClientError(pfc,"A required variable or header was empty.");
+        else
+            return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");
+    }
+    catch (exception& e) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
+        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
+    }
+    catch(...) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw an unknown exception.");
+        if (g_catchAll)
+            return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");
+        throw;
+    }
+
+    return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");
+}
+
+
+/****************************************************************************/
+// ISAPI Extension
+
+DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
+{
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
+    DWORD resplen=strlen(xmsg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
+    resplen=strlen(msg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
+    static const char* xmsg2="</BODY></HTML>";
+    resplen=strlen(xmsg2);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
+    return HSE_STATUS_SUCCESS;
+}
+
+
+class ShibTargetIsapiE : public AbstractSPRequest
+{
+  LPEXTENSION_CONTROL_BLOCK m_lpECB;
+  multimap<string,string> m_headers;
+  mutable vector<string> m_certs;
+  mutable string m_body;
+  mutable bool m_gotBody;
+  int m_port;
+  string m_scheme,m_hostname,m_uri;
+  mutable string m_remote_addr,m_remote_user;
+
+public:
+  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)
+      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {
+    dynabuf ssl(5);
+    GetServerVariable(lpECB,"HTTPS",ssl,5);
+    bool SSL=(ssl=="on" || ssl=="ON");
+
+    // Scheme may come from site def or be derived from IIS.
+    m_scheme=site.m_scheme;
+    if (m_scheme.empty() || !g_bNormalizeRequest)
+        m_scheme = SSL ? "https" : "http";
+
+    // URL path always come from IIS.
+    dynabuf url(256);
+    GetServerVariable(lpECB,"URL",url,255);
+
+    // Port may come from IIS or from site def.
+    dynabuf port(11);
+    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
+        GetServerVariable(lpECB,"SERVER_PORT",port,10);
+    else if (SSL) {
+        strncpy(port,site.m_sslport.c_str(),10);
+        static_cast<char*>(port)[10]=0;
+    }
+    else {
+        strncpy(port,site.m_port.c_str(),10);
+        static_cast<char*>(port)[10]=0;
+    }
+    m_port = atoi(port);
+
+    dynabuf var(32);
+    GetServerVariable(lpECB, "SERVER_NAME", var, 32);
+
+    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
+    m_hostname=var;
+    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
+        m_hostname=site.m_name;
+
+    /*
+     * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if
+     * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",
+     * which is the default. No perfect way to tell, but we can take a good guess by checking
+     * whether the URL is a substring of the PATH_INFO:
+     *
+     * e.g. for /Shibboleth.sso/SAML/POST
+     *
+     *  Bad mode (default):
+     *      URL:        /Shibboleth.sso
+     *      PathInfo:   /Shibboleth.sso/SAML/POST
+     *
+     *  Good mode:
+     *      URL:        /Shibboleth.sso
+     *      PathInfo:   /SAML/POST
+     */
+
+    string uri;
+
+    // Clearly we're only in bad mode if path info exists at all.
+    if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {
+        if (strstr(lpECB->lpszPathInfo,url))
+            // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.
+            uri = lpECB->lpszPathInfo;
+        else {
+            uri = url;
+            uri += lpECB->lpszPathInfo;
+        }
+    }
+    else {
+        uri = url;
+    }
+
+    // For consistency with Apache, let's add the query string.
+    if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {
+        uri += '?';
+        uri += lpECB->lpszQueryString;
+    }
+
+    setRequestURI(uri.c_str());
+  }
+  ~ShibTargetIsapiE() { }
+
+  const char* getScheme() const {
+    return m_scheme.c_str();
+  }
+  const char* getHostname() const {
+    return m_hostname.c_str();
+  }
+  int getPort() const {
+    return m_port;
+  }
+  const char* getMethod() const {
+    return m_lpECB->lpszMethod;
+  }
+  string getContentType() const {
+    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";
+  }
+  long getContentLength() const {
+      return m_lpECB->cbTotalBytes;
+  }
+  string getRemoteUser() const {
+    if (m_remote_user.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
+        if (!var.empty())
+            m_remote_user = var;
+    }
+    return m_remote_user;
+  }
+  string getRemoteAddr() const {
+    m_remote_addr = AbstractSPRequest::getRemoteAddr();
+    if (m_remote_addr.empty()) {
+        dynabuf var(16);
+        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
+        if (!var.empty())
+            m_remote_addr = var;
+    }
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) const {
+      AbstractSPRequest::log(level,msg);
+      if (level >= SPCrit)
+          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  }
+  string getHeader(const char* name) const {
+    string hdr("HTTP_");
+    for (; *name; ++name) {
+        if (*name=='-')
+            hdr += '_';
+        else
+            hdr += toupper(*name);
+    }
+    dynabuf buf(128);
+    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
+    return buf.empty() ? "" : buf;
+  }
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers.insert(make_pair(name,value));
+    else
+        m_headers.erase(name);
+  }
+  const char* getQueryString() const {
+    return m_lpECB->lpszQueryString;
+  }
+  const char* getRequestBody() const {
+    if (m_gotBody)
+        return m_body.c_str();
+    if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
+        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
+    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
+      m_gotBody=true;
+      DWORD datalen=m_lpECB->cbTotalBytes;
+      if (m_lpECB->cbAvailable > 0) {
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
+        datalen-=m_lpECB->cbAvailable;
+      }
+      char buf[8192];
+      while (datalen) {
+        DWORD buflen=8192;
+        BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
+        if (!ret)
+            throw IOException("Error reading request body from browser.");
+        else if (!buflen)
+            throw IOException("Socket closed while reading request body from browser.");
+        m_body.append(buf, buflen);
+        datalen-=buflen;
+      }
+    }
+    else if (m_lpECB->cbAvailable) {
+        m_gotBody=true;
+        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
+    }
+    return m_body.c_str();
+  }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    const char* codestr="200 OK";
+    switch (status) {
+        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;
+    }
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);
+    }
+    return HSE_STATUS_SUCCESS;
+  }
+  long sendRedirect(const char* url) {
+    string hdr=string("Location: ") + url + "\r\n"
+      "Content-Type: text/html\r\n"
+      "Content-Length: 40\r\n"
+      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());
+    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+    DWORD resplen=40;
+    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
+    return HSE_STATUS_SUCCESS;
+  }
+  // Decline happens in the POST processor if this isn't the shire url
+  // Note that it can also happen with HTAccess, but we don't support that, yet.
+  long returnDecline() {
+    return WriteClientError(
+        m_lpECB,
+        "ISAPI extension can only be invoked to process Shibboleth protocol requests."
+               "Make sure the mapped file extension doesn't match actual content."
+        );
+  }
+  long returnOK() {
+      return HSE_STATUS_SUCCESS;
+  }
+
+  const vector<string>& getClientCertificates() const {
+      if (m_certs.empty()) {
+        char CertificateBuf[8192];
+        CERT_CONTEXT_EX ccex;
+        ccex.cbAllocated = sizeof(CertificateBuf);
+        ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;
+        DWORD dwSize = sizeof(ccex);
+
+        if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {
+            if (ccex.CertContext.cbCertEncoded) {
+                xsecsize_t outlen;
+                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
+                m_certs.push_back(reinterpret_cast<char*>(serialized));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&serialized);
+#else
+                XMLString::release((char**)&serialized);
+#endif
+            }
+        }
+      }
+      return m_certs;
+  }
+
+  // Not used in the extension.
+  void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }
+  void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
+  void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
+};
+
+extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
+{
+    try {
+        ostringstream threadid;
+        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
+        xmltooling::NDC ndc(threadid.str().c_str());
+
+        // Determine web site number. This can't really fail, I don't think.
+        dynabuf buf(128);
+        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
+
+        // Match site instance to host name, skip if no match.
+        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+        if (map_i==g_Sites.end())
+            return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check <ISAPI> mappings in configuration).");
+
+        ShibTargetIsapiE ste(lpECB, map_i->second);
+        pair<bool,long> res = ste.getServiceProvider().doHandler(ste);
+        if (res.first) return res.second;
+
+        return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
+
+    }
+    catch(bad_alloc) {
+        return WriteClientError(lpECB,"Out of Memory");
+    }
+    catch(long e) {
+        if (e==ERROR_NO_DATA)
+            return WriteClientError(lpECB,"A required variable or header was empty.");
+        else
+            return WriteClientError(lpECB,"Server detected unexpected IIS error.");
+    }
+    catch (exception& e) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
+        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
+    }
+    catch(...) {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw an unknown exception.");
+        if (g_catchAll)
+            return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");
+        throw;
+    }
+
+    // If we get here we've got an error.
+    return HSE_STATUS_ERROR;
+}
index 26733a8..4a6f709 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,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, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "isapi_shib\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "isapi_shib.dll\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 3f1bad4..f82279a 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="isapi_shib"
        ProjectGUID="{87C25D4E-8D19-4513-B0BA-BC668BC2DEE3}"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
                        <Tool
                                Name="VCLinkerTool"
                                AdditionalOptions="/export:GetExtensionVersion /export:GetFilterVersion /export:TerminateExtension /export:TerminateFilter /export:HttpFilterProc /export:HttpExtensionProc"
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib"
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="1"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-                       IntermediateDirectory="$(ConfigurationName)"
+                       Name="Release|x64"
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="1"
-                               TypeLibraryName=".\Debug/isapi_shib.tlb"
+                               TargetEnvironment="3"
+                               TypeLibraryName=".\Release/isapi_shib.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="0"
+                               Optimization="2"
+                               InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0400"
-                               BasicRuntimeChecks="3"
-                               RuntimeLibrary="3"
+                               PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0400"
+                               StringPooling="true"
+                               RuntimeLibrary="2"
+                               EnableFunctionLevelLinking="true"
                                BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
-                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                Culture="1033"
                        />
                        <Tool
                        <Tool
                                Name="VCLinkerTool"
                                AdditionalOptions="/export:GetExtensionVersion /export:GetFilterVersion /export:TerminateExtension /export:TerminateFilter /export:HttpFilterProc /export:HttpExtensionProc"
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib"
-                               LinkIncremental="2"
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib"
+                               LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
-                               GenerateDebugInformation="true"
-                               TargetMachine="1"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
+                               ProgramDatabaseFile=".\Release/isapi_shib.pdb"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="17"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Release|x64"
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="3"
-                               TypeLibraryName=".\Release/isapi_shib.tlb"
+                               TargetEnvironment="1"
+                               TypeLibraryName=".\Debug/isapi_shib.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="1"
+                               Optimization="0"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0400"
-                               StringPooling="true"
-                               RuntimeLibrary="2"
-                               EnableFunctionLevelLinking="true"
+                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0400"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
                                BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
+                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                Culture="1033"
                        />
                        <Tool
                        <Tool
                                Name="VCLinkerTool"
                                AdditionalOptions="/export:GetExtensionVersion /export:GetFilterVersion /export:TerminateExtension /export:TerminateFilter /export:HttpFilterProc /export:HttpExtensionProc"
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib"
-                               LinkIncremental="1"
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib"
+                               LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
-                               ProgramDatabaseFile=".\Release/isapi_shib.pdb"
-                               TargetMachine="17"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
+                               GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="1"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                        <Tool
                                Name="VCLinkerTool"
                                AdditionalOptions="/export:GetExtensionVersion /export:GetFilterVersion /export:TerminateExtension /export:TerminateFilter /export:HttpFilterProc /export:HttpExtensionProc"
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib"
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
                                GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="17"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
index d1fb373..c208108 100644 (file)
 # include "config.h"\r
 #endif\r
 \r
+#ifdef WIN32\r
+# define _CRT_NONSTDC_NO_DEPRECATE 1\r
+# define _CRT_SECURE_NO_DEPRECATE 1\r
+# define MCEXT_EXPORTS __declspec(dllexport)\r
+#else\r
+# define MCEXT_EXPORTS\r
+#endif\r
+\r
+#include <xmltooling/base.h>\r
+\r
+#include <iostream> \r
+#include <libmemcached/memcached.h>\r
 #include <xercesc/util/XMLUniDefs.hpp>\r
 \r
 #include <xmltooling/logging.h>\r
-\r
 #include <xmltooling/XMLToolingConfig.h>\r
 #include <xmltooling/util/NDC.h>\r
 #include <xmltooling/util/StorageService.h>\r
 #include <xmltooling/util/XMLHelper.h>\r
 \r
-#include <libmemcached/memcached.h>\r
-\r
 using namespace xmltooling::logging;\r
 using namespace xmltooling;\r
 using namespace xercesc;\r
@@ -100,7 +109,7 @@ namespace xmltooling {
     memcached_st *memc;\r
     string m_memcacheHosts;\r
     string m_prefix;\r
-    \r
+    Mutex* m_lock;\r
   };\r
   \r
   class MemcacheStorageService : public StorageService, public MemcacheBase {\r
@@ -151,15 +160,19 @@ bool MemcacheBase::addLock(string what, bool use_prefix) {
   string set_val = "1";\r
   unsigned tries = 5;\r
   while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {\r
-    if (tries-- < 0) {\r
+    if (tries-- == 0) {\r
       log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());\r
       return false;\r
     }\r
     log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());\r
     \r
     // sleep 100ms\r
+#ifdef WIN32\r
+    Sleep(100);\r
+#else\r
     struct timeval tv = { 0, 100000 };\r
-    select(0, 0, 0, 0, &tv);    \r
+    select(0, 0, 0, 0, &tv);\r
+#endif\r
   }\r
   return true;\r
 }\r
@@ -264,7 +277,6 @@ bool MemcacheBase::deleteMemcache(const char *key,
                                   bool use_prefix) {\r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -273,23 +285,25 @@ bool MemcacheBase::deleteMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::deleteMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_delete(&clone, (char *)final_key.c_str(), final_key.length(), timeout);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTFOUND) {\r
     // Key wasn't there... No biggie.\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
-    log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     // shouldn't be here\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -301,7 +315,6 @@ bool MemcacheBase::getMemcache(const char *key,
   size_t len;\r
   char *result;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
   \r
   if (use_prefix) {\r
@@ -310,11 +323,10 @@ bool MemcacheBase::getMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::getMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
+  m_lock->unlock();\r
 \r
-  result = memcached_get(&clone, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     dest = result;\r
     free(result);\r
@@ -322,12 +334,15 @@ bool MemcacheBase::getMemcache(const char *key,
   } else if (rv == MEMCACHED_NOTFOUND) {\r
     log.debug("Key %s not found in memcache...", key);\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
-    log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -339,7 +354,6 @@ bool MemcacheBase::addMemcache(const char *key,
 \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -348,23 +362,25 @@ bool MemcacheBase::addMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::addMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_add(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTSTORED) {\r
     // already there\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -376,7 +392,6 @@ bool MemcacheBase::setMemcache(const char *key,
 \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -385,20 +400,22 @@ bool MemcacheBase::setMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::setMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_set(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -410,7 +427,6 @@ bool MemcacheBase::replaceMemcache(const char *key,
   \r
   memcached_return rv;\r
   string final_key;\r
-  memcached_st clone;\r
   bool success;\r
 \r
   if (use_prefix) {\r
@@ -419,23 +435,25 @@ bool MemcacheBase::replaceMemcache(const char *key,
     final_key = key;\r
   }\r
 \r
-  if (memcached_clone(&clone, memc) == NULL) {\r
-    throw IOException("MemcacheBase::replaceMemcache(): memcached_clone() failed");\r
-  }\r
+  m_lock->lock();\r
+  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
+  m_lock->unlock();\r
 \r
-  rv = memcached_replace(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
   if (rv == MEMCACHED_SUCCESS) {\r
     success = true;\r
   } else if (rv == MEMCACHED_NOTSTORED) {\r
     // not there\r
     success = false;\r
+  } else if (rv == MEMCACHED_ERRNO) {\r
+    // System error\r
+    log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
+    success = false;\r
   } else {\r
     // shouldn't be here\r
-    log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(&clone, rv));\r
+    log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv));\r
     success = false;\r
   }\r
 \r
-  memcached_free(&clone);\r
   return success;\r
 }\r
 \r
@@ -456,6 +474,9 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
   log.debug("INIT: GOT Hosts: %s", h.get());\r
   m_memcacheHosts = h.get();\r
 \r
+  m_lock = Mutex::create();\r
+  log.debug("Lock created");\r
+\r
   memc = memcached_create(NULL);\r
   if (memc == NULL) {\r
     throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");\r
@@ -463,10 +484,23 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
 \r
   log.debug("Memcache created");\r
 \r
-  unsigned int set = MEMCACHED_HASH_CRC;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, set);\r
+  unsigned int hash = MEMCACHED_HASH_CRC;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);\r
   log.debug("CRC hash set");\r
 \r
+  int32_t timeout = 1000000;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout);\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout);\r
+\r
+  int32_t poll_timeout = 1000;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);\r
+\r
+  int32_t fail_limit = 5;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);\r
+\r
+  int32_t retry_timeout = 30;\r
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);\r
+\r
   memcached_server_st *servers;\r
   servers = memcached_servers_parse((char *)m_memcacheHosts.c_str());\r
   log.debug("Got %u hosts.",  memcached_server_list_count(servers));\r
@@ -480,6 +514,7 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
 \r
 MemcacheBase::~MemcacheBase() {\r
   memcached_free(memc);\r
+  delete m_lock;\r
   log.debug("Base object destroyed");\r
 }\r
 \r
@@ -564,6 +599,19 @@ int MemcacheStorageService::readString(const char* context, const char* key, str
   uint32_t rec_version;\r
   string value;\r
 \r
+  if (m_buildMap) {\r
+    log.debug("Checking context");\r
+\r
+    string map_name = context;\r
+    string ser_arr;\r
+    uint32_t flags;\r
+    bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);\r
+\r
+    if (!ctx_found) {\r
+      return 0;\r
+    }\r
+  }\r
+\r
   bool found = getMemcache(final_key.c_str(), value, &rec_version);\r
   if (!found) {\r
     return 0;\r
@@ -645,12 +693,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
   }\r
 \r
   string map_name = context;\r
-  \r
-  if (! addLock(map_name)) {\r
-    log.error("Unable to get lock for context %s!", context);\r
-    return;\r
-  }\r
-  \r
   string ser_arr;\r
   uint32_t flags;\r
   bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
@@ -681,8 +723,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
     replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);\r
   }\r
   \r
-  deleteLock(map_name);\r
-  \r
 }\r
 \r
 void MemcacheStorageService::deleteContext(const char* context) {\r
@@ -695,12 +735,6 @@ void MemcacheStorageService::deleteContext(const char* context) {
   }\r
 \r
   string map_name = context;\r
-  \r
-  if (! addLock(map_name)) {\r
-    log.error("Unable to get lock for context %s!", context);\r
-    return;\r
-  }\r
-  \r
   string ser_arr;\r
   uint32_t flags;\r
   bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
@@ -723,16 +757,14 @@ void MemcacheStorageService::deleteContext(const char* context) {
     deleteMemcache(map_name.c_str(), 0);\r
   }\r
   \r
-  deleteLock(map_name);\r
-\r
 }\r
 \r
-extern "C" int xmltooling_extension_init(void*) {\r
+extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {\r
     // Register this SS type\r
     XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);\r
     return 0;\r
 }\r
 \r
-extern "C" void xmltooling_extension_term() {\r
+extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {\r
     XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");\r
 }\r
index ee39660..ffd78ff 100644 (file)
@@ -53,8 +53,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,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, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "memcache-store\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "OriginalFilename", "memcache-store.so\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
         END
     END
     BLOCK "VarFileInfo"
index 854aad3..245333c 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="memcache-store"\r
        ProjectGUID="{666A63A7-983F-4C19-8411-207F24305198}"\r
        RootNamespace="memcachestore"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
@@ -43,7 +44,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;;..\..\..\libmemcached"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib memcached.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;..\..\..\libmemcached\visualc\$(ConfigurationName)&quot;"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
-                               RuntimeLibrary="2"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;;..\..\..\libmemcached\visualc\toolset"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               LinkIncremental="2"\r
+                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
-                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
-                               BrowseInformation="1"\r
+                               AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;;..\..\..\libmemcached"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
+                               RuntimeLibrary="2"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib memcached.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               LinkIncremental="1"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;&quot;..\..\..\libmemcached\visualc\$(ConfigurationName)&quot;"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;;..\..\..\libmemcached\visualc\toolset"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
                                RuntimeLibrary="2"\r
                                WarningLevel="3"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
index ea38feb..960409d 100644 (file)
@@ -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.
@@ -31,6 +31,7 @@
 #ifdef WIN32
 # define _CRT_NONSTDC_NO_DEPRECATE 1
 # define _CRT_SECURE_NO_DEPRECATE 1
+# define _CRT_RAND_S
 #endif
 
 #include <shibsp/AbstractSPRequest.h>
@@ -75,13 +76,23 @@ using namespace std;
 namespace {
     SPConfig* g_Config=NULL;
     string g_ServerName;
-    string g_ServerScheme;
     string g_unsetHeaderValue;
+    string g_spoofKey;
     bool g_checkSpoofing = true;
     bool g_catchAll = false;
 
     static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);
     static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+
+    void _my_invalid_parameter_handler(
+       const wchar_t * expression,
+       const wchar_t * function,
+       const wchar_t * file,
+       unsigned int line,
+       uintptr_t pReserved
+       ) {
+        return;
+    }
 }
 
 PluginManager<RequestMapper,string,const xercesc::DOMElement*>::Factory SunRequestMapFactory;
@@ -115,9 +126,6 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
             }
         }
     }
-    name=pblock_findval("server-scheme",pb);
-    if (name)
-        g_ServerScheme=name;
 
     log_error(LOG_INFORM,"nsapi_shib_init",sn,rq,"nsapi_shib loaded for host (%s)",g_ServerName.c_str());
 
@@ -139,7 +147,7 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
         return REQ_ABORTED;
     }
 
-    g_Config->RequestMapperManager.registerFactory(XML_REQUEST_MAPPER,&SunRequestMapFactory);
+    g_Config->RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER,&SunRequestMapFactory);
 
     try {
         if (!g_Config->instantiate(pblock_findval("shib-config",pb), true))
@@ -156,15 +164,41 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
 
     ServiceProvider* sp=g_Config->getServiceProvider();
     Locker locker(sp);
-    const PropertySet* props=sp->getPropertySet("Local");
+    const PropertySet* props=sp->getPropertySet("InProcess");
     if (props) {
-        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
-        if (unsetValue.first)
-            g_unsetHeaderValue = unsetValue.second;
         pair<bool,bool> flag=props->getBool("checkSpoofing");
         g_checkSpoofing = !flag.first || flag.second;
         flag=props->getBool("catchAll");
         g_catchAll = flag.first && flag.second;
+
+        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        if (unsetValue.first)
+            g_unsetHeaderValue = unsetValue.second;
+        if (g_checkSpoofing) {
+            unsetValue=props->getString("spoofKey");
+            if (unsetValue.first)
+                g_spoofKey = unsetValue.second;
+#ifdef WIN32
+            else {
+                _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
+                unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
+                if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
+                    _set_invalid_parameter_handler(old);
+                    ostringstream keystr;
+                    keystr << randkey << randkey2 << randkey3 << randkey4;
+                    g_spoofKey = keystr.str();
+                }
+                else {
+                    _set_invalid_parameter_handler(old);
+                    pblock_nvinsert("error", "module failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually)", pb);
+                    locker.assign(); // pops lock on SP config
+                    g_Config->term();
+                    g_Config=NULL;
+                    return REQ_ABORTED;
+                }
+            }
+#endif
+        }
     }
     return REQ_PROCEED;
 }
@@ -176,6 +210,8 @@ class ShibTargetNSAPI : public AbstractSPRequest
 {
   mutable string m_body;
   mutable bool m_gotBody,m_firsttime;
+  bool m_security_active;
+  int m_server_portnum;
   mutable vector<string> m_certs;
   set<string> m_allhttp;
 
@@ -185,10 +221,34 @@ public:
   Request* m_rq;
 
   ShibTargetNSAPI(pblock* pb, ::Session* sn, Request* rq)
-      : AbstractSPRequest(SHIBSP_LOGCAT".NSAPI"), m_gotBody(false), m_firsttime(true), m_pb(pb), m_sn(sn), m_rq(rq) {
+      : AbstractSPRequest(SHIBSP_LOGCAT".NSAPI"),
+        m_gotBody(false), m_firsttime(true), m_security_active(false), m_server_portnum(0), m_pb(pb), m_sn(sn), m_rq(rq) {
+
+    // To determine whether SSL is active or not, we're supposed to rely
+    // on the security_active macro. For iPlanet 4.x, this works.
+    // For Sun 7.x, it's useless and appears to be on or off based
+    // on whether ANY SSL support is enabled for a vhost. Sun 6.x is unknown.
+    // As a fix, there's a conf variable called $security that can be mapped
+    // into a function parameter: security_active="$security"
+    // We check for this parameter, and rely on the macro if it isn't set.
+    // This doubles as a scheme virtualizer for load balanced scenarios
+    // since you can set the parameter to 1 or 0 as needed.
+    const char* sa = pblock_findval("security_active", m_pb);
+    if (sa)
+        m_security_active = (*sa == '1');
+    else if (security_active)
+        m_security_active = true;
+    else
+        m_security_active = false;
+
+    // A similar issue exists for the port. server_portnum is no longer
+    // working on at least Sun 7.x, and returns the first listener's port
+    // rather than whatever port is actually used for the request. Nice job, Sun.
+    sa = pblock_findval("server_portnum", m_pb);
+    m_server_portnum = (sa && *sa) ? atoi(sa) : server_portnum;
 
-    const char* uri=pblock_findval("uri", rq->reqpb);
-    const char* qstr=pblock_findval("query", rq->reqpb);
+    const char* uri = pblock_findval("uri", rq->reqpb);
+    const char* qstr = pblock_findval("query", rq->reqpb);
 
     if (qstr) {
         string temp = string(uri) + '?' + qstr;
@@ -199,16 +259,18 @@ public:
     }
 
     // See if this is the first time we've run.
-    qstr = pblock_findval("auth-type", rq->vars);
-    if (qstr && !strcmp(qstr, "shibboleth"))
-        m_firsttime = false;
+    if (!g_spoofKey.empty()) {
+        qstr = pblock_findval("Shib-Spoof-Check", rq->headers);
+        if (qstr && g_spoofKey == qstr)
+            m_firsttime = false;
+    }
     if (!m_firsttime || rq->orig_rq)
         log(SPDebug, "nsapi_shib function running more than once");
   }
   ~ShibTargetNSAPI() { }
 
   const char* getScheme() const {
-    return security_active ? "https" : "http";
+    return m_security_active ? "https" : "http";
   }
   const char* getHostname() const {
 #ifdef vs_is_default_vs
@@ -223,25 +285,28 @@ public:
     return g_ServerName.c_str();
   }
   int getPort() const {
-    return server_portnum;
+    return m_server_portnum;
   }
   const char* getMethod() const {
     return pblock_findval("method", m_rq->reqpb);
   }
   string getContentType() const {
-    char* content_type = "";
-    request_header("content-type", &content_type, m_sn, m_rq);
-    return content_type;
+    char* content_type = NULL;
+    if (request_header("content-type", &content_type, m_sn, m_rq) != REQ_PROCEED)
+        return "";
+    return content_type ? content_type : "";
   }
   long getContentLength() const {
     if (m_gotBody)
         return m_body.length();
-    char* content_length="";
-    request_header("content-length", &content_length, m_sn, m_rq);
-    return atoi(content_length);
+    char* content_length=NULL;
+    if (request_header("content-length", &content_length, m_sn, m_rq) != REQ_PROCEED)
+        return 0;
+    return content_length ? atoi(content_length) : 0;
   }
   string getRemoteAddr() const {
-    return pblock_findval("ip", m_sn->client);
+    string ret = AbstractSPRequest::getRemoteAddr();
+    return ret.empty() ? pblock_findval("ip", m_sn->client) : ret;
   }
   void log(SPLogLevel level, const string& msg) const {
     AbstractSPRequest::log(level,msg);
@@ -255,7 +320,11 @@ public:
     if (m_gotBody)
         return m_body.c_str();
     char* content_length=NULL;
-    if (request_header("content-length", &content_length, m_sn, m_rq)!=REQ_PROCEED || atoi(content_length) > 1024*1024) // 1MB?
+    if (request_header("content-length", &content_length, m_sn, m_rq) != REQ_PROCEED || !content_length) {
+        m_gotBody = true;
+        return NULL;
+    }
+    else if (atoi(content_length) > 1024*1024) // 1MB?
       throw opensaml::SecurityPolicyException("Blocked request body exceeding 1M size limit.");
     else {
       char ch=IO_EOF+1;
@@ -296,8 +365,14 @@ public:
         if (m_allhttp.count(cginame) > 0)
             throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
     }
-    param_free(pblock_remove(rawname, m_rq->headers));
-    pblock_nvinsert(rawname, g_unsetHeaderValue.c_str(), m_rq->headers);
+    if (strcmp(rawname, "REMOTE_USER") == 0) {
+        param_free(pblock_remove("remote-user", m_rq->headers));
+        pblock_nvinsert("remote-user", g_unsetHeaderValue.c_str(), m_rq->headers);
+    }
+    else {
+        param_free(pblock_remove(rawname, m_rq->headers));
+        pblock_nvinsert(rawname, g_unsetHeaderValue.c_str(), m_rq->headers);
+    }
   }
   void setHeader(const char* name, const char* value) {
     param_free(pblock_remove(name, m_rq->headers));
@@ -323,11 +398,27 @@ public:
   }
   void setRemoteUser(const char* user) {
     pblock_nvinsert("auth-user", user, m_rq->vars);
+    param_free(pblock_remove("remote-user", m_rq->headers));
+    pblock_nvinsert("remote-user", user, m_rq->headers);
   }
   string getRemoteUser() const {
     const char* ru = pblock_findval("auth-user", m_rq->vars);
     return ru ? ru : "";
   }
+  void setAuthType(const char* authtype) {
+    param_free(pblock_remove("auth-type", m_rq->vars));
+    if (authtype)
+        pblock_nvinsert("auth-type", authtype, m_rq->vars);
+  }
+  string getAuthType() const {
+    const char* at = pblock_findval("auth-type", m_rq->vars);
+    return at ? at : "";
+  }
+  void setContentType(const char* type) {
+      // iPlanet seems to have a case folding problem.
+      param_free(pblock_remove("content-type", m_rq->srvhdrs));
+      setResponseHeader("Content-Type", type);
+  }
   void setResponseHeader(const char* name, const char* value) {
     pblock_nvinsert(name, value, m_rq->srvhdrs);
   }
@@ -391,13 +482,16 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
 
     // Check user authentication
     pair<bool,long> res = stn.getServiceProvider().doAuthentication(stn);
+    // If directed, install a spoof key to recognize when we've already cleared headers.
+    if (!g_spoofKey.empty()) {
+      param_free(pblock_remove("Shib-Spoof-Check", rq->headers));
+      pblock_nvinsert("Shib-Spoof-Check", g_spoofKey.c_str(), rq->headers);
+    }
     if (res.first) return (int)res.second;
 
     // user authN was okay -- export the assertions now
     param_free(pblock_remove("auth-user",rq->vars));
-    // This seems to be required in order to eventually set
-    // the auth-user var.
-    pblock_nvinsert("auth-type","shibboleth",rq->vars);
+
     res = stn.getServiceProvider().doExport(stn);
     if (res.first) return (int)res.second;
 
@@ -442,6 +536,7 @@ extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an exception, see web server log for error.");
   }
   catch (...) {
+    log_error(LOG_FAILURE,FUNC,sn,rq,"unknown exception caught in Shibboleth handler");
     if (g_catchAll)
         return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an unknown exception.");
     throw;
index 6af4d84..ba31800 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,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, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "nsapi_shib\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "nsapi_shib.dll\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index a1c457b..ad271b0 100644 (file)
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="nsapi_shib"
        ProjectGUID="{1396D80A-8672-4224-9B02-95F3F4207CDB}"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib ns-httpd30.lib"
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib ns-httpd30.lib"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="1"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-                       IntermediateDirectory="$(ConfigurationName)"
+                       Name="Release|x64"
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="1"
-                               TypeLibraryName=".\Debug/nsapi_shib.tlb"
+                               TargetEnvironment="3"
+                               TypeLibraryName=".\Release/nsapi_shib.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="0"
+                               Optimization="2"
+                               InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
-                               BasicRuntimeChecks="3"
-                               RuntimeLibrary="3"
-                               BrowseInformation="1"
+                               PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32"
+                               StringPooling="true"
+                               RuntimeLibrary="2"
+                               EnableFunctionLevelLinking="true"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
-                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib ns-httpd30.lib"
-                               LinkIncremental="2"
+                               AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib ns-httpd30.lib"
+                               LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
-                               GenerateDebugInformation="true"
-                               TargetMachine="1"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
+                               ProgramDatabaseFile=".\Release/nsapi_shib.pdb"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="17"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Release|x64"
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
                        ConfigurationType="2"
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
                        UseOfMFC="0"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                MkTypLibCompatible="true"
                                SuppressStartupBanner="true"
-                               TargetEnvironment="3"
-                               TypeLibraryName=".\Release/nsapi_shib.tlb"
+                               TargetEnvironment="1"
+                               TypeLibraryName=".\Debug/nsapi_shib.tlb"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="1"
+                               Optimization="0"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32"
-                               StringPooling="true"
-                               RuntimeLibrary="2"
-                               EnableFunctionLevelLinking="true"
+                               PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
+                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
+                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib ns-httpd30.lib"
-                               LinkIncremental="1"
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib ns-httpd30.lib"
+                               LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
-                               ProgramDatabaseFile=".\Release/nsapi_shib.pdb"
-                               TargetMachine="17"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;"
+                               GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="1"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib ns-httpd30.lib"
+                               AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib ns-httpd30.lib"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;"
                                GenerateDebugInformation="true"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="17"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
index ef40f0e..1a9eb39 100644 (file)
@@ -53,8 +53,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,1,0
+ PRODUCTVERSION 2,2,1,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, 1, 0, 0\0"
+            VALUE "FileVersion", "2, 2, 1, 0\0"
             VALUE "InternalName", "odbc-store\0"
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "OriginalFilename", "odbc-store.so\0"
-            VALUE "ProductName", "Shibboleth 2.1\0"
-            VALUE "ProductVersion", "2, 1, 0, 0\0"
+            VALUE "ProductName", "Shibboleth 2.2.1\0"
+            VALUE "ProductVersion", "2, 2, 1, 0\0"
         END
     END
     BLOCK "VarFileInfo"
index 1b6a307..b15cf98 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="odbc-store"\r
        ProjectGUID="{666A63A7-983F-4C19-8411-207F24305197}"\r
        RootNamespace="odbcstore"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               LinkIncremental="2"\r
+                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories="&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
-                               BrowseInformation="1"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
+                               RuntimeLibrary="2"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
                        />\r
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
-                               LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               LinkIncremental="1"\r
+                               AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"\r
                                OutputFile="$(OutDir)\$(ProjectName).so"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
diff --git a/pkginfo b/pkginfo
index 67f161a..cd040c3 100644 (file)
--- a/pkginfo
+++ b/pkginfo
@@ -1,5 +1,5 @@
 PKG=SHIBsp
-VERSION=2.1
+VERSION=2.2.1
 BASEDIR=/
 NAME=shibboleth-sp
 CATEGORY=application,security
index 53f2469..9df027f 100644 (file)
@@ -1,5 +1,5 @@
 PKG=SHIBsp
-VERSION=@-VERSION-@
+VERSION=@PACKAGE_VERSION@
 BASEDIR=/
 NAME=shibboleth-sp
 CATEGORY=application,security
index 3a72cda..caf5e1e 100644 (file)
@@ -3,7 +3,7 @@
         xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:am="urn:mace:shibboleth:2.0:attribute-map"
         elementFormDefault="qualified"
-        version="2.1">
+        version="2.2">
 
     <annotation>
         <documentation>
     <simpleType name="listOfStrings">
         <list itemType="am:string"/>
     </simpleType>
+
+    <complexType name="PluggableType">
+        <sequence>
+            <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+        </sequence>
+        <attribute name="type" type="am:string" use="required"/>
+        <anyAttribute namespace="##any" processContents="lax"/>
+    </complexType>
     
     <element name="Attributes">
         <annotation>
         </annotation>
         <complexType>
             <sequence>
+                <element name="MetadataProvider" type="am:PluggableType" minOccurs="0"/>
+                <element name="TrustEngine" type="am:PluggableType" minOccurs="0"/>
+                <element name="AttributeFilter" type="am:PluggableType" minOccurs="0"/>
                 <element name="Attribute" type="am:AttributeType" maxOccurs="unbounded"/>
             </sequence>
+            <attribute name="metadataPolicyId" type="am:string"/>
         </complexType>
     </element>
 
                 Decodes a SAML attribute into its Shibboleth-internal representation.
             </documentation>
         </annotation>
-        <attribute name="caseSensitive" type="boolean" default="true">
+        <attribute name="caseSensitive" type="boolean">
             <annotation>
                 <documentation>
                     Flag controlling case sensitivity when comparisons to the attribute's values are done.
                 </documentation>
             </annotation>
         </attribute>
+        <attribute name="internal" type="boolean">
+            <annotation>
+                <documentation>Flag controlling whether the resulting attribute should be exported for CGI use.</documentation>
+            </annotation>
+        </attribute>
     </complexType>
     
     <complexType name="StringAttributeDecoder">
                         </documentation>
                     </annotation>
                 </attribute>
+                <attribute name="defaultQualifiers" type="boolean">
+                    <annotation>
+                        <documentation>
+                            Flag controlling whether to default in values for NameQualifier/SPNameQualifier if not set.
+                        </documentation>
+                    </annotation>
+                </attribute>
             </extension>
         </complexContent>
     </complexType>
                         </documentation>
                     </annotation>
                 </attribute>
+                <attribute name="defaultQualifiers" type="boolean">
+                    <annotation>
+                        <documentation>
+                            Flag controlling whether to default in values for NameQualifier/SPNameQualifier if not set.
+                        </documentation>
+                    </annotation>
+                </attribute>
                 <attribute name="formatter" type="am:string">
                     <annotation>
                         <documentation>
index f9950db..88befab 100644 (file)
@@ -8,7 +8,7 @@
        elementFormDefault="qualified"\r
        attributeFormDefault="unqualified"\r
        blockDefault="substitution"\r
-       version="2.1">\r
+       version="2.2">\r
 \r
        <import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>\r
        <import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>\r
@@ -87,6 +87,7 @@
                        </sequence>\r
                        <attribute name="logger" type="anyURI"/>\r
                        <attribute name="clockSkew" type="unsignedInt"/>\r
+            <attribute name="unsafeChars" type="conf:string"/>
                        <anyAttribute namespace="##other" processContents="lax"/>\r
                </complexType>\r
        </element>\r
                                <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
                        </sequence>\r
                        <attribute name="logger" type="anyURI"/>\r
-                       <attribute name="unsetHeaderValue" type="string"/>\r
+                       <attribute name="unsetHeaderValue" type="conf:string"/>\r
                        <attribute name="checkSpoofing" type="boolean"/>\r
-                   <attribute name="catchAll" type="boolean"/>\r
+                       <attribute name="spoofKey" type="conf:string"/>\r
+                       <attribute name="catchAll" type="boolean"/>\r
                        <anyAttribute namespace="##other" processContents="lax"/>\r
                </complexType>\r
        </element>\r
                                <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
                        </sequence>\r
                        <attribute name="normalizeRequest" type="boolean"/>\r
+                       <attribute name="safeHeaderNames" type="boolean"/>\r
                        <anyAttribute namespace="##other" processContents="lax"/>\r
                </complexType>\r
        </element>\r
                <attribute name="metadataError" type="anyURI"/>\r
                <attribute name="accessError" type="anyURI"/>\r
                <attribute name="sslError" type="anyURI"/>\r
+        <attribute name="REMOTE_ADDR" type="conf:string"/>\r
                <anyAttribute namespace="##other" processContents="lax"/>\r
        </attributeGroup>\r
        <element name="AccessControlProvider" type="conf:PluggableType"/>\r
                                        </complexType>\r
                                </element>\r
                        </choice>\r
-                       <attribute name="handlerURL" type="anyURI"/>\r
+                       <attribute name="handlerURL" type="anyURI" use="required"/>\r
                        <attribute name="handlerSSL" type="boolean"/>\r
                        <attribute name="exportLocation" type="conf:string"/>\r
                        <attribute name="exportACL" type="conf:listOfStrings"/>\r
                    <attribute name="maxTimeSinceAuthn" type="unsignedInt"/>\r
                        <attribute name="checkAddress" type="boolean"/>\r
                        <attribute name="consistentAddress" type="boolean"/>\r
+                       <attribute name="postData" type="conf:string"/>\r
+            <attribute name="postLimit" type="positiveInteger"/>\r
+                       <attribute name="postTemplate" type="conf:string"/>\r
+            <attribute name="postExpire" type="boolean"/>\r
                        <anyAttribute namespace="##other" processContents="lax"/>\r
                </complexType>\r
        </element>\r
                     <attribute name="forceAuthn" type="boolean"/>\r
                     <attribute name="authnContextClassRef" type="anyURI"/>\r
                     <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
+                    <attribute name="requestDelegation" type="boolean"/>\r
                                        <anyAttribute namespace="##any" processContents="lax"/>\r
                                </restriction>\r
                        </complexContent>\r
                                                <documentation>Specifies a set of SecurityPolicyRule plugins</documentation>\r
                                        </annotation>\r
                                        <complexType>\r
-                                               <sequence>\r
+                                               <choice>\r
                                                        <element name="Rule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>\r
-                                               </sequence>\r
+                            <element name="PolicyRule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>\r
+                                               </choice>\r
                                                <attribute name="id" type="conf:string" use="required"/>\r
                                                <attribute name="validate" type="boolean"/>\r
                                                <anyAttribute namespace="##any" processContents="lax"/>\r
index 89a86a1..393507a 100644 (file)
@@ -1,19 +1,32 @@
 Name:          shibboleth
-Summary:       Open source system for attribute-based Web SSO
-Version:       2.1
+Version:       2.2.1
 Release:       1
-#Copyright:    Internet2
+Summary:    Open source system for attribute-based Web SSO
 Group:         System Environment/Libraries
-License:       Apache style
+Vendor:     Internet2
+License:       Apache 2.0
 URL:           http://shibboleth.internet2.edu/
-Source0:       http://shibboleth.internet2.edu/downloads/%{name}-%{version}.tar.gz
+Source:     %{name}-sp-%{version}.tar.gz
 BuildRoot:     %{_tmppath}/%{name}-%{version}-root
-BuildRequires: openssl-devel
-BuildRequires: xerces%{?xercesver}-c-devel >= 2.8.0
+%if 0%{?suse_version} > 1030
+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
+%{?_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: zlib-devel, opensaml-devel >= 2.1
-%{?_with_log4cpp:BuildRequires:        log4cpp-devel >= 1.0}
+BuildRequires:  xmltooling-devel >= 1.2
+BuildRequires:  opensaml-devel >= 2.2
+%{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: log4shib-devel}
+%endif
+BuildRequires:  gcc-c++
+%{!?_without_doxygen:BuildRequires: doxygen}
+%{!?_without_odbc:BuildRequires:unixODBC-devel}
+BuildRequires:  zlib-devel
 %{?_with_fastcgi:BuildRequires: fcgi-devel}
 %if "%{_vendor}" == "redhat"
 %{!?_without_builtinapache:BuildRequires: httpd-devel}
@@ -22,68 +35,76 @@ BuildRequires:      zlib-devel, opensaml-devel >= 2.1
 %{!?_without_builtinapache:BuildRequires: apache2-devel}
 %endif
 
+%if "%{_vendor}" == "suse"
+%define pkgdocdir %{_docdir}/%{name}
+%else
+%define pkgdocdir %{_docdir}/%{name}-%{version}
+%endif
 
 %description
-Shibboleth, a project of Internet2/MACE, is developing architectures,
-policy structures, practical technologies, and an open source
-implementation to support inter-institutional sharing of web resources
-subject to access controls. In addition, Shibboleth will develop a
-policy framework that will allow inter-operation within the higher
-education community.
+Shibboleth is a Web Single Sign-On implementations based on OpenSAML
+that supports multiple protocols, federated identity, and the extensible
+exchange of rich attributes subject to privacy controls.
 
-This package contains the shibboleth runtime library and apache module.
+This package contains the Shibboleth Service Provider runtime libraries
+and Apache module(s).
 
 %package devel
 Summary: Shibboleth development Headers
 Group: Development/Libraries
 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
+%{?_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
+%{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
+%{!?_with_log4cpp:Requires: log4shib-devel}
+%endif
 
 %description devel
-Shibboleth, a project of Internet2/MACE, is developing architectures,
-policy structures, practical technologies, and an open source
-implementation to support inter-institutional sharing of web resources
-subject to access controls. In addition, Shibboleth will develop a
-policy framework that will allow inter-operation within the higher
-education community.
-
-This package contains the headers and other necessary files to build
-applications that use the shibboleth library.
-
-%package docs
-Summary: Shibboleth API Documentation
-Group: Development/Libraries
-Requires: %{name} = %{version}
+Shibboleth is a Web Single Sign-On implementations based on OpenSAML
+that supports multiple protocols, federated identity, and the extensible
+exchange of rich attributes subject to privacy controls.
+
+This package includes files needed for development with Shibboleth.
 
-%description docs
-Shibboleth Library API documentation generated by doxygen.
 
 %prep
 %setup -q
 
 %build
-%configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{?shib_options}
-%{__make}
+%configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{?_with_memcached} %{?shib_options}
+%{__make} pkgdocdir=%{pkgdocdir}
 
 %install
-[ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf $RPM_BUILD_ROOT
-%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT
+%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT pkgdocdir=%{pkgdocdir}
 
 %if "%{_vendor}" == "suse"
        %{__sed} -i "s/\/var\/log\/httpd/\/var\/log\/apache2/g" \
-               $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/native.logger
+               $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/native.logger
 %endif
 
-# Plug the SP into Apache on a recognized system.
+# Plug the SP into the built-in Apache on a recognized system.
+touch rpm.filelist
 APACHE_CONFIG="no"
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_13.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_13.so ] ; then
     APACHE_CONFIG="apache.config"
 fi
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_20.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_20.so ] ; then
     APACHE_CONFIG="apache2.config"
 fi
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_22.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_22.so ] ; then
     APACHE_CONFIG="apache22.config"
 fi
+%{?_without_builtinapache:APACHE_CONFIG="no"}
 if [ "$APACHE_CONFIG" != "no" ] ; then
     APACHE_CONFD="no"
     if [ -d %{_sysconfdir}/httpd/conf.d ] ; then
@@ -94,19 +115,19 @@ if [ "$APACHE_CONFIG" != "no" ] ; then
     fi
     if [ "$APACHE_CONFD" != "no" ] ; then
         %{__mkdir} -p $RPM_BUILD_ROOT$APACHE_CONFD
-%if "%{_vendor}" == "suse"
-        %{__sed} "s/\/usr\/doc\/%{name}/\/usr\/share\/doc\/packages\/%{name}/g" \
-            $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG \
-            > $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf
-%else
-        %{__sed} "s/\/usr\/doc\/%{name}/\/usr\/share\/doc\/%{name}-2.1/g" \
-            $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG \
-            > $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf
-%endif
+        %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf 
+        echo "%config $APACHE_CONFD/shib.conf" > rpm.filelist
     fi
 fi
 
-%check || :
+%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
+%endif
+
+%check
 %{__make} check
 
 %clean
@@ -117,34 +138,62 @@ fi
 /sbin/ldconfig
 %endif
 
-# Install the shibd init.d scripts and service
-%if "%{_vendor}" == "redhat"
-       if [ -d %{_sysconfdir}/init.d ] ; then
-               if [ ! -f %{_sysconfdir}/init.d/shibd ] ; then
-                       %{__cp} -p %{_sysconfdir}/%{name}/shibd-%{_vendor} %{_sysconfdir}/init.d/shibd
-                       %{__chmod} 755 %{_sysconfdir}/init.d/shibd
-                       chkconfig --add shibd
-               fi
-       fi
-%endif
-
 # Key generation
 cd %{_sysconfdir}/%{name}
 sh ./keygen.sh -b
 
-%postun
+%if "%{_vendor}" == "redhat"
+       # This adds the proper /etc/rc*.d links for the script
+       /sbin/chkconfig --add shibd
+       # 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/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+    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
+%endif
+
+%preun
+%if "%{_vendor}" == "redhat"
+       if [ "$1" = 0 ] ; then
+               /sbin/service shibd stop >/dev/null 2>&1
+               /sbin/chkconfig --del shibd
+       fi
+%endif
+%if "%{_vendor}" == "suse"
+    if [ "$1" = 0 ] ; then
+        /sbin/service shibd stop >/dev/null 2>&1
+        /sbin/chkconfig --del shibd
+        cd /usr/sbin && %{__rm} -f rcshibd
+    fi
+%endif
+
 %ifnos solaris2.8 solaris2.9 solaris2.10
-/sbin/ldconfig
+%postun -p /sbin/ldconfig
 %endif
 
-# clear init.d state
+%posttrans
+# ugly hack if init script got removed during %postun by upgraded (buggy/2.1) package
 %if "%{_vendor}" == "redhat"
-       chkconfig --del shibd
-       [ -f %{_sysconfdir}/init.d/shibd ] && \
-           %{__rm} -f %{_sysconfdir}/init.d/shibd
+    if [ ! -f %{_initrddir}/shibd ] ; then
+        if [ -f %{_sysconfdir}/%{name}/shibd-%{_vendor} ] ; then
+            %{__cp} -p %{_sysconfdir}/%{name}/shibd-%{_vendor} %{_initrddir}/shibd
+            %{__chmod} 755 %{_initrddir}/shibd
+            /sbin/chkconfig --add shibd
+        fi
+    fi
 %endif
 
-%files
+%files -f rpm.filelist
 %defattr(-,root,root,-)
 %{_sbindir}/shibd
 %{_bindir}/mdquery
@@ -162,41 +211,46 @@ sh ./keygen.sh -b
 %config(noreplace) %{_sysconfdir}/%{name}/*.xml
 %config(noreplace) %{_sysconfdir}/%{name}/*.html
 %config(noreplace) %{_sysconfdir}/%{name}/*.logger
-%if "%{_vendor}" == "suse"
-%config %{_sysconfdir}/apache2/conf.d/shib.conf
-%else
-%config %{_sysconfdir}/httpd/conf.d/shib.conf
+%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
+%attr(755, root, root) %{_initrddir}/shibd
 %endif
 %{_sysconfdir}/%{name}/*.dist
 %{_sysconfdir}/%{name}/apache*.config
-%{_sysconfdir}/%{name}/shibd-redhat
-%{_sysconfdir}/%{name}/shibd-debian
-%{_sysconfdir}/%{name}/shibd-osx.plist
-%{_sysconfdir}/%{name}/keygen.sh
+%{_sysconfdir}/%{name}/shibd-*
+%attr(755, root, root) %{_sysconfdir}/%{name}/keygen.sh
+%attr(755, root, root) %{_sysconfdir}/%{name}/metagen.sh
 %{_sysconfdir}/%{name}/*.xsl
-%docdir %{_datadir}/doc/%{name}
-%{_datadir}/doc/%{name}/CREDITS.txt
-%{_datadir}/doc/%{name}/FASTCGI.LICENSE
-%{_datadir}/doc/%{name}/LICENSE.txt
-%{_datadir}/doc/%{name}/LOG4CPP.LICENSE
-%{_datadir}/doc/%{name}/logo.jpg
-%{_datadir}/doc/%{name}/main.css
-%{_datadir}/doc/%{name}/NOTICE.txt
-%{_datadir}/doc/%{name}/OPENSSL.LICENSE
-%{_datadir}/doc/%{name}/README.txt
-%{_datadir}/doc/%{name}/RELEASE.txt
+%doc %{pkgdocdir}
+%exclude %{pkgdocdir}/api
 
 %files devel
 %defattr(-,root,root,-)
-%{_includedir}
+%{_includedir}/*
 %{_libdir}/libshibsp.so
 %{_libdir}/libshibsp-lite.so
-
-%files docs
-%defattr(644,root,root,755)
-%doc %{_datadir}/doc/%{name}/api
+%doc %{pkgdocdir}/api
 
 %changelog
+* Mon Aug 10 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2.1-1
+- Doc handling changes
+- SuSE init script
+
+* Tue Aug 4 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2.1-1
+- Initial version for 2.2.1, with shibd/httpd restart on upgrade
+
+* Thu Jun 25 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2-3
+- Add additional cleanup to posttrans fix
+
+* Tue Jun 23 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2-2
+- Reverse without_builtinapache macro test
+- Fix init script handling on Red Hat to handle upgrades
+
+* Wed Dec 3 2008  Scott Cantor  <cantor.2@osu.edu>  - 2.2-1
+- Bump minor version.
+- Make keygen.sh executable.
+- Fixing SUSE Xerces dependency name.
+- Optionally package shib.conf.
+
 * Tue Jun 10 2008  Scott Cantor  <cantor.2@osu.edu>  - 2.1-1
 - Change shib.conf handling to treat as config file.
 
index 2a9f809..b6f89d8 100644 (file)
@@ -1,19 +1,32 @@
-Name:          shibboleth
-Summary:       Open source system for attribute-based Web SSO
-Version:       @-VERSION-@
+Name:          @PACKAGE@
+Version:       @PACKAGE_VERSION@
 Release:       1
-#Copyright:    Internet2
+Summary:    Open source system for attribute-based Web SSO
 Group:         System Environment/Libraries
-License:       Apache style
+Vendor:     Internet2
+License:       Apache 2.0
 URL:           http://shibboleth.internet2.edu/
-Source0:       http://shibboleth.internet2.edu/downloads/%{name}-%{version}.tar.gz
+Source:     %{name}-sp-%{version}.tar.gz
 BuildRoot:     %{_tmppath}/%{name}-%{version}-root
-BuildRequires: openssl-devel
-BuildRequires: xerces%{?xercesver}-c-devel >= 2.8.0
+%if 0%{?suse_version} > 1030
+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
+%{?_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: zlib-devel, opensaml-devel >= 2.1
-%{?_with_log4cpp:BuildRequires:        log4cpp-devel >= 1.0}
+BuildRequires:  xmltooling-devel >= 1.2
+BuildRequires:  opensaml-devel >= 2.2
+%{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: log4shib-devel}
+%endif
+BuildRequires:  gcc-c++
+%{!?_without_doxygen:BuildRequires: doxygen}
+%{!?_without_odbc:BuildRequires:unixODBC-devel}
+BuildRequires:  zlib-devel
 %{?_with_fastcgi:BuildRequires: fcgi-devel}
 %if "%{_vendor}" == "redhat"
 %{!?_without_builtinapache:BuildRequires: httpd-devel}
@@ -22,68 +35,76 @@ BuildRequires:      zlib-devel, opensaml-devel >= 2.1
 %{!?_without_builtinapache:BuildRequires: apache2-devel}
 %endif
 
+%if "%{_vendor}" == "suse"
+%define pkgdocdir %{_docdir}/%{name}
+%else
+%define pkgdocdir %{_docdir}/%{name}-%{version}
+%endif
 
 %description
-Shibboleth, a project of Internet2/MACE, is developing architectures,
-policy structures, practical technologies, and an open source
-implementation to support inter-institutional sharing of web resources
-subject to access controls. In addition, Shibboleth will develop a
-policy framework that will allow inter-operation within the higher
-education community.
+Shibboleth is a Web Single Sign-On implementations based on OpenSAML
+that supports multiple protocols, federated identity, and the extensible
+exchange of rich attributes subject to privacy controls.
 
-This package contains the shibboleth runtime library and apache module.
+This package contains the Shibboleth Service Provider runtime libraries
+and Apache module(s).
 
 %package devel
 Summary: Shibboleth development Headers
 Group: Development/Libraries
 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
+%{?_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
+%{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
+%{!?_with_log4cpp:Requires: log4shib-devel}
+%endif
 
 %description devel
-Shibboleth, a project of Internet2/MACE, is developing architectures,
-policy structures, practical technologies, and an open source
-implementation to support inter-institutional sharing of web resources
-subject to access controls. In addition, Shibboleth will develop a
-policy framework that will allow inter-operation within the higher
-education community.
-
-This package contains the headers and other necessary files to build
-applications that use the shibboleth library.
-
-%package docs
-Summary: Shibboleth API Documentation
-Group: Development/Libraries
-Requires: %{name} = %{version}
+Shibboleth is a Web Single Sign-On implementations based on OpenSAML
+that supports multiple protocols, federated identity, and the extensible
+exchange of rich attributes subject to privacy controls.
+
+This package includes files needed for development with Shibboleth.
 
-%description docs
-Shibboleth Library API documentation generated by doxygen.
 
 %prep
 %setup -q
 
 %build
-%configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{?shib_options}
-%{__make}
+%configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{?_with_memcached} %{?shib_options}
+%{__make} pkgdocdir=%{pkgdocdir}
 
 %install
-[ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf $RPM_BUILD_ROOT
-%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT
+%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT pkgdocdir=%{pkgdocdir}
 
 %if "%{_vendor}" == "suse"
        %{__sed} -i "s/\/var\/log\/httpd/\/var\/log\/apache2/g" \
-               $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/native.logger
+               $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/native.logger
 %endif
 
-# Plug the SP into Apache on a recognized system.
+# Plug the SP into the built-in Apache on a recognized system.
+touch rpm.filelist
 APACHE_CONFIG="no"
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_13.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_13.so ] ; then
     APACHE_CONFIG="apache.config"
 fi
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_20.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_20.so ] ; then
     APACHE_CONFIG="apache2.config"
 fi
-if [ -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/mod_shib_22.so ] ; then
+if [ -f $RPM_BUILD_ROOT%{_libdir}/%{name}/mod_shib_22.so ] ; then
     APACHE_CONFIG="apache22.config"
 fi
+%{?_without_builtinapache:APACHE_CONFIG="no"}
 if [ "$APACHE_CONFIG" != "no" ] ; then
     APACHE_CONFD="no"
     if [ -d %{_sysconfdir}/httpd/conf.d ] ; then
@@ -94,19 +115,19 @@ if [ "$APACHE_CONFIG" != "no" ] ; then
     fi
     if [ "$APACHE_CONFD" != "no" ] ; then
         %{__mkdir} -p $RPM_BUILD_ROOT$APACHE_CONFD
-%if "%{_vendor}" == "suse"
-        %{__sed} "s/\/usr\/doc\/%{name}/\/usr\/share\/doc\/packages\/%{name}/g" \
-            $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG \
-            > $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf
-%else
-        %{__sed} "s/\/usr\/doc\/%{name}/\/usr\/share\/doc\/%{name}-@-VERSION-@/g" \
-            $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG \
-            > $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf
-%endif
+        %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/$APACHE_CONFIG $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf 
+        echo "%config $APACHE_CONFD/shib.conf" > rpm.filelist
     fi
 fi
 
-%check || :
+%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
+%endif
+
+%check
 %{__make} check
 
 %clean
@@ -117,34 +138,62 @@ fi
 /sbin/ldconfig
 %endif
 
-# Install the shibd init.d scripts and service
-%if "%{_vendor}" == "redhat"
-       if [ -d %{_sysconfdir}/init.d ] ; then
-               if [ ! -f %{_sysconfdir}/init.d/shibd ] ; then
-                       %{__cp} -p %{_sysconfdir}/%{name}/shibd-%{_vendor} %{_sysconfdir}/init.d/shibd
-                       %{__chmod} 755 %{_sysconfdir}/init.d/shibd
-                       chkconfig --add shibd
-               fi
-       fi
-%endif
-
 # Key generation
 cd %{_sysconfdir}/%{name}
 sh ./keygen.sh -b
 
-%postun
+%if "%{_vendor}" == "redhat"
+       # This adds the proper /etc/rc*.d links for the script
+       /sbin/chkconfig --add shibd
+       # 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/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+    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
+%endif
+
+%preun
+%if "%{_vendor}" == "redhat"
+       if [ "$1" = 0 ] ; then
+               /sbin/service shibd stop >/dev/null 2>&1
+               /sbin/chkconfig --del shibd
+       fi
+%endif
+%if "%{_vendor}" == "suse"
+    if [ "$1" = 0 ] ; then
+        /sbin/service shibd stop >/dev/null 2>&1
+        /sbin/chkconfig --del shibd
+        cd /usr/sbin && %{__rm} -f rcshibd
+    fi
+%endif
+
 %ifnos solaris2.8 solaris2.9 solaris2.10
-/sbin/ldconfig
+%postun -p /sbin/ldconfig
 %endif
 
-# clear init.d state
+%posttrans
+# ugly hack if init script got removed during %postun by upgraded (buggy/2.1) package
 %if "%{_vendor}" == "redhat"
-       chkconfig --del shibd
-       [ -f %{_sysconfdir}/init.d/shibd ] && \
-           %{__rm} -f %{_sysconfdir}/init.d/shibd
+    if [ ! -f %{_initrddir}/shibd ] ; then
+        if [ -f %{_sysconfdir}/%{name}/shibd-%{_vendor} ] ; then
+            %{__cp} -p %{_sysconfdir}/%{name}/shibd-%{_vendor} %{_initrddir}/shibd
+            %{__chmod} 755 %{_initrddir}/shibd
+            /sbin/chkconfig --add shibd
+        fi
+    fi
 %endif
 
-%files
+%files -f rpm.filelist
 %defattr(-,root,root,-)
 %{_sbindir}/shibd
 %{_bindir}/mdquery
@@ -162,41 +211,46 @@ sh ./keygen.sh -b
 %config(noreplace) %{_sysconfdir}/%{name}/*.xml
 %config(noreplace) %{_sysconfdir}/%{name}/*.html
 %config(noreplace) %{_sysconfdir}/%{name}/*.logger
-%if "%{_vendor}" == "suse"
-%config %{_sysconfdir}/apache2/conf.d/shib.conf
-%else
-%config %{_sysconfdir}/httpd/conf.d/shib.conf
+%if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
+%attr(755, root, root) %{_initrddir}/shibd
 %endif
 %{_sysconfdir}/%{name}/*.dist
 %{_sysconfdir}/%{name}/apache*.config
-%{_sysconfdir}/%{name}/shibd-redhat
-%{_sysconfdir}/%{name}/shibd-debian
-%{_sysconfdir}/%{name}/shibd-osx.plist
-%{_sysconfdir}/%{name}/keygen.sh
+%{_sysconfdir}/%{name}/shibd-*
+%attr(755, root, root) %{_sysconfdir}/%{name}/keygen.sh
+%attr(755, root, root) %{_sysconfdir}/%{name}/metagen.sh
 %{_sysconfdir}/%{name}/*.xsl
-%docdir %{_datadir}/doc/%{name}
-%{_datadir}/doc/%{name}/CREDITS.txt
-%{_datadir}/doc/%{name}/FASTCGI.LICENSE
-%{_datadir}/doc/%{name}/LICENSE.txt
-%{_datadir}/doc/%{name}/LOG4CPP.LICENSE
-%{_datadir}/doc/%{name}/logo.jpg
-%{_datadir}/doc/%{name}/main.css
-%{_datadir}/doc/%{name}/NOTICE.txt
-%{_datadir}/doc/%{name}/OPENSSL.LICENSE
-%{_datadir}/doc/%{name}/README.txt
-%{_datadir}/doc/%{name}/RELEASE.txt
+%doc %{pkgdocdir}
+%exclude %{pkgdocdir}/api
 
 %files devel
 %defattr(-,root,root,-)
-%{_includedir}
+%{_includedir}/*
 %{_libdir}/libshibsp.so
 %{_libdir}/libshibsp-lite.so
-
-%files docs
-%defattr(644,root,root,755)
-%doc %{_datadir}/doc/%{name}/api
+%doc %{pkgdocdir}/api
 
 %changelog
+* Mon Aug 10 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2.1-1
+- Doc handling changes
+- SuSE init script
+
+* Tue Aug 4 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2.1-1
+- Initial version for 2.2.1, with shibd/httpd restart on upgrade
+
+* Thu Jun 25 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2-3
+- Add additional cleanup to posttrans fix
+
+* Tue Jun 23 2009 Scott Cantor  <cantor.2@osu.edu>  - 2.2-2
+- Reverse without_builtinapache macro test
+- Fix init script handling on Red Hat to handle upgrades
+
+* Wed Dec 3 2008  Scott Cantor  <cantor.2@osu.edu>  - 2.2-1
+- Bump minor version.
+- Make keygen.sh executable.
+- Fixing SUSE Xerces dependency name.
+- Optionally package shib.conf.
+
 * Tue Jun 10 2008  Scott Cantor  <cantor.2@osu.edu>  - 2.1-1
 - Change shib.conf handling to treat as config file.
 
index b7a6956..4c86dae 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -61,7 +61,7 @@ const char* shar_schemadir = NULL;
 const char* shar_prefix = NULL;\r
 bool shar_checkonly = false;\r
 bool shar_version = false;\r
-static int unlink_socket = 0;\r
+static bool unlink_socket = false;\r
 const char* pidfile = NULL;\r
 \r
 #ifdef WIN32\r
@@ -141,14 +141,21 @@ int real_main(int preinit)
 \r
         //_CrtSetAllocHook(MyAllocHook);\r
 \r
-        // Run the listener\r
         if (!shar_checkonly) {\r
-\r
             // Run the listener.\r
-            if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
-                fprintf(stderr, "listener failed to enter listen loop\n");\r
+            ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+            if (!listener->init(unlink_socket)) {\r
+                fprintf(stderr, "listener failed to initialize\n");\r
+                conf.term();\r
+                return -3;\r
+            }\r
+            else if (!listener->run(&shibd_shutdown)) {\r
+                fprintf(stderr, "listener failed during service\n");\r
+                listener->term();\r
+                conf.term();\r
                 return -3;\r
             }\r
+            listener->term();\r
         }\r
 \r
         conf.term();\r
@@ -158,11 +165,25 @@ int real_main(int preinit)
 \r
 #else\r
 \r
+int daemon_wait = 3;\r
+bool shibd_running = false;\r
+bool daemonize = true;\r
+\r
 static void term_handler(int arg)\r
 {\r
     shibd_shutdown = true;\r
 }\r
 \r
+static void run_handler(int arg)\r
+{\r
+    shibd_running = true;\r
+}\r
+\r
+static void child_handler(int arg)\r
+{\r
+    // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
+}\r
+\r
 static int setup_signals(void)\r
 {\r
     struct sigaction sa;\r
@@ -190,6 +211,23 @@ static int setup_signals(void)
     if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
         return -1;\r
     }\r
+\r
+    if (daemonize) {\r
+        memset(&sa, 0, sizeof (sa));\r
+        sa.sa_handler = run_handler;\r
+\r
+        if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
+            return -1;\r
+        }\r
+\r
+        memset(&sa, 0, sizeof (sa));\r
+        sa.sa_handler = child_handler;\r
+\r
+        if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
+            return -1;\r
+        }\r
+    }\r
+\r
     return 0;\r
 }\r
 \r
@@ -199,9 +237,11 @@ static void usage(char* whoami)
     fprintf(stderr, "  -d\tinstallation prefix to use.\n");\r
     fprintf(stderr, "  -c\tconfig file to use.\n");\r
     fprintf(stderr, "  -x\tXML schema catalogs to use.\n");\r
-    fprintf(stderr, "  -t\tcheck configuration file for problems.\n");\r
+    fprintf(stderr, "  -t\ttest configuration file for problems.\n");\r
     fprintf(stderr, "  -f\tforce removal of listener socket.\n");\r
+    fprintf(stderr, "  -F\tstay in the foreground.\n");\r
     fprintf(stderr, "  -p\tpid file to use.\n");\r
+    fprintf(stderr, "  -w\tseconds to wait for successful daemonization.\n");\r
     fprintf(stderr, "  -v\tprint software version.\n");\r
     fprintf(stderr, "  -h\tprint this help message.\n");\r
     exit(1);\r
@@ -211,7 +251,7 @@ static int parse_args(int argc, char* argv[])
 {\r
     int opt;\r
 \r
-    while ((opt = getopt(argc, argv, "d:c:x:p:ftvh")) > 0) {\r
+    while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {\r
         switch (opt) {\r
             case 'd':\r
                 shar_prefix=optarg;\r
@@ -223,10 +263,14 @@ static int parse_args(int argc, char* argv[])
                 shar_schemadir=optarg;\r
                 break;\r
             case 'f':\r
-                unlink_socket = 1;\r
+                unlink_socket = true;\r
+                break;\r
+            case 'F':\r
+                daemonize = false;\r
                 break;\r
             case 't':\r
                 shar_checkonly=true;\r
+                daemonize=false;\r
                 break;\r
             case 'v':\r
                 shar_version=true;\r
@@ -234,6 +278,12 @@ static int parse_args(int argc, char* argv[])
             case 'p':\r
                 pidfile=optarg;\r
                 break;\r
+            case 'w':\r
+                if (optarg)\r
+                    daemon_wait = atoi(optarg);\r
+                if (daemon_wait <= 0)\r
+                    daemon_wait = 3;\r
+                break;\r
             default:\r
                 return -1;\r
         }\r
@@ -271,6 +321,21 @@ int main(int argc, char *argv[])
         return -1;\r
     }\r
 \r
+    if (daemonize) {\r
+        // We must fork() early, while we're single threaded.\r
+        // StorageService cleanup thread is about to start.\r
+        switch (fork()) {\r
+            case 0:\r
+                break;\r
+            case -1:\r
+                perror("forking");\r
+                exit(EXIT_FAILURE);\r
+            default:\r
+                sleep(daemon_wait);\r
+                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
+        }\r
+    }\r
+\r
     if (!conf.instantiate(shar_config)) {\r
         fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
         conf.term();\r
@@ -280,23 +345,53 @@ int main(int argc, char *argv[])
     if (shar_checkonly)\r
         fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
     else {\r
+        // Init the listener.\r
+        ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+        if (!listener->init(unlink_socket)) {\r
+            fprintf(stderr, "listener failed to initialize\n");\r
+            conf.term();\r
+            return -3;\r
+        }\r
 \r
-        // Write the pid file\r
-        if (pidfile) {\r
-            FILE* pidf = fopen(pidfile, "w");\r
-            if (pidf) {\r
-                fprintf(pidf, "%d\n", getpid());\r
-                fclose(pidf);\r
-            } else {\r
-                perror(pidfile);  // keep running though\r
+        if (daemonize) {\r
+            if (setsid() == -1) {\r
+                perror("setsid");\r
+                exit(EXIT_FAILURE);\r
             }\r
+            if (chdir("/") == -1) {\r
+                perror("chdir to root");\r
+                exit(EXIT_FAILURE);\r
+            }\r
+\r
+            if (pidfile) {\r
+                FILE* pidf = fopen(pidfile, "w");\r
+                if (pidf) {\r
+                    fprintf(pidf, "%d\n", getpid());\r
+                    fclose(pidf);\r
+                }\r
+                else {\r
+                    perror(pidfile);\r
+                }\r
+            }\r
+\r
+            freopen("/dev/null", "r", stdin);\r
+            freopen("/dev/null", "w", stdout);\r
+            freopen("/dev/null", "w", stderr);\r
+\r
+            // Signal our parent that we are A-OK.\r
+            kill(getppid(), SIGUSR1);\r
         }\r
 \r
-        // Run the listener\r
-        if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
-            fprintf(stderr, "listener failed to enter listen loop\n");\r
+        // Run the listener.\r
+        if (!listener->run(&shibd_shutdown)) {\r
+            fprintf(stderr, "listener failure during service\n");\r
+            listener->term();\r
+            conf.term();\r
+            if (pidfile)\r
+                unlink(pidfile);\r
             return -3;\r
         }\r
+        listener->term();\r
     }\r
 \r
     conf.term();\r
index 6f21f45..4f11667 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,1,0,0\r
- PRODUCTVERSION 2,1,0,0\r
+ FILEVERSION 2,2,1,0\r
+ PRODUCTVERSION 2,2,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth Daemon Service\0"\r
-            VALUE "FileVersion", "2, 1, 0, 0\0"\r
+            VALUE "FileVersion", "2, 2, 1, 0\0"\r
             VALUE "InternalName", "shibd\0"\r
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"\r
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibd.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.1\0"\r
-            VALUE "ProductVersion", "2, 1, 0, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
+            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index f86cfad..c921764 100644 (file)
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="shibd"
        ProjectGUID="{F13141B5-6C87-40BB-8D4E-5CC56EBB4C59}"
        RootNamespace="shibd"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="wsock32.lib log4shib1.lib xmltooling1.lib xerces-c_2.lib"
+                               AdditionalDependencies="wsock32.lib log4shib1.lib xmltooling1.lib"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
                                SubSystem="1"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="1"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-                       IntermediateDirectory="$(ConfigurationName)"
+                       Name="Release|x64"
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
                        ConfigurationType="1"
                        UseOfMFC="0"
                        ATLMinimizesCRunTimeLibraryUsage="false"
                        />
                        <Tool
                                Name="VCMIDLTool"
+                               TargetEnvironment="3"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="0"
+                               Optimization="2"
+                               InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"
-                               BasicRuntimeChecks="3"
-                               RuntimeLibrary="3"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+                               StringPooling="true"
+                               RuntimeLibrary="2"
+                               EnableFunctionLevelLinking="true"
                                RuntimeTypeInfo="true"
-                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
-                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="_DEBUG"
+                               PreprocessorDefinitions="NDEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="wsock32.lib log4shib1D.lib xmltooling1D.lib"
-                               LinkIncremental="2"
+                               AdditionalDependencies="wsock32.lib log4shib1.lib xmltooling1.lib"
+                               LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
-                               GenerateDebugInformation="true"
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
                                SubSystem="1"
-                               TargetMachine="1"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="17"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                <Configuration
-                       Name="Release|x64"
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
                        ConfigurationType="1"
                        UseOfMFC="0"
                        ATLMinimizesCRunTimeLibraryUsage="false"
                        />
                        <Tool
                                Name="VCMIDLTool"
-                               TargetEnvironment="3"
                                HeaderFileName=""
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="1"
+                               Optimization="0"
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-                               StringPooling="true"
-                               RuntimeLibrary="2"
-                               EnableFunctionLevelLinking="true"
+                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
                                RuntimeTypeInfo="true"
+                               BrowseInformation="1"
                                WarningLevel="3"
                                SuppressStartupBanner="true"
                                Detect64BitPortabilityProblems="true"
+                               DebugInformationFormat="4"
                                CompileAs="0"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCResourceCompilerTool"
-                               PreprocessorDefinitions="NDEBUG"
+                               PreprocessorDefinitions="_DEBUG"
                                Culture="1033"
                        />
                        <Tool
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="wsock32.lib log4shib1.lib xmltooling1.lib xerces-c_2.lib"
-                               LinkIncremental="1"
+                               AdditionalDependencies="wsock32.lib log4shib1D.lib xmltooling1D.lib"
+                               LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
+                               GenerateDebugInformation="true"
                                SubSystem="1"
-                               TargetMachine="17"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
+                               TargetMachine="1"
                        />
                        <Tool
                                Name="VCALinkTool"
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
                                GenerateDebugInformation="true"
                                SubSystem="1"
+                               RandomizedBaseAddress="1"
+                               DataExecutionPrevention="0"
                                TargetMachine="17"
                        />
                        <Tool
                                Name="VCAppVerifierTool"
                        />
                        <Tool
-                               Name="VCWebDeploymentTool"
-                       />
-                       <Tool
                                Name="VCPostBuildEventTool"
                        />
                </Configuration>
index ff5c98c..c18d826 100644 (file)
@@ -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.
@@ -52,14 +52,19 @@ AbstractSPRequest::~AbstractSPRequest()
 
 RequestMapper::Settings AbstractSPRequest::getRequestSettings() const
 {
-    if (m_mapper)
-        return m_settings;
-
-    // Map request to application and content settings.
-    m_mapper=m_sp->getRequestMapper();
-    m_mapper->lock();
-    return m_settings = m_mapper->getSettings(*this);
-
+    if (!m_mapper) {
+        // Map request to application and content settings.
+        m_mapper=m_sp->getRequestMapper();
+        m_mapper->lock();
+        m_settings = m_mapper->getSettings(*this);
+
+        if (reinterpret_cast<Category*>(m_log)->isDebugEnabled()) {
+            reinterpret_cast<Category*>(m_log)->debug(
+                "mapped %s to %s", getRequestURL(), m_settings.first->getString("applicationId").second
+                );
+        }
+    }
+    return m_settings;
 }
 
 const Application& AbstractSPRequest::getApplication() const
@@ -68,7 +73,7 @@ const Application& AbstractSPRequest::getApplication() const
         // Now find the application from the URL settings
         m_app=m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
         if (!m_app)
-            throw ConfigurationException("Unable to map request to application settings, check configuration.");
+            throw ConfigurationException("Unable to map request to ApplicationOverride settings, check configuration.");
     }
     return *m_app;
 }
@@ -127,17 +132,6 @@ void AbstractSPRequest::setRequestURI(const char* uri)
                 m_uri += uri;
                 break;
             }
-            else if (*uri == ';') {
-                // If this is Java being stupid, skip everything up to the query string, if any.
-                if (!strncmp(uri, ";jsessionid=", 12)) {
-                    if (uri = strchr(uri, '?'))
-                        m_uri += uri;
-                    break;
-                }
-                else {
-                    m_uri += *uri;
-                }
-            }
             else if (*uri != '%') {
                 m_uri += *uri;
             }
@@ -170,6 +164,12 @@ const char* AbstractSPRequest::getRequestURL() const
     return m_url.c_str();
 }
 
+string AbstractSPRequest::getRemoteAddr() const
+{
+    pair<bool,const char*> addr = getRequestSettings().first->getString("REMOTE_ADDR");
+    return addr.first ? getHeader(addr.second) : "";
+}
+
 const char* AbstractSPRequest::getParameter(const char* name) const
 {
     if (!m_parser)
@@ -209,7 +209,7 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
 
     bool ssl_only=true;
     const char* handler=NULL;
-    const PropertySet* props=m_app->getPropertySet("Sessions");
+    const PropertySet* props=getApplication().getPropertySet("Sessions");
     if (props) {
         pair<bool,bool> p=props->getBool("handlerSSL");
         if (p.first)
@@ -222,7 +222,7 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
     // Should never happen...
     if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
         throw ConfigurationException(
-            "Invalid handlerURL property ($1) in Application ($2)",
+            "Invalid handlerURL property ($1) in <Sessions> element for Application ($2)",
             params(2, handler ? handler : "null", m_app->getId())
             );
 
index 6faf9ee..1253256 100644 (file)
@@ -74,6 +74,8 @@ namespace shibsp {
 
         const char* getRequestURL() const;
         
+        std::string getRemoteAddr() const;
+        
         const char* getParameter(const char* name) const;
 
         std::vector<const char*>::size_type getParameters(const char* name, std::vector<const char*>& values) const;
index 77774b6..59178aa 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/AccessControl.h
- * 
+ *
  * Interface to an access control plugin
  */
 
@@ -33,7 +33,7 @@ namespace shibsp {
 
      /**
      * Interface to an access control plugin
-     * 
+     *
      * Access control plugins return authorization decisions based on the intersection
      * of the resource request and the active session. They can be implemented through
      * cross-platform or platform-specific mechanisms.
@@ -54,10 +54,10 @@ namespace shibsp {
             shib_acl_false,
             shib_acl_indeterminate
         };
-        
+
         /**
          * Perform an authorization check.
-         * 
+         *
          * @param request   SP request information
          * @param session   active user session, if any
          * @return true iff access should be granted
@@ -70,11 +70,14 @@ namespace shibsp {
      */
     void SHIBSP_API registerAccessControls();
 
+    /** Chains together multiple plugins. */
+    #define CHAINING_ACCESS_CONTROL "Chaining"
+
     /** AccessControl based on rudimentary XML syntax. */
-    #define XML_ACCESS_CONTROL  "XML"
+    #define XML_ACCESS_CONTROL      "XML"
 
     /** Reserved for Apache-style .htaccess support. */
-    #define HT_ACCESS_CONTROL   "htaccess"
+    #define HT_ACCESS_CONTROL       "htaccess"
 };
 
 #endif /* __shibsp_acl_h__ */
index 8e41cab..6ee7919 100644 (file)
@@ -68,6 +68,21 @@ pair<string,const char*> Application::getCookieNameProps(const char* prefix, tim
     return pair<string,const char*>(prefix,defProps);
 }
 
+void Application::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
+{
+    request.clearHeader(rawname, cginame);
+}
+
+void Application::setHeader(SPRequest& request, const char* name, const char* value) const
+{
+    request.setHeader(name, value);
+}
+
+string Application::getSecureHeader(const SPRequest& request, const char* name) const
+{
+    return request.getSecureHeader(name);
+}
+
 void Application::clearAttributeHeaders(SPRequest& request) const
 {
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
index c7352a2..cfd38e7 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/Application.h
- * 
+ *
  * Interface to a Shibboleth Application instance.
  */
 
@@ -36,7 +36,7 @@
 #include <xmltooling/util/Threads.h>
 
 namespace shibsp {
-    
+
 #ifndef SHIBSP_LITE
     class SHIBSP_API AttributeExtractor;
     class SHIBSP_API AttributeFilter;
@@ -55,7 +55,7 @@ namespace shibsp {
 
     /**
      * Interface to a Shibboleth Application instance.
-     * 
+     *
      * <p>An Application is a logical set of resources that act as a unit
      * of session management and policy.
      */
@@ -72,7 +72,7 @@ namespace shibsp {
          * @param sp    parent ServiceProvider instance
          */
         Application(const ServiceProvider* sp);
-        
+
         /** Pointer to parent SP instance. */
         const ServiceProvider* m_sp;
 
@@ -96,23 +96,23 @@ namespace shibsp {
 
         /**
          * Returns the Application's ID.
-         * 
+         *
          * @return  the ID
-         */        
+         */
         virtual const char* getId() const {
             return getString("id").second;
         }
 
         /**
          * Returns a unique hash for the Application.
-         * 
+         *
          * @return a value resulting from a computation over the Application's configuration
          */
         virtual const char* getHash() const=0;
 
         /**
          * Returns the name and cookie properties to use for this Application.
-         * 
+         *
          * @param prefix    a value to prepend to the base cookie name
          * @param lifetime  if non-null, will be populated with a suggested lifetime for the cookie, or 0 if session-bound
          * @return  a pair containing the cookie name and the string to append to the cookie value
@@ -122,15 +122,15 @@ namespace shibsp {
 #ifndef SHIBSP_LITE
         /**
          * Returns a MetadataProvider for use with this Application.
-         * 
+         *
          * @param required  true iff an exception should be thrown if no MetadataProvider is available
          * @return  a MetadataProvider instance, or NULL
          */
         virtual opensaml::saml2md::MetadataProvider* getMetadataProvider(bool required=true) const=0;
-        
+
         /**
          * Returns a TrustEngine for use with this Application.
-         * 
+         *
          * @param required  true iff an exception should be thrown if no TrustEngine is available
          * @return  a TrustEngine instance, or NULL
          */
@@ -138,35 +138,35 @@ namespace shibsp {
 
         /**
          * Returns an AttributeExtractor for use with this Application.
-         * 
+         *
          * @return  an AttributeExtractor, or NULL
          */
         virtual AttributeExtractor* getAttributeExtractor() const=0;
 
         /**
          * Returns an AttributeFilter for use with this Application.
-         * 
+         *
          * @return  an AttributeFilter, or NULL
          */
         virtual AttributeFilter* getAttributeFilter() const=0;
 
         /**
          * Returns an AttributeResolver for use with this Application.
-         * 
+         *
          * @return  an AttributeResolver, or NULL
          */
         virtual AttributeResolver* getAttributeResolver() const=0;
 
         /**
          * Returns the CredentialResolver instance associated with this Application.
-         * 
+         *
          * @return  a CredentialResolver, or NULL
          */
         virtual xmltooling::CredentialResolver* getCredentialResolver() const=0;
 
         /**
          * Returns configuration properties governing security interactions with a peer.
-         * 
+         *
          * @param provider  a peer entity's metadata
          * @return  the applicable PropertySet
          */
@@ -174,15 +174,16 @@ namespace shibsp {
 
         /**
          * Returns configuration properties governing security interactions with a named peer.
-         * 
+         *
          * @param entityID  a peer name
          * @return  the applicable PropertySet
          */
         virtual const PropertySet* getRelyingParty(const XMLCh* entityID) const=0;
 
         /**
+         * @deprecated
          * Returns any additional audience values associated with this Application.
-         * 
+         *
          * @return additional audience values associated with the Application, or NULL
          */
         virtual const std::vector<const XMLCh*>* getAudiences() const=0;
@@ -206,6 +207,33 @@ namespace shibsp {
         virtual const std::vector<std::string>& getRemoteUserAttributeIds() const=0;
 
         /**
+         * Ensures no value exists for a request header, allowing for application-specific customization.
+         *
+         * @param request  SP request to modify
+         * @param rawname  raw name of header to clear
+         * @param cginame  CGI-equivalent name of header, <strong>MUST</strong> begin with "HTTP_".
+         */
+        virtual void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;
+
+        /**
+         * Sets a value for a request header allowing for application-specific customization.
+         *
+         * @param request   SP request to modify
+         * @param name      name of header to set
+         * @param value     value to set
+         */
+        virtual void setHeader(SPRequest& request, const char* name, const char* value) const;
+
+        /**
+         * Returns a non-spoofable request header value allowing for application-specific customization.
+         *
+         * @param request   SP request to access
+         * @param name      the name of the secure header to return
+         * @return  the header's value, or an empty string
+         */
+        virtual std::string getSecureHeader(const SPRequest& request, const char* name) const;
+
+        /**
          * Clears any headers that may be used to hold attributes after export.
          *
          * @param request   SP request to clear
@@ -214,14 +242,14 @@ namespace shibsp {
 
         /**
          * Returns the default SessionInitiator when automatically requesting a session.
-         * 
+         *
          * @return the default SessionInitiator, or NULL
          */
         virtual const SessionInitiator* getDefaultSessionInitiator() const=0;
-        
+
         /**
          * Returns a SessionInitiator with a particular ID when automatically requesting a session.
-         * 
+         *
          * @param id    an identifier unique to the Application
          * @return the designated SessionInitiator, or NULL
          */
@@ -230,7 +258,7 @@ namespace shibsp {
         /**
          * Returns the default AssertionConsumerService Handler
          * for use in AuthnRequest messages.
-         * 
+         *
          * @return the default AssertionConsumerService, or NULL
          */
         virtual const Handler* getDefaultAssertionConsumerService() const=0;
@@ -238,7 +266,7 @@ namespace shibsp {
         /**
          * Returns an AssertionConsumerService Handler with a particular index
          * for use in AuthnRequest messages.
-         * 
+         *
          * @param index an index unique to an application
          * @return the designated AssertionConsumerService, or NULL
          */
@@ -247,18 +275,18 @@ namespace shibsp {
         /**
          * Returns one or more AssertionConsumerService Handlers that support
          * a particular protocol binding.
-         * 
+         *
          * @param binding   a protocol binding identifier
          * @return a set of qualifying AssertionConsumerServices
          */
         virtual const std::vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const=0;
-        
+
         /**
          * Returns the Handler associated with a particular path/location.
-         * 
+         *
          * @param path  the PATH_INFO appended to the end of a base Handler location
          *              that invokes the Handler
-         * @return the mapped Handler, or NULL 
+         * @return the mapped Handler, or NULL
          */
         virtual const Handler* getHandler(const char* path) const=0;
 
index 703da9d..811d4ed 100644 (file)
@@ -1,8 +1,5 @@
 AUTOMAKE_OPTIONS = foreign
 
-pkgsysconfdir = $(sysconfdir)/@PACKAGE@
-pkgxmldir = $(datadir)/xml/@PACKAGE@
-
 lib_LTLIBRARIES = libshibsp.la libshibsp-lite.la
 
 libshibspincludedir = $(includedir)/shibsp
@@ -46,9 +43,11 @@ libshibspinclude_HEADERS = \
 attrinclude_HEADERS = \
        attribute/Attribute.h \
        attribute/AttributeDecoder.h \
+       attribute/ExtensibleAttribute.h \
        attribute/NameIDAttribute.h \
        attribute/ScopedAttribute.h \
-       attribute/SimpleAttribute.h
+       attribute/SimpleAttribute.h \
+       attribute/XMLAttribute.h
 
 attrfiltinclude_HEADERS = \
        attribute/filtering/AttributeFilter.h \
@@ -107,6 +106,7 @@ common_sources = \
        ServiceProvider.cpp \
        SPConfig.cpp \
        attribute/Attribute.cpp \
+       attribute/ExtensibleAttribute.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
        handler/impl/AssertionLookup.cpp \
@@ -132,6 +132,7 @@ common_sources = \
        handler/impl/Shib1SessionInitiator.cpp \
        handler/impl/TransformSessionInitiator.cpp \
        handler/impl/WAYFSessionInitiator.cpp \
+       impl/ChainingAccessControl.cpp \
     impl/StorageServiceSessionCache.cpp \
        impl/XMLAccessControl.cpp \
        impl/XMLRequestMapper.cpp \
@@ -153,10 +154,13 @@ libshibsp_lite_la_SOURCES = \
 
 libshibsp_la_SOURCES = \
        ${common_sources} \
+       attribute/DOMAttributeDecoder.cpp \
+       attribute/KeyInfoAttributeDecoder.cpp \
        attribute/NameIDAttributeDecoder.cpp \
        attribute/NameIDFromScopedAttributeDecoder.cpp \
        attribute/ScopedAttributeDecoder.cpp \
        attribute/StringAttributeDecoder.cpp \
+       attribute/XMLAttributeDecoder.cpp \
        attribute/filtering/impl/AttributeFilter.cpp \
        attribute/filtering/impl/ChainingAttributeFilter.cpp \
        attribute/filtering/impl/XMLAttributeFilter.cpp \
@@ -181,7 +185,10 @@ libshibsp_la_SOURCES = \
        attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp \
        attribute/resolver/impl/ChainingAttributeResolver.cpp \
        attribute/resolver/impl/QueryAttributeResolver.cpp \
+       attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp \
        attribute/resolver/impl/ChainingAttributeExtractor.cpp \
+       attribute/resolver/impl/DelegationAttributeExtractor.cpp \
+       attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp \
        attribute/resolver/impl/XMLAttributeExtractor.cpp \
        binding/impl/ArtifactResolver.cpp \
        binding/impl/SOAPClient.cpp \
@@ -193,14 +200,25 @@ libshibsp_la_SOURCES = \
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 2:0:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 2:0:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
 libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
 
+pkgsysconfdir = $(sysconfdir)/@PACKAGE@
+pkgxmldir = $(datadir)/xml/@PACKAGE@
+logdir = ${localstatedir}/log
+rundir = $(localstatedir)/run
+xmldir = $(datadir)/xml
+
 paths.h: ${srcdir}/paths.h.in Makefile ${top_builddir}/config.status
        rm -f $@.tmp
        sed < ${srcdir}/$@.in > $@.tmp \
            -e 's:@-PREFIX-@:${prefix}:g' \
+        -e 's:@-LIBDIR-@:${libdir}:g' \
+        -e 's:@-SYSCONFDIR-@:${sysconfdir}:g' \
+        -e 's:@-LOGDIR-@:${logdir}:g' \
+        -e 's:@-RUNDIR-@:${rundir}:g' \
+        -e 's:@-XMLDIR-@:${xmldir}:g' \
            -e 's:@-PKGSYSCONFDIR-@:${pkgsysconfdir}:g' \
            -e 's:@-PKGXMLDIR-@:${pkgxmldir}:g' \
            -e 's:@-XMLTOOLINGXMLDIR-@:${XMLTOOLINGXMLDIR}:g' \
index 7a04a6c..43015a5 100644 (file)
@@ -75,6 +75,7 @@ am__objects_1 = libshibsp_lite_la-AbstractSPRequest.lo \
        libshibsp_lite_la-Application.lo \
        libshibsp_lite_la-ServiceProvider.lo \
        libshibsp_lite_la-SPConfig.lo libshibsp_lite_la-Attribute.lo \
+       libshibsp_lite_la-ExtensibleAttribute.lo \
        libshibsp_lite_la-AbstractHandler.lo \
        libshibsp_lite_la-AssertionConsumerService.lo \
        libshibsp_lite_la-AssertionLookup.lo \
@@ -100,6 +101,7 @@ am__objects_1 = libshibsp_lite_la-AbstractSPRequest.lo \
        libshibsp_lite_la-Shib1SessionInitiator.lo \
        libshibsp_lite_la-TransformSessionInitiator.lo \
        libshibsp_lite_la-WAYFSessionInitiator.lo \
+       libshibsp_lite_la-ChainingAccessControl.lo \
        libshibsp_lite_la-StorageServiceSessionCache.lo \
        libshibsp_lite_la-XMLAccessControl.lo \
        libshibsp_lite_la-XMLRequestMapper.lo \
@@ -118,28 +120,30 @@ am_libshibsp_lite_la_OBJECTS = $(am__objects_1) \
 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 AbstractHandler.lo \
-       AssertionConsumerService.lo AssertionLookup.lo \
-       ChainingLogoutInitiator.lo ChainingSessionInitiator.lo \
-       CookieSessionInitiator.lo FormSessionInitiator.lo \
-       LocalLogoutInitiator.lo LogoutHandler.lo MetadataGenerator.lo \
-       RemotedHandler.lo StatusHandler.lo SessionHandler.lo \
-       SAML1Consumer.lo SAML2Consumer.lo SAML2ArtifactResolution.lo \
-       SAML2Logout.lo SAML2LogoutInitiator.lo SAML2NameIDMgmt.lo \
+       SPConfig.lo Attribute.lo ExtensibleAttribute.lo \
+       AbstractHandler.lo AssertionConsumerService.lo \
+       AssertionLookup.lo ChainingLogoutInitiator.lo \
+       ChainingSessionInitiator.lo CookieSessionInitiator.lo \
+       FormSessionInitiator.lo LocalLogoutInitiator.lo \
+       LogoutHandler.lo MetadataGenerator.lo RemotedHandler.lo \
+       StatusHandler.lo SessionHandler.lo SAML1Consumer.lo \
+       SAML2Consumer.lo SAML2ArtifactResolution.lo SAML2Logout.lo \
+       SAML2LogoutInitiator.lo SAML2NameIDMgmt.lo \
        SAML2SessionInitiator.lo SAMLDSSessionInitiator.lo \
        SessionInitiator.lo Shib1SessionInitiator.lo \
        TransformSessionInitiator.lo WAYFSessionInitiator.lo \
-       StorageServiceSessionCache.lo XMLAccessControl.lo \
-       XMLRequestMapper.lo XMLServiceProvider.lo ddf.lo \
-       ListenerService.lo SocketListener.lo TCPListener.lo \
+       ChainingAccessControl.lo StorageServiceSessionCache.lo \
+       XMLAccessControl.lo XMLRequestMapper.lo XMLServiceProvider.lo \
+       ddf.lo ListenerService.lo SocketListener.lo TCPListener.lo \
        UnixListener.lo CGIParser.lo DOMPropertySet.lo SPConstants.lo \
        TemplateParameters.lo
-am_libshibsp_la_OBJECTS = $(am__objects_2) NameIDAttributeDecoder.lo \
+am_libshibsp_la_OBJECTS = $(am__objects_2) DOMAttributeDecoder.lo \
+       KeyInfoAttributeDecoder.lo NameIDAttributeDecoder.lo \
        NameIDFromScopedAttributeDecoder.lo ScopedAttributeDecoder.lo \
-       StringAttributeDecoder.lo AttributeFilter.lo \
-       ChainingAttributeFilter.lo XMLAttributeFilter.lo \
-       MatchFunctor.lo AndMatchFunctor.lo AnyMatchFunctor.lo \
-       NotMatchFunctor.lo OrMatchFunctor.lo \
+       StringAttributeDecoder.lo XMLAttributeDecoder.lo \
+       AttributeFilter.lo ChainingAttributeFilter.lo \
+       XMLAttributeFilter.lo MatchFunctor.lo AndMatchFunctor.lo \
+       AnyMatchFunctor.lo NotMatchFunctor.lo OrMatchFunctor.lo \
        AttributeIssuerStringFunctor.lo \
        AttributeRequesterStringFunctor.lo \
        AttributeScopeStringFunctor.lo AttributeValueStringFunctor.lo \
@@ -153,7 +157,9 @@ am_libshibsp_la_OBJECTS = $(am__objects_2) NameIDAttributeDecoder.lo \
        AttributeRequesterInEntityGroupFunctor.lo \
        AttributeScopeMatchesShibMDScopeFunctor.lo \
        ChainingAttributeResolver.lo QueryAttributeResolver.lo \
-       ChainingAttributeExtractor.lo XMLAttributeExtractor.lo \
+       SimpleAggregationAttributeResolver.lo \
+       ChainingAttributeExtractor.lo DelegationAttributeExtractor.lo \
+       KeyDescriptorAttributeExtractor.lo XMLAttributeExtractor.lo \
        ArtifactResolver.lo SOAPClient.lo DynamicMetadataProvider.lo \
        MetadataExtImpl.lo MetadataExtSchemaValidators.lo \
        PKIXTrustEngine.lo SecurityPolicy.lo
@@ -389,8 +395,6 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 xs = @xs@
 AUTOMAKE_OPTIONS = foreign
-pkgsysconfdir = $(sysconfdir)/@PACKAGE@
-pkgxmldir = $(datadir)/xml/@PACKAGE@
 lib_LTLIBRARIES = libshibsp.la libshibsp-lite.la
 libshibspincludedir = $(includedir)/shibsp
 attrincludedir = $(includedir)/shibsp/attribute
@@ -422,9 +426,11 @@ libshibspinclude_HEADERS = \
 attrinclude_HEADERS = \
        attribute/Attribute.h \
        attribute/AttributeDecoder.h \
+       attribute/ExtensibleAttribute.h \
        attribute/NameIDAttribute.h \
        attribute/ScopedAttribute.h \
-       attribute/SimpleAttribute.h
+       attribute/SimpleAttribute.h \
+       attribute/XMLAttribute.h
 
 attrfiltinclude_HEADERS = \
        attribute/filtering/AttributeFilter.h \
@@ -483,6 +489,7 @@ common_sources = \
        ServiceProvider.cpp \
        SPConfig.cpp \
        attribute/Attribute.cpp \
+       attribute/ExtensibleAttribute.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
        handler/impl/AssertionLookup.cpp \
@@ -508,6 +515,7 @@ common_sources = \
        handler/impl/Shib1SessionInitiator.cpp \
        handler/impl/TransformSessionInitiator.cpp \
        handler/impl/WAYFSessionInitiator.cpp \
+       impl/ChainingAccessControl.cpp \
     impl/StorageServiceSessionCache.cpp \
        impl/XMLAccessControl.cpp \
        impl/XMLRequestMapper.cpp \
@@ -529,10 +537,13 @@ libshibsp_lite_la_SOURCES = \
 
 libshibsp_la_SOURCES = \
        ${common_sources} \
+       attribute/DOMAttributeDecoder.cpp \
+       attribute/KeyInfoAttributeDecoder.cpp \
        attribute/NameIDAttributeDecoder.cpp \
        attribute/NameIDFromScopedAttributeDecoder.cpp \
        attribute/ScopedAttributeDecoder.cpp \
        attribute/StringAttributeDecoder.cpp \
+       attribute/XMLAttributeDecoder.cpp \
        attribute/filtering/impl/AttributeFilter.cpp \
        attribute/filtering/impl/ChainingAttributeFilter.cpp \
        attribute/filtering/impl/XMLAttributeFilter.cpp \
@@ -557,7 +568,10 @@ libshibsp_la_SOURCES = \
        attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp \
        attribute/resolver/impl/ChainingAttributeResolver.cpp \
        attribute/resolver/impl/QueryAttributeResolver.cpp \
+       attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp \
        attribute/resolver/impl/ChainingAttributeExtractor.cpp \
+       attribute/resolver/impl/DelegationAttributeExtractor.cpp \
+       attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp \
        attribute/resolver/impl/XMLAttributeExtractor.cpp \
        binding/impl/ArtifactResolver.cpp \
        binding/impl/SOAPClient.cpp \
@@ -570,9 +584,14 @@ libshibsp_la_SOURCES = \
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 2:0:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 2:0:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
 libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
+pkgsysconfdir = $(sysconfdir)/@PACKAGE@
+pkgxmldir = $(datadir)/xml/@PACKAGE@
+logdir = ${localstatedir}/log
+rundir = $(localstatedir)/run
+xmldir = $(datadir)/xml
 EXTRA_DIST = shibsp.vcproj shibsp-lite.vcproj paths.h.in resource.h shibsp.rc
 BUILT_SOURCES = paths.h
 all: $(BUILT_SOURCES)
@@ -671,15 +690,21 @@ distclean-compile:
 @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)/CGIParser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAccessControl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAttributeExtractor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAttributeFilter.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAttributeResolver.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingLogoutInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieSessionInitiator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DOMAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DOMPropertySet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DelegationAttributeExtractor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DynamicMetadataProvider.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExtensibleAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FormSessionInitiator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/KeyDescriptorAttributeExtractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/KeyInfoAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ListenerService.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LocalLogoutInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogoutHandler.Plo@am__quote@
@@ -712,6 +737,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Shib1SessionInitiator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleAggregationAttributeResolver.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/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@
@@ -722,6 +748,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)/XMLAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeExtractor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeFilter.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLRequestMapper.Plo@am__quote@
@@ -734,11 +761,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-AssertionLookup.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-Attribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-CGIParser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ChainingLogoutInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ChainingSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-CommonDomainCookie.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-CookieSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-DOMPropertySet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-FormSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ListenerService.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-LocalLogoutInitiator.Plo@am__quote@
@@ -829,6 +858,13 @@ libshibsp_lite_la-Attribute.lo: attribute/Attribute.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-Attribute.lo `test -f 'attribute/Attribute.cpp' || echo '$(srcdir)/'`attribute/Attribute.cpp
 
+libshibsp_lite_la-ExtensibleAttribute.lo: attribute/ExtensibleAttribute.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-ExtensibleAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Tpo" -c -o libshibsp_lite_la-ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/ExtensibleAttribute.cpp' object='libshibsp_lite_la-ExtensibleAttribute.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-ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.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
@@ -1004,6 +1040,13 @@ libshibsp_lite_la-WAYFSessionInitiator.lo: handler/impl/WAYFSessionInitiator.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-WAYFSessionInitiator.lo `test -f 'handler/impl/WAYFSessionInitiator.cpp' || echo '$(srcdir)/'`handler/impl/WAYFSessionInitiator.cpp
 
+libshibsp_lite_la-ChainingAccessControl.lo: impl/ChainingAccessControl.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-ChainingAccessControl.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Tpo" -c -o libshibsp_lite_la-ChainingAccessControl.lo `test -f 'impl/ChainingAccessControl.cpp' || echo '$(srcdir)/'`impl/ChainingAccessControl.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Tpo" "$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='impl/ChainingAccessControl.cpp' object='libshibsp_lite_la-ChainingAccessControl.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-ChainingAccessControl.lo `test -f 'impl/ChainingAccessControl.cpp' || echo '$(srcdir)/'`impl/ChainingAccessControl.cpp
+
 libshibsp_lite_la-StorageServiceSessionCache.lo: impl/StorageServiceSessionCache.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-StorageServiceSessionCache.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Tpo" -c -o libshibsp_lite_la-StorageServiceSessionCache.lo `test -f 'impl/StorageServiceSessionCache.cpp' || echo '$(srcdir)/'`impl/StorageServiceSessionCache.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Tpo" "$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Tpo"; exit 1; fi
@@ -1116,6 +1159,13 @@ Attribute.lo: attribute/Attribute.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 Attribute.lo `test -f 'attribute/Attribute.cpp' || echo '$(srcdir)/'`attribute/Attribute.cpp
 
+ExtensibleAttribute.lo: attribute/ExtensibleAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ExtensibleAttribute.lo -MD -MP -MF "$(DEPDIR)/ExtensibleAttribute.Tpo" -c -o ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/ExtensibleAttribute.Tpo" "$(DEPDIR)/ExtensibleAttribute.Plo"; else rm -f "$(DEPDIR)/ExtensibleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/ExtensibleAttribute.cpp' object='ExtensibleAttribute.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 ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.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
@@ -1291,6 +1341,13 @@ WAYFSessionInitiator.lo: handler/impl/WAYFSessionInitiator.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 WAYFSessionInitiator.lo `test -f 'handler/impl/WAYFSessionInitiator.cpp' || echo '$(srcdir)/'`handler/impl/WAYFSessionInitiator.cpp
 
+ChainingAccessControl.lo: impl/ChainingAccessControl.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ChainingAccessControl.lo -MD -MP -MF "$(DEPDIR)/ChainingAccessControl.Tpo" -c -o ChainingAccessControl.lo `test -f 'impl/ChainingAccessControl.cpp' || echo '$(srcdir)/'`impl/ChainingAccessControl.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/ChainingAccessControl.Tpo" "$(DEPDIR)/ChainingAccessControl.Plo"; else rm -f "$(DEPDIR)/ChainingAccessControl.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='impl/ChainingAccessControl.cpp' object='ChainingAccessControl.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 ChainingAccessControl.lo `test -f 'impl/ChainingAccessControl.cpp' || echo '$(srcdir)/'`impl/ChainingAccessControl.cpp
+
 StorageServiceSessionCache.lo: impl/StorageServiceSessionCache.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT StorageServiceSessionCache.lo -MD -MP -MF "$(DEPDIR)/StorageServiceSessionCache.Tpo" -c -o StorageServiceSessionCache.lo `test -f 'impl/StorageServiceSessionCache.cpp' || echo '$(srcdir)/'`impl/StorageServiceSessionCache.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/StorageServiceSessionCache.Tpo" "$(DEPDIR)/StorageServiceSessionCache.Plo"; else rm -f "$(DEPDIR)/StorageServiceSessionCache.Tpo"; exit 1; fi
@@ -1382,6 +1439,20 @@ TemplateParameters.lo: util/TemplateParameters.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 TemplateParameters.lo `test -f 'util/TemplateParameters.cpp' || echo '$(srcdir)/'`util/TemplateParameters.cpp
 
+DOMAttributeDecoder.lo: attribute/DOMAttributeDecoder.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT DOMAttributeDecoder.lo -MD -MP -MF "$(DEPDIR)/DOMAttributeDecoder.Tpo" -c -o DOMAttributeDecoder.lo `test -f 'attribute/DOMAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/DOMAttributeDecoder.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/DOMAttributeDecoder.Tpo" "$(DEPDIR)/DOMAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/DOMAttributeDecoder.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/DOMAttributeDecoder.cpp' object='DOMAttributeDecoder.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 DOMAttributeDecoder.lo `test -f 'attribute/DOMAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/DOMAttributeDecoder.cpp
+
+KeyInfoAttributeDecoder.lo: attribute/KeyInfoAttributeDecoder.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT KeyInfoAttributeDecoder.lo -MD -MP -MF "$(DEPDIR)/KeyInfoAttributeDecoder.Tpo" -c -o KeyInfoAttributeDecoder.lo `test -f 'attribute/KeyInfoAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/KeyInfoAttributeDecoder.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/KeyInfoAttributeDecoder.Tpo" "$(DEPDIR)/KeyInfoAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/KeyInfoAttributeDecoder.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/KeyInfoAttributeDecoder.cpp' object='KeyInfoAttributeDecoder.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 KeyInfoAttributeDecoder.lo `test -f 'attribute/KeyInfoAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/KeyInfoAttributeDecoder.cpp
+
 NameIDAttributeDecoder.lo: attribute/NameIDAttributeDecoder.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT NameIDAttributeDecoder.lo -MD -MP -MF "$(DEPDIR)/NameIDAttributeDecoder.Tpo" -c -o NameIDAttributeDecoder.lo `test -f 'attribute/NameIDAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/NameIDAttributeDecoder.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/NameIDAttributeDecoder.Tpo" "$(DEPDIR)/NameIDAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/NameIDAttributeDecoder.Tpo"; exit 1; fi
@@ -1410,6 +1481,13 @@ StringAttributeDecoder.lo: attribute/StringAttributeDecoder.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 StringAttributeDecoder.lo `test -f 'attribute/StringAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/StringAttributeDecoder.cpp
 
+XMLAttributeDecoder.lo: attribute/XMLAttributeDecoder.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT XMLAttributeDecoder.lo -MD -MP -MF "$(DEPDIR)/XMLAttributeDecoder.Tpo" -c -o XMLAttributeDecoder.lo `test -f 'attribute/XMLAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/XMLAttributeDecoder.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/XMLAttributeDecoder.Tpo" "$(DEPDIR)/XMLAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/XMLAttributeDecoder.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/XMLAttributeDecoder.cpp' object='XMLAttributeDecoder.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 XMLAttributeDecoder.lo `test -f 'attribute/XMLAttributeDecoder.cpp' || echo '$(srcdir)/'`attribute/XMLAttributeDecoder.cpp
+
 AttributeFilter.lo: attribute/filtering/impl/AttributeFilter.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT AttributeFilter.lo -MD -MP -MF "$(DEPDIR)/AttributeFilter.Tpo" -c -o AttributeFilter.lo `test -f 'attribute/filtering/impl/AttributeFilter.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/AttributeFilter.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/AttributeFilter.Tpo" "$(DEPDIR)/AttributeFilter.Plo"; else rm -f "$(DEPDIR)/AttributeFilter.Tpo"; exit 1; fi
@@ -1578,6 +1656,13 @@ QueryAttributeResolver.lo: attribute/resolver/impl/QueryAttributeResolver.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 QueryAttributeResolver.lo `test -f 'attribute/resolver/impl/QueryAttributeResolver.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/QueryAttributeResolver.cpp
 
+SimpleAggregationAttributeResolver.lo: attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SimpleAggregationAttributeResolver.lo -MD -MP -MF "$(DEPDIR)/SimpleAggregationAttributeResolver.Tpo" -c -o SimpleAggregationAttributeResolver.lo `test -f 'attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/SimpleAggregationAttributeResolver.Tpo" "$(DEPDIR)/SimpleAggregationAttributeResolver.Plo"; else rm -f "$(DEPDIR)/SimpleAggregationAttributeResolver.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp' object='SimpleAggregationAttributeResolver.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 SimpleAggregationAttributeResolver.lo `test -f 'attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
+
 ChainingAttributeExtractor.lo: attribute/resolver/impl/ChainingAttributeExtractor.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ChainingAttributeExtractor.lo -MD -MP -MF "$(DEPDIR)/ChainingAttributeExtractor.Tpo" -c -o ChainingAttributeExtractor.lo `test -f 'attribute/resolver/impl/ChainingAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/ChainingAttributeExtractor.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/ChainingAttributeExtractor.Tpo" "$(DEPDIR)/ChainingAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/ChainingAttributeExtractor.Tpo"; exit 1; fi
@@ -1585,6 +1670,20 @@ ChainingAttributeExtractor.lo: attribute/resolver/impl/ChainingAttributeExtracto
 @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 ChainingAttributeExtractor.lo `test -f 'attribute/resolver/impl/ChainingAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/ChainingAttributeExtractor.cpp
 
+DelegationAttributeExtractor.lo: attribute/resolver/impl/DelegationAttributeExtractor.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT DelegationAttributeExtractor.lo -MD -MP -MF "$(DEPDIR)/DelegationAttributeExtractor.Tpo" -c -o DelegationAttributeExtractor.lo `test -f 'attribute/resolver/impl/DelegationAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/DelegationAttributeExtractor.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/DelegationAttributeExtractor.Tpo" "$(DEPDIR)/DelegationAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/DelegationAttributeExtractor.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/resolver/impl/DelegationAttributeExtractor.cpp' object='DelegationAttributeExtractor.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 DelegationAttributeExtractor.lo `test -f 'attribute/resolver/impl/DelegationAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/DelegationAttributeExtractor.cpp
+
+KeyDescriptorAttributeExtractor.lo: attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT KeyDescriptorAttributeExtractor.lo -MD -MP -MF "$(DEPDIR)/KeyDescriptorAttributeExtractor.Tpo" -c -o KeyDescriptorAttributeExtractor.lo `test -f 'attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/KeyDescriptorAttributeExtractor.Tpo" "$(DEPDIR)/KeyDescriptorAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/KeyDescriptorAttributeExtractor.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp' object='KeyDescriptorAttributeExtractor.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 KeyDescriptorAttributeExtractor.lo `test -f 'attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
+
 XMLAttributeExtractor.lo: attribute/resolver/impl/XMLAttributeExtractor.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT XMLAttributeExtractor.lo -MD -MP -MF "$(DEPDIR)/XMLAttributeExtractor.Tpo" -c -o XMLAttributeExtractor.lo `test -f 'attribute/resolver/impl/XMLAttributeExtractor.cpp' || echo '$(srcdir)/'`attribute/resolver/impl/XMLAttributeExtractor.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/XMLAttributeExtractor.Tpo" "$(DEPDIR)/XMLAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/XMLAttributeExtractor.Tpo"; exit 1; fi
@@ -2042,6 +2141,11 @@ paths.h: ${srcdir}/paths.h.in Makefile ${top_builddir}/config.status
        rm -f $@.tmp
        sed < ${srcdir}/$@.in > $@.tmp \
            -e 's:@-PREFIX-@:${prefix}:g' \
+        -e 's:@-LIBDIR-@:${libdir}:g' \
+        -e 's:@-SYSCONFDIR-@:${sysconfdir}:g' \
+        -e 's:@-LOGDIR-@:${logdir}:g' \
+        -e 's:@-RUNDIR-@:${rundir}:g' \
+        -e 's:@-XMLDIR-@:${xmldir}:g' \
            -e 's:@-PKGSYSCONFDIR-@:${pkgsysconfdir}:g' \
            -e 's:@-PKGXMLDIR-@:${pkgxmldir}:g' \
            -e 's:@-XMLTOOLINGXMLDIR-@:${XMLTOOLINGXMLDIR}:g' \
index 7aaaf98..cbc9f8c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- *  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.
@@ -55,7 +55,6 @@
 # include "metadata/MetadataExt.h"
 # include "security/PKIXTrustEngine.h"
 # include <saml/SAMLConfig.h>
-# include <xmltooling/util/CurlNetAccessor.hpp>
 #else
 # include <xmltooling/XMLToolingConfig.h>
 #endif
@@ -124,6 +123,10 @@ bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
     std::string ll(loglevel);
     PathResolver localpr;
     localpr.setDefaultPrefix(inst_prefix2.c_str());
+    inst_prefix = getenv("SHIBSP_CFGDIR");
+    if (!inst_prefix)
+        inst_prefix = SHIBSP_CFGDIR;
+    localpr.setCfgDir(inst_prefix);
     XMLToolingConfig::getConfig().log_config(localpr.resolve(ll, PathResolver::XMLTOOLING_CFG_FILE, PACKAGE_NAME).c_str());
 
     Category& log=Category::getInstance(SHIBSP_LOGCAT".Config");
@@ -140,15 +143,33 @@ bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
         log.fatal("failed to initialize OpenSAML library");
         return false;
     }
-    XMLPlatformUtils::fgNetAccessor = new CurlNetAccessor();
 #else
     if (!XMLToolingConfig::getConfig().init()) {
         log.fatal("failed to initialize XMLTooling library");
         return false;
     }
 #endif
-    XMLToolingConfig::getConfig().getPathResolver()->setDefaultPackageName(PACKAGE_NAME);
-    XMLToolingConfig::getConfig().getPathResolver()->setDefaultPrefix(inst_prefix2.c_str());
+    PathResolver* pr = XMLToolingConfig::getConfig().getPathResolver();
+    pr->setDefaultPackageName(PACKAGE_NAME);
+    pr->setDefaultPrefix(inst_prefix2.c_str());
+    pr->setCfgDir(inst_prefix);
+    inst_prefix = getenv("SHIBSP_LIBDIR");
+    if (!inst_prefix)
+        inst_prefix = SHIBSP_LIBDIR;
+    pr->setLibDir(inst_prefix);
+    inst_prefix = getenv("SHIBSP_LOGDIR");
+    if (!inst_prefix)
+        inst_prefix = SHIBSP_LOGDIR;
+    pr->setLogDir(inst_prefix);
+    inst_prefix = getenv("SHIBSP_RUNDIR");
+    if (!inst_prefix)
+        inst_prefix = SHIBSP_RUNDIR;
+    pr->setRunDir(inst_prefix);
+    inst_prefix = getenv("SHIBSP_XMLDIR");
+    if (!inst_prefix)
+        inst_prefix = SHIBSP_XMLDIR;
+    pr->setXMLDir(inst_prefix);
+
     XMLToolingConfig::getConfig().setTemplateEngine(new TemplateEngine());
     XMLToolingConfig::getConfig().getTemplateEngine()->setTagPrefix("shibmlp");
 
@@ -220,6 +241,9 @@ void SPConfig::term()
     log.info("%s library shutting down", PACKAGE_STRING);
 
     setServiceProvider(NULL);
+    if (m_configDoc)
+        m_configDoc->release();
+    m_configDoc = NULL;
 #ifndef SHIBSP_LITE
     setArtifactResolver(NULL);
 #endif
@@ -289,6 +313,9 @@ bool SPConfig::instantiate(const char* config, bool rethrow)
             dummydoc = XMLToolingConfig::getConfig().getParser().parse(snippet);
             XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);
             setServiceProvider(ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER, dummydoc->getDocumentElement()));
+            if (m_configDoc)
+                m_configDoc->release();
+            m_configDoc = docjanitor.release();
         }
         else {
             stringstream snippet(config);
@@ -300,6 +327,9 @@ bool SPConfig::instantiate(const char* config, bool rethrow)
                 setServiceProvider(ServiceProviderManager.newPlugin(type.get(), dummydoc->getDocumentElement()));
             else
                 throw ConfigurationException("The supplied XML bootstrapping configuration did not include a type attribute.");
+            if (m_configDoc)
+                m_configDoc->release();
+            m_configDoc = docjanitor.release();
         }
 
         getServiceProvider()->init();
index d58c3a4..99f1a22 100644 (file)
@@ -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.
@@ -69,7 +69,8 @@ namespace shibsp {
 #ifndef SHIBSP_LITE
             m_artifactResolver(NULL),
 #endif
-            m_features(0) {}
+            m_features(0), m_configDoc(NULL) {
+        }
 
         virtual ~SPConfig() {}
 
@@ -185,7 +186,7 @@ namespace shibsp {
          *
          * @return  global ArtifactResolver or NULL
          */
-        opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const {
+        const opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const {
             return m_artifactResolver;
         }
 #endif
@@ -291,6 +292,7 @@ namespace shibsp {
 
     private:
         unsigned long m_features;
+        xercesc::DOMDocument* m_configDoc;
     };
 
 #if defined (_MSC_VER)
index cf2b7ed..255e8b5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,8 +16,8 @@
 
 /**
  * @file shibsp/SPRequest.h
- * 
- * Interface to server request being processed  
+ *
+ * Interface to server request being processed
  */
 
 #ifndef __shibsp_req_h__
 #include <xmltooling/io/HTTPResponse.h>
 
 namespace shibsp {
-    
+
     class SHIBSP_API Application;
     class SHIBSP_API ServiceProvider;
     class SHIBSP_API Session;
-    
+
     /**
      * Interface to server request being processed
-     * 
+     *
      * <p>To supply information from the surrounding web server environment,
      * a shim must be supplied in the form of this interface to adapt the
      * library to different proprietary server APIs.
-     * 
+     *
      * <p>This interface need not be threadsafe.
      */
     class SHIBSP_API SPRequest : public virtual xmltooling::HTTPRequest, public virtual xmltooling::HTTPResponse
@@ -48,10 +48,10 @@ namespace shibsp {
         SPRequest() {}
     public:
         virtual ~SPRequest() {}
-        
+
         /**
          * Returns the locked ServiceProvider processing the request.
-         * 
+         *
          * @return reference to ServiceProvider
          */
         virtual const ServiceProvider& getServiceProvider() const=0;
@@ -59,14 +59,14 @@ namespace shibsp {
         /**
          * Returns RequestMapper Settings associated with the request, guaranteed
          * to be valid for the request's duration.
-         * 
+         *
          * @return copy of settings
          */
         virtual RequestMapper::Settings getRequestSettings() const=0;
-        
+
         /**
          * Returns the Application governing the request.
-         * 
+         *
          * @return reference to Application
          */
         virtual const Application& getApplication() const=0;
@@ -84,7 +84,7 @@ namespace shibsp {
         /**
          * Returns the effective base Handler URL for a resource,
          * or the current request URL.
-         * 
+         *
          * @param resource  resource URL to compute handler for
          * @return  base location of handler
          */
@@ -94,7 +94,7 @@ namespace shibsp {
          * Returns a non-spoofable request header value, if possible.
          * Platforms that support environment export can redirect header
          * lookups by overriding this method.
-         * 
+         *
          * @param name  the name of the secure header to return
          * @return the header's value, or an empty string
          */
@@ -104,7 +104,7 @@ namespace shibsp {
 
         /**
          * Ensures no value exists for a request header.
-         * 
+         *
          * @param rawname  raw name of header to clear
          * @param cginame  CGI-equivalent name of header
          */
@@ -112,7 +112,7 @@ namespace shibsp {
 
         /**
          * Sets a value for a request header.
-         * 
+         *
          * @param name  name of header to set
          * @param value value to set
          */
@@ -120,11 +120,19 @@ namespace shibsp {
 
         /**
          * Establish REMOTE_USER identity in request.
-         * 
+         *
          * @param user  REMOTE_USER value to set or NULL to clear
          */
         virtual void setRemoteUser(const char* user)=0;
-        
+
+        /**
+         * Establish AUTH_TYPE for request.
+         *
+         * @param authtype  AUTH_TYPE value to set or NULL to clear
+         */
+        virtual void setAuthType(const char* authtype) {
+        }
+
         /** Portable logging levels. */
         enum SPLogLevel {
           SPDebug,
@@ -136,7 +144,7 @@ namespace shibsp {
 
         /**
          * Log to native server environment.
-         * 
+         *
          * @param level logging level
          * @param msg   message to log
          */
@@ -144,7 +152,7 @@ namespace shibsp {
 
         /**
          * Test logging level.
-         * 
+         *
          * @param level logging level
          * @return true iff logging level is enabled
          */
@@ -152,16 +160,16 @@ namespace shibsp {
 
         /**
          * Indicates that processing was declined, meaning no action is required during this phase of processing.
-         * 
+         *
          * @return  a status code to pass back to the server-specific layer
-         */        
+         */
         virtual long returnDecline()=0;
 
         /**
          * Indicates that processing was completed.
-         * 
+         *
          * @return  a status code to pass back to the server-specific layer
-         */        
+         */
         virtual long returnOK()=0;
     };
 };
index 91a8ab9..0006dbc 100644 (file)
@@ -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.
@@ -55,7 +55,12 @@ namespace shibsp {
         bool mderror = dynamic_cast<const opensaml::saml2md::MetadataException*>(tp.getRichException())!=NULL;
         pair<bool,const char*> redirectErrors = pair<bool,const char*>(false,NULL);
         pair<bool,const char*> pathname = pair<bool,const char*>(false,NULL);
-        const PropertySet* props=app ? app->getPropertySet("Errors") : NULL;
+
+        // Strictly for error handling, detect a NULL application and point at the default.
+        if (!app)
+            app = request.getServiceProvider().getApplication("default");
+
+        const PropertySet* props=app->getPropertySet("Errors");
 
         try {
             RequestMapper::Settings settings = request.getRequestSettings();
@@ -101,13 +106,13 @@ namespace shibsp {
                 tp.setPropertySet(props);
                 stringstream str;
                 XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException());
-                return request.sendResponse(str);
+                return request.sendError(str);
             }
         }
 
         if (!strcmp(page,"access")) {
             istringstream msg("Access Denied");
-            return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_UNAUTHORIZED);
+            return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN);
         }
 
         log.error("sendError could not process error template (%s)", page);
@@ -116,16 +121,16 @@ namespace shibsp {
     }
 
     void SHIBSP_DLLLOCAL clearHeaders(SPRequest& request) {
-        request.clearHeader("Shib-Session-ID", "HTTP_SHIB_SESSION_ID");
-        request.clearHeader("Shib-Identity-Provider", "HTTP_SHIB_IDENTITY_PROVIDER");
-        request.clearHeader("Shib-Authentication-Method", "HTTP_SHIB_AUTHENTICATION_METHOD");
-        request.clearHeader("Shib-Authentication-Instant", "HTTP_SHIB_AUTHENTICATION_INSTANT");
-        request.clearHeader("Shib-AuthnContext-Class", "HTTP_SHIB_AUTHNCONTEXT_CLASS");
-        request.clearHeader("Shib-AuthnContext-Decl", "HTTP_SHIB_AUTHNCONTEXT_DECL");
-        request.clearHeader("Shib-Assertion-Count", "HTTP_SHIB_ASSERTION_COUNT");
+        const Application& app = request.getApplication();
+        app.clearHeader(request, "Shib-Session-ID", "HTTP_SHIB_SESSION_ID");
+        app.clearHeader(request, "Shib-Identity-Provider", "HTTP_SHIB_IDENTITY_PROVIDER");
+        app.clearHeader(request, "Shib-Authentication-Method", "HTTP_SHIB_AUTHENTICATION_METHOD");
+        app.clearHeader(request, "Shib-Authentication-Instant", "HTTP_SHIB_AUTHENTICATION_INSTANT");
+        app.clearHeader(request, "Shib-AuthnContext-Class", "HTTP_SHIB_AUTHNCONTEXT_CLASS");
+        app.clearHeader(request, "Shib-AuthnContext-Decl", "HTTP_SHIB_AUTHNCONTEXT_DECL");
+        app.clearHeader(request, "Shib-Assertion-Count", "HTTP_SHIB_ASSERTION_COUNT");
+        app.clearAttributeHeaders(request);
         request.clearHeader("REMOTE_USER", "HTTP_REMOTE_USER");
-        //request.clearHeader("Shib-Application-ID");   handle inside app method
-        request.getApplication().clearAttributeHeaders(request);
     }
 };
 
@@ -240,12 +245,15 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
             return initiator->run(request,false);
         }
 
+        request.setAuthType("shibboleth");
+
         // We're done.  Everything is okay.  Nothing to report.  Nothing to do..
         // Let the caller decide how to proceed.
         log.debug("doAuthentication succeeded");
         return make_pair(false,0L);
     }
     catch (exception& e) {
+        request.log(SPRequest::SPError, e.what());
         TemplateParameters tp(&e);
         tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
         return make_pair(true,sendError(log, request, app, "session", tp));
@@ -316,6 +324,7 @@ pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
         }
     }
     catch (exception& e) {
+        request.log(SPRequest::SPError, e.what());
         TemplateParameters tp(&e);
         tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
         return make_pair(true,sendError(log, request, app, "access", tp));
@@ -355,24 +364,24 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                        return make_pair(false,0L);     // just bail silently
         }
 
-        request.setHeader("Shib-Application-ID", app->getId());
-        request.setHeader("Shib-Session-ID", session->getID());
+        app->setHeader(request, "Shib-Application-ID", app->getId());
+        app->setHeader(request, "Shib-Session-ID", session->getID());
 
         // Export the IdP name and Authn method/context info.
         const char* hval = session->getEntityID();
         if (hval)
-            request.setHeader("Shib-Identity-Provider", hval);
+            app->setHeader(request, "Shib-Identity-Provider", hval);
         hval = session->getAuthnInstant();
         if (hval)
-            request.setHeader("Shib-Authentication-Instant", hval);
+            app->setHeader(request, "Shib-Authentication-Instant", hval);
         hval = session->getAuthnContextClassRef();
         if (hval) {
-            request.setHeader("Shib-Authentication-Method", hval);
-            request.setHeader("Shib-AuthnContext-Class", hval);
+            app->setHeader(request, "Shib-Authentication-Method", hval);
+            app->setHeader(request, "Shib-AuthnContext-Class", hval);
         }
         hval = session->getAuthnContextDeclRef();
         if (hval)
-            request.setHeader("Shib-AuthnContext-Decl", hval);
+            app->setHeader(request, "Shib-AuthnContext-Decl", hval);
 
         // Maybe export the assertion keys.
         pair<bool,bool> exp=settings.first->getBool("exportAssertion");
@@ -397,16 +406,18 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                     *(exportName.rbegin()) = '0' + (count%10);
                     *(++exportName.rbegin()) = '0' + (count/10);
                     string fullURL = baseURL + encoder->encode(*tokenids);
-                    request.setHeader(exportName.c_str(), fullURL.c_str());
+                    app->setHeader(request, exportName.c_str(), fullURL.c_str());
                 }
-                request.setHeader("Shib-Assertion-Count", exportName.c_str() + 15);
+                app->setHeader(request, "Shib-Assertion-Count", exportName.c_str() + 15);
             }
         }
 
         // Export the attributes.
         const multimap<string,const Attribute*>& attributes = session->getIndexedAttributes();
         for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) {
-            string header(request.getSecureHeader(a->first.c_str()));
+            if (a->second->isInternal())
+                continue;
+            string header(app->getSecureHeader(request, a->first.c_str()));
             const vector<string>& vals = a->second->getSerializedValues();
             for (vector<string>::const_iterator v = vals.begin(); v!=vals.end(); ++v) {
                 if (!header.empty())
@@ -424,7 +435,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                     header += (*v);
                 }
             }
-            request.setHeader(a->first.c_str(), header.c_str());
+            app->setHeader(request, a->first.c_str(), header.c_str());
         }
 
         // Check for REMOTE_USER.
@@ -433,7 +444,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
         for (vector<string>::const_iterator rmid = rmids.begin(); !remoteUserSet && rmid != rmids.end(); ++rmid) {
             pair<multimap<string,const Attribute*>::const_iterator,multimap<string,const Attribute*>::const_iterator> matches =
                 attributes.equal_range(*rmid);
-            while (matches.first != matches.second) {
+            for (; matches.first != matches.second; ++matches.first) {
                 const vector<string>& vals = matches.first->second->getSerializedValues();
                 if (!vals.empty()) {
                     request.setRemoteUser(vals.front().c_str());
@@ -446,6 +457,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
         return make_pair(false,0L);
     }
     catch (exception& e) {
+        request.log(SPRequest::SPError, e.what());
         TemplateParameters tp(&e);
         tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
         return make_pair(true,sendError(log, request, app, "session", tp));
@@ -525,6 +537,7 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
         throw ConfigurationException("Configured Shibboleth handler failed to process the request.");
     }
     catch (exception& e) {
+        request.log(SPRequest::SPError, e.what());
         TemplateParameters tp(&e);
         tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
         tp.m_request = &request;
index d4301e4..36c32bc 100644 (file)
@@ -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.
 #include "attribute/SimpleAttribute.h"
 #include "attribute/ScopedAttribute.h"
 #include "attribute/NameIDAttribute.h"
+#include "attribute/ExtensibleAttribute.h"
+#include "attribute/XMLAttribute.h"
 #include "util/SPConstants.h"
 
+#include <xercesc/util/Base64.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 
 using namespace shibsp;
@@ -50,26 +53,44 @@ namespace shibsp {
         return new NameIDAttribute(in);
     }
 
+    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
+        return new ExtensibleAttribute(in);
+    }
+
+    SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
+        return new XMLAttribute(in);
+    }
+
 #ifndef SHIBSP_LITE
-    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
-    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
-    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
-    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
 
     static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _NameIDAttributeDecoder[] = UNICODE_LITERAL_22(N,a,m,e,I,D,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _NameIDFromScopedAttributeDecoder[] = UNICODE_LITERAL_32(N,a,m,e,I,D,F,r,o,m,S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _KeyInfoAttributeDecoder[] =UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _DOMAttributeDecoder[] =    UNICODE_LITERAL_19(D,O,M,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    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 internal[] =                UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
 #endif
 };
 
 #ifndef SHIBSP_LITE
-QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _StringAttributeDecoder);
-QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
-QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
-QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
+xmltooling::QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _StringAttributeDecoder);
+xmltooling::QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
+xmltooling::QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
+xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
+xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
+xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
+xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
 
 void shibsp::registerAttributeDecoders()
 {
@@ -78,14 +99,21 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(ScopedAttributeDecoderType, ScopedAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(NameIDAttributeDecoderType, NameIDAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
 }
 
-AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true)
+AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), m_internal(false)
 {
     if (e) {
-        const XMLCh* flag = e->getAttributeNS(NULL,caseSensitive);
+        const XMLCh* flag = e->getAttributeNS(NULL, caseSensitive);
         if (flag && (*flag == chLatin_f || *flag == chDigit_0))
             m_caseSensitive = false;
+
+        flag = e->getAttributeNS(NULL, internal);
+        if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+            m_internal = true;
     }
 }
 #endif
@@ -96,14 +124,76 @@ void shibsp::registerAttributeFactories()
     Attribute::registerFactory("Simple", SimpleAttributeFactory);
     Attribute::registerFactory("Scoped", ScopedAttributeFactory);
     Attribute::registerFactory("NameID", NameIDAttributeFactory);
+    Attribute::registerFactory("Extensible", ExtensibleAttributeFactory);
+    Attribute::registerFactory("XML", XMLAttributeFactory);
+}
+
+map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
+
+Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()), m_internal(!in["internal"].isnull())
+{
+    const char* id = in.first().name();
+    if (id && *id)
+        m_id.push_back(id);
+    else
+        throw AttributeException("No id found in marshalled attribute content.");
+    DDF aliases = in["aliases"];
+    if (aliases.islist()) {
+        DDF alias = aliases.first();
+        while (alias.isstring()) {
+            m_id.push_back(alias.string());
+            alias = aliases.next();
+        }
+    }
 }
 
-std::map<std::string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
+DDF Attribute::marshall() const
+{
+    DDF ddf(NULL);
+    ddf.structure().addmember(m_id.front().c_str()).list();
+    if (!m_caseSensitive)
+        ddf.addmember("case_insensitive");
+    if (m_internal)
+        ddf.addmember("internal");
+    if (m_id.size() > 1) {
+        DDF alias;
+        DDF aliases = ddf.addmember("aliases").list();
+        for (std::vector<std::string>::const_iterator a = m_id.begin() + 1; a != m_id.end(); ++a) {
+            alias = DDF(NULL).string(a->c_str());
+            aliases.add(alias);
+        }
+    }
+    return ddf;
+}
 
 Attribute* Attribute::unmarshall(DDF& in)
 {
     map<string,AttributeFactory*>::const_iterator i = m_factoryMap.find(in.name() ? in.name() : "");
     if (i == m_factoryMap.end())
-        throw AttributeException("No registered factory for Attribute of type ($1).", xmltooling::params(1,in.name()));
+        throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
     return (i->second)(in);
 }
+
+const vector<string>& XMLAttribute::getSerializedValues() const
+{
+    xsecsize_t len;
+    XMLByte *pos, *pos2;\r
+    if (m_serialized.empty()) {
+        for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+            XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
+            if (enc) {
+                for (pos=enc, pos2=enc; *pos2; pos2++)\r
+                    if (isgraph(*pos2))\r
+                        *pos++=*pos2;\r
+                *pos=0;\r
+                m_serialized.push_back(reinterpret_cast<char*>(enc));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&enc);
+#else
+                XMLString::release((char**)&enc);
+#endif
+            }
+        }
+    }
+    return Attribute::getSerializedValues();
+}
index 1219681..37e1d39 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/attribute/Attribute.h
- * 
+ *
  * A resolved attribute.
  */
 
@@ -39,16 +39,16 @@ namespace shibsp {
 
     /**
      * A resolved attribute.
-     * 
+     *
      * <p>Resolved attributes are a neutral construct that represent both simple and
      * complex attribute data structures that might be found in SAML assertions
      * or obtained from other sources.
-     * 
+     *
      * <p>Attributes consist of an id/name that is locally unique (that is, unique to a
      * configuration at any given point in time) and zero or more values. Values can
      * be of any type or structure, but will generally be made available to applications
      * only if a serialized string form exists. More complex values can be used with
-     * access control plugins that understand them, however. 
+     * access control plugins and other components that understand them, however.
      */
     class SHIBSP_API Attribute
     {
@@ -56,50 +56,36 @@ namespace shibsp {
     protected:
         /**
          * Constructor
-         * 
+         *
          * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        Attribute(const std::vector<std::string>& ids) : m_id(ids), m_caseSensitive(true) {
+        Attribute(const std::vector<std::string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false) {
         }
 
         /**
          * Constructs based on a remoted Attribute.
-         * 
+         *
          * <p>This allows Attribute objects to be recreated after marshalling.
          * The DDF supplied must be a struct containing a single list member named
          * with the Attribute's "id" and containing the values.
-         * 
+         *
          * @param in    input object containing marshalled Attribute
          */
-        Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()) {
-            const char* id = in.first().name();
-            if (id && *id)
-                m_id.push_back(id);
-            else
-                throw AttributeException("No id found in marshalled attribute content.");
-            DDF aliases = in["aliases"];
-            if (aliases.islist()) {
-                DDF alias = aliases.first();
-                while (alias.isstring()) {
-                    m_id.push_back(alias.string());
-                    alias = aliases.next();
-                }
-            }
-        }
-        
+        Attribute(DDF& in);
+
         /**
          * Maintains a copy of serialized attribute values, when possible.
-         * 
+         *
          * <p>Implementations should maintain the array when values are added or removed.
          */
         mutable std::vector<std::string> m_serialized;
 
     public:
         virtual ~Attribute() {}
-        
+
         /**
          * Returns the Attribute identifier.
-         * 
+         *
          * @return the Attribute identifier
          */
         const char* getId() const {
@@ -134,6 +120,15 @@ namespace shibsp {
         }
 
         /**
+         * Sets whether the attribute should be exported for CGI use.
+         *
+         * @param export  true iff the attribute should <strong>NOT</strong> be exported
+         */
+        void setInternal(bool internal) {
+            m_internal = internal;
+        }
+
+        /**
          * Indicates whether case sensitivity should apply to basic value comparisons.
          *
          * @return  true iff value comparisons should be case sensitive
@@ -141,31 +136,40 @@ namespace shibsp {
         bool isCaseSensitive() const {
             return m_caseSensitive;
         }
-        
+
+        /**
+         * Indicates whether the attribute should be exported for CGI use.
+         *
+         * @return  true iff the attribute should <strong>NOT</strong> be exported
+         */
+        bool isInternal() const {
+            return m_internal;
+        }
+
         /**
          * Returns the number of values.
-         * 
+         *
          * @return  number of values
          */
         virtual size_t valueCount() const {
             return m_serialized.size();
         }
-        
+
         /**
          * Returns serialized Attribute values encoded as UTF-8 strings.
-         * 
+         *
          * @return  an immutable vector of values
          */
         virtual const std::vector<std::string>& getSerializedValues() const {
             return m_serialized;
         }
-        
+
         /**
          * Informs the Attribute that values have changed and any serializations
-         * must be cleared. 
+         * must be cleared.
          */
         virtual void clearSerializedValues()=0;
-        
+
         /**
          * Gets the string equivalent of the value at the specified position (starting from zero).
          *
@@ -198,54 +202,40 @@ namespace shibsp {
 
         /**
          * Marshalls an Attribute for remoting.
-         * 
+         *
          * <p>This allows Attribute objects to be communicated across process boundaries
          * without excess XML parsing. The DDF returned must be a struct containing
          * a single list member named with the Attribute's "id". The name of the struct
          * should contain the registered name of the Attribute implementation.
          */
-        virtual DDF marshall() const {
-            DDF ddf(NULL);
-            ddf.structure().addmember(m_id.front().c_str()).list();
-            if (!m_caseSensitive)
-                ddf.addmember("case_insensitive");
-            if (m_id.size() > 1) {
-                DDF alias;
-                DDF aliases = ddf.addmember("aliases").list();
-                for (std::vector<std::string>::const_iterator a = m_id.begin() + 1; a != m_id.end(); ++a) {
-                    alias = DDF(NULL).string(a->c_str());
-                    aliases.add(alias);
-                }
-            }
-            return ddf;
-        }
-        
+        virtual DDF marshall() const;
+
         /**
          * Unmarshalls a remoted Attribute.
-         * 
+         *
          * @param in    remoted Attribute data
-         * @return  a resolved Attribute of the proper subclass 
+         * @return  a resolved Attribute of the proper subclass
          */
         static Attribute* unmarshall(DDF& in);
-        
+
         /** A function that unmarshalls remoted data into the proper Attribute subclass. */
         typedef Attribute* AttributeFactory(DDF& in);
 
         /**
          * Registers an AttributeFactory function for a given attribute "type".
-         * 
+         *
          * @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;
         }
 
         /**
          * 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);
         }
@@ -256,11 +246,11 @@ namespace shibsp {
         static void deregisterFactories() {
             m_factoryMap.clear();
         }
-        
+
     private:
         static std::map<std::string,AttributeFactory*> m_factoryMap;
         std::vector<std::string> m_id;
-        bool m_caseSensitive;
+        bool m_caseSensitive,m_internal;
     };
 
 #if defined (_MSC_VER)
@@ -269,7 +259,7 @@ namespace shibsp {
 
     /** Registers built-in Attribute types into the runtime. */
     void registerAttributeFactories();
-    
+
 };
 
 #endif /* __shibsp_attribute_h__ */
index 7063ceb..5b0ad48 100644 (file)
@@ -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.
@@ -45,6 +45,21 @@ namespace shibsp {
         /** Flag for case sensitivity of decoded attributes. */
         bool m_caseSensitive;
 
+        /** Flag for hiding attributes from CGI export. */
+        bool m_internal;
+
+        /**
+         * 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;
+        }
+
     public:
         virtual ~AttributeDecoder() {}
 
@@ -78,6 +93,15 @@ namespace shibsp {
     /** Decodes scoped attributes into a NameIDAttribute. */
     extern SHIBSP_API xmltooling::QName NameIDFromScopedAttributeDecoderType;
 
+    /** Decodes KeyInfo information into a SimpleAttribute. */
+    extern SHIBSP_API xmltooling::QName KeyInfoAttributeDecoderType;
+
+    /** Decodes arbitrary DOM information into an ExtensibleAttribute. */
+    extern SHIBSP_API xmltooling::QName DOMAttributeDecoderType;
+
+    /** Decodes arbitrary XML into an XMLAttribute. */
+    extern SHIBSP_API xmltooling::QName XMLAttributeDecoderType;
+
     /** Registers built-in AttributeDecoders into the runtime. */
     void registerAttributeDecoders();
 };
diff --git a/shibsp/attribute/DOMAttributeDecoder.cpp b/shibsp/attribute/DOMAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..98cb87c
--- /dev/null
@@ -0,0 +1,226 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * DOMAttributeDecoder.cpp\r
+ *\r
+ * Decodes a DOM into an ExtensibleAttribute.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "attribute/AttributeDecoder.h"\r
+#include "attribute/ExtensibleAttribute.h"\r
+\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+using namespace shibsp;\r
+using namespace opensaml;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder\r
+    {\r
+    public:\r
+        DOMAttributeDecoder(const DOMElement* e);\r
+        ~DOMAttributeDecoder() {}\r
+\r
+        Attribute* decode(\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            ) const;\r
+\r
+    private:\r
+        DDF convert(DOMElement* e, bool nameit=true) const;\r
+        auto_ptr_char m_formatter;\r
+        map<pair<xstring,xstring>,string> m_tagMap;\r
+    };\r
+\r
+    AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)\r
+    {\r
+        return new DOMAttributeDecoder(e);\r
+    }\r
+\r
+    static const XMLCh Mapping[] =  UNICODE_LITERAL_7(M,a,p,p,i,n,g);\r
+    static const XMLCh _from[] =    UNICODE_LITERAL_4(f,r,o,m);\r
+    static const XMLCh _to[] =      UNICODE_LITERAL_2(t,o);\r
+    static const XMLCh formatter[] =      UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
+};\r
+\r
+DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)\r
+    : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)\r
+{\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
+\r
+    e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;\r
+    while (e) {\r
+        if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {\r
+            auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));\r
+            auto_ptr_char t(e->getAttributeNS(NULL, _to));\r
+            if (f.get() && t.get() && *t.get()) {\r
+                if (log.isDebugEnabled())\r
+                    log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());\r
+                m_tagMap.insert(\r
+                    pair< const pair<xstring,xstring>,string>(\r
+                        pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),\r
+                        t.get()\r
+                        )\r
+                    );\r
+            }\r
+        }\r
+        e = XMLHelper::getNextSiblingElement(e, Mapping);\r
+    }\r
+}\r
+\r
+Attribute* DOMAttributeDecoder::decode(\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    ) const\r
+{\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
+\r
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
+        log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
+        return NULL;\r
+    }\r
+\r
+    auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));\r
+    DDF dest = attr->getValues();\r
+    vector<XMLObject*>::const_iterator v,stop;\r
+\r
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
+    if (saml2attr) {\r
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
+        v = values.begin();\r
+        stop = values.end();\r
+        if (log.isDebugEnabled()) {\r
+            auto_ptr_char n(saml2attr->getName());\r
+            log.debug(\r
+                "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                );\r
+        }\r
+    }\r
+    else {\r
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
+        if (saml1attr) {\r
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
+            v = values.begin();\r
+            stop = values.end();\r
+            if (log.isDebugEnabled()) {\r
+                auto_ptr_char n(saml1attr->getAttributeName());\r
+                log.debug(\r
+                    "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
+            }\r
+        }\r
+        else {\r
+            log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
+            return NULL;\r
+        }\r
+    }\r
+\r
+    for (; v!=stop; ++v) {\r
+        DOMElement* e = (*v)->getDOM();\r
+        if (e) {\r
+            DDF converted = convert(e, false);\r
+            if (!converted.isnull())\r
+                dest.add(converted);\r
+        }\r
+        else\r
+            log.warn("skipping AttributeValue without a backing DOM");\r
+    }\r
+\r
+    return dest.integer() ? _decode(attr.release()) : NULL;\r
+}\r
+\r
+DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const\r
+{\r
+    const XMLCh* nsURI;\r
+    const XMLCh* local;\r
+    map<pair<xstring,xstring>,string>::const_iterator mapping;\r
+    DDF obj = DDF(NULL).structure();\r
+\r
+    if (nameit) {\r
+        // Name this structure.\r
+        nsURI = e->getNamespaceURI();\r
+        local = e->getLocalName();\r
+        mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));\r
+        if (mapping == m_tagMap.end()) {\r
+            auto_ptr_char temp(local);\r
+            obj.name(temp.get());\r
+        }\r
+        else {\r
+            obj.name(mapping->second.c_str());\r
+        }\r
+    }\r
+\r
+    // Process non-xmlns attributes.\r
+    DOMNamedNodeMap* attrs = e->getAttributes();\r
+    for (XMLSize_t a = attrs->getLength(); a > 0; --a) {\r
+        DOMNode* attr = attrs->item(a-1);\r
+        nsURI = attr->getNamespaceURI();\r
+        if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))\r
+            continue;\r
+        local = attr->getLocalName();\r
+        mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));\r
+        if (mapping == m_tagMap.end()) {\r
+            auto_ptr_char temp(local);\r
+            obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);\r
+        }\r
+        else {\r
+            obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);\r
+        }\r
+    }\r
+\r
+    DOMElement* child = XMLHelper::getFirstChildElement(e);\r
+    if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {\r
+        // Attach a _text member if a text node is present.\r
+        obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);\r
+    }\r
+    else {\r
+        while (child) {\r
+            // Convert the child element.\r
+            DDF converted = convert(child);\r
+            if (!converted.isnull()) {\r
+                // Now identify it and attach it.\r
+                if (obj[converted.name()].isnull()) {\r
+                    // We're a new child, so just attach as a structure member.\r
+                    obj.add(converted);\r
+                }\r
+                else if (obj[converted.name()].islist()) {\r
+                    // We're already a repeating child, so add it to the list.\r
+                    obj[converted.name()].add(converted);\r
+                }\r
+                else if (obj[converted.name()].isstruct()) {\r
+                    // This is the complex case where we see a child for the second\r
+                    // time and have to convert a structure member into a named list.\r
+                    DDF newlist = DDF(converted.name()).list();\r
+                    newlist.add(obj[converted.name()].remove());\r
+                    newlist.add(converted);\r
+                    obj.add(newlist);\r
+                }\r
+            }\r
+            child = XMLHelper::getNextSiblingElement(child);\r
+        }\r
+    }\r
+\r
+    // If we're empty, just delete.\r
+    if (obj.integer() == 0)\r
+        obj.destroy();\r
+    return obj;\r
+}\r
diff --git a/shibsp/attribute/ExtensibleAttribute.cpp b/shibsp/attribute/ExtensibleAttribute.cpp
new file mode 100644 (file)
index 0000000..5602c55
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  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.
+ */
+
+/**
+ * shibsp/attribute/ExtensibleAttribute.cpp
+ *
+ * An Attribute whose values are arbitrary structures.
+ */
+
+#include "internal.h"
+#include "SPConfig.h"
+#include "attribute/ExtensibleAttribute.h"
+#include "util/SPConstants.h"
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+const vector<string>& ExtensibleAttribute::getSerializedValues() const
+{
+    if (m_serialized.empty()) {
+        const char* formatter = m_obj["_formatter"].string();
+        if (formatter) {
+            string msg = formatter;
+            DDF val = m_obj.first().first();
+            while (!val.isnull()) {
+
+                static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_.[]";
+
+                m_serialized.push_back(string());
+                string& processed = m_serialized.back();
+
+                string::size_type i=0,start=0;
+                while (start!=string::npos && start<msg.length() && (i=msg.find("$",start))!=string::npos) {
+                    if (i>start)
+                        processed += msg.substr(start,i-start); // append everything in between
+                    start=i+1;                                  // move start to the beginning of the token name
+                    i=msg.find_first_not_of(legal,start);       // find token delimiter
+                    if (i==start) {                             // append a non legal character
+                       processed+=msg[start++];
+                       continue;
+                    }
+                    
+                    string tag = msg.substr(start,(i==string::npos) ? i : i-start);
+                    if (tag == "_string" && val.string()) {
+                        processed += val.string();
+                        start=i;
+                    }
+                    else {
+                        DDF child = val.getmember(tag.c_str());
+                        if (child.string())
+                            processed += child.string();
+                        else if (child.isstruct() && child["_string"].string())
+                            processed += child["_string"].string();
+                        start=i;
+                    }
+                }
+                if (start!=string::npos && start<msg.length())
+                    processed += msg.substr(start,i);    // append rest of string
+
+                val = m_obj.first().next();
+            }
+        }
+    }
+    return Attribute::getSerializedValues();
+}
diff --git a/shibsp/attribute/ExtensibleAttribute.h b/shibsp/attribute/ExtensibleAttribute.h
new file mode 100644 (file)
index 0000000..8a12836
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  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.
+ */
+
+/**
+ * @file shibsp/attribute/ExtensibleAttribute.h
+ *
+ * An Attribute whose values are arbitrary structures.
+ */
+
+#ifndef __shibsp_extattr_h__
+#define __shibsp_extattr_h__
+
+#include <shibsp/attribute/Attribute.h>
+#include <xmltooling/exceptions.h>
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * An Attribute whose values are arbitrary structures.
+     */
+    class SHIBSP_API ExtensibleAttribute : public Attribute
+    {
+    public:
+        /**
+         * Constructor.
+         *
+         * @param ids       array with primary identifier in first position, followed by any aliases
+         * @param formatter template for serialization of values
+         */
+        ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter) : Attribute(ids) {
+            m_obj = Attribute::marshall();
+            m_obj.name("Extensible");
+            m_obj.addmember("_formatter").string(formatter);
+        }
+
+        /**
+         * Constructs based on a remoted ExtensibleAttribute.
+         *
+         * @param in    input object containing marshalled ExtensibleAttribute
+         */
+        ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy()) {
+        }
+
+        virtual ~ExtensibleAttribute() {
+            m_obj.destroy();
+        }
+
+        /**
+         * Returns the set of values in a DDF list.
+         *
+         * @return  a mutable list object containing the values
+         */
+        DDF getValues() {
+            return m_obj.first();
+        }
+
+        size_t valueCount() const {
+            return m_obj.first().integer();
+        }
+
+        void clearSerializedValues() {
+            m_serialized.clear();
+        }
+
+        const char* getString(size_t index) const {
+            return m_obj.first()[static_cast<unsigned long>(index)].string();
+        }
+
+        const char* getScope(size_t index) const {
+            return NULL;
+        }
+
+        void removeValue(size_t index) {
+            Attribute::removeValue(index);
+            DDF vals = m_obj.first();
+            if (index < static_cast<size_t>(vals.integer()))
+                vals[static_cast<unsigned long>(index)].remove().destroy();
+        }
+
+        const std::vector<std::string>& getSerializedValues() const;
+
+        DDF marshall() const {
+            if (!isCaseSensitive())
+                m_obj.addmember("case_insensitive");
+            if (isInternal())
+                m_obj.addmember("internal");
+            return m_obj.copy();
+        }
+
+    private:
+        mutable DDF m_obj;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+};
+
+#endif /* __shibsp_nameidattr_h__ */
diff --git a/shibsp/attribute/KeyInfoAttributeDecoder.cpp b/shibsp/attribute/KeyInfoAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..3ab80f2
--- /dev/null
@@ -0,0 +1,157 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * KeyInfoAttributeDecoder.cpp\r
+ *\r
+ * Decodes KeyInfo information into a SimpleAttribute.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "attribute/AttributeDecoder.h"\r
+#include "attribute/SimpleAttribute.h"\r
+\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/security/SecurityHelper.h>\r
+#include <xmltooling/signature/KeyInfo.h>\r
+\r
+using namespace shibsp;\r
+using namespace opensaml;\r
+using namespace xmlsignature;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder\r
+    {\r
+    public:\r
+        KeyInfoAttributeDecoder(const DOMElement* e);\r
+        ~KeyInfoAttributeDecoder() {\r
+            delete m_keyInfoResolver;\r
+        }\r
+\r
+        Attribute* decode(\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            ) const;\r
+\r
+    private:\r
+        void extract(const KeyInfo* k, vector<string>& dest) const {\r
+            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));\r
+            if (cred.get()) {\r
+                dest.push_back(string());\r
+                dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash);\r
+                if (dest.back().empty())\r
+                    dest.pop_back();\r
+            }\r
+        }\r
+\r
+        const KeyInfoResolver* getKeyInfoResolver() const {\r
+            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();\r
+        }\r
+\r
+        bool m_hash;\r
+        KeyInfoResolver* m_keyInfoResolver;\r
+    };\r
+\r
+    AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)\r
+    {\r
+        return new KeyInfoAttributeDecoder(e);\r
+    }\r
+\r
+    static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);\r
+    static const XMLCh _hash[] =            UNICODE_LITERAL_4(h,a,s,h);\r
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
+};\r
+\r
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {\r
+    const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;\r
+    m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
+    e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;\r
+    if (e) {\r
+        auto_ptr_char t(e->getAttributeNS(NULL, _type));\r
+        if (t.get() && *t.get())\r
+            m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);\r
+        else\r
+            throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");\r
+    }\r
+}\r
+\r
+Attribute* KeyInfoAttributeDecoder::decode(\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    ) const\r
+{\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");\r
+\r
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
+        log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
+        return NULL;\r
+    }\r
+\r
+    auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));\r
+    vector<string>& dest = attr->getValues();\r
+    vector<XMLObject*>::const_iterator v,stop;\r
+\r
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
+    if (saml2attr) {\r
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
+        v = values.begin();\r
+        stop = values.end();\r
+        if (log.isDebugEnabled()) {\r
+            auto_ptr_char n(saml2attr->getName());\r
+            log.debug(\r
+                "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                );\r
+        }\r
+    }\r
+    else {\r
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
+        if (saml1attr) {\r
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
+            v = values.begin();\r
+            stop = values.end();\r
+            if (log.isDebugEnabled()) {\r
+                auto_ptr_char n(saml1attr->getAttributeName());\r
+                log.debug(\r
+                    "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
+            }\r
+        }\r
+        else {\r
+            log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
+            return NULL;\r
+        }\r
+    }\r
+\r
+    for (; v!=stop; ++v) {\r
+        const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);\r
+        if (k)\r
+            extract(k, dest);\r
+        else if ((*v)->hasChildren()) {\r
+            const list<XMLObject*>& children = (*v)->getOrderedChildren();\r
+            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {\r
+                if (k=dynamic_cast<const KeyInfo*>(*vv))\r
+                    extract(k, dest);\r
+                else\r
+                    log.warn("skipping AttributeValue without a recognizable KeyInfo");\r
+            }\r
+        }\r
+    }\r
+\r
+    return dest.empty() ? NULL : _decode(attr.release());\r
+}\r
index bd292ce..1b8d247 100644 (file)
@@ -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/attribute/NameIDAttribute.h
  * 
- * An Attribute whose values are relations of a value and a scope.
+ * An Attribute whose values are derived from or mappable to a SAML NameID.
  */
 
 #ifndef __shibsp_nameidattr_h__
@@ -102,14 +102,21 @@ namespace shibsp {
         /**
          * Returns the set of values encoded as UTF-8 strings.
          * 
-         * <p>Each compound value is a pair containing the simple value and the scope. 
-         * 
          * @return  a mutable vector of the values
          */
         std::vector<Value>& getValues() {
             return m_values;
         }
-        
+
+        /**
+         * Returns the set of values encoded as UTF-8 strings.
+         * 
+         * @return  an immutable vector of the values
+         */
+        const std::vector<Value>& getValues() const {
+            return m_values;
+        }
+
         size_t valueCount() const {
             return m_values.size();
         }
index 440fa57..903bc33 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -34,12 +34,18 @@ using namespace xmltooling;
 using namespace std;\r
 \r
 namespace shibsp {\r
-    static XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
+    static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
+    static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);\r
 \r
     class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder\r
     {\r
     public:\r
-        NameIDAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {}\r
+        NameIDAttributeDecoder(const DOMElement* e)\r
+                : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {\r
+            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;\r
+            if (flag && (*flag == chLatin_t || *flag == chDigit_1))\r
+                m_defaultQualifiers = true;\r
+        }\r
         ~NameIDAttributeDecoder() {}\r
 \r
         shibsp::Attribute* decode(\r
@@ -54,6 +60,7 @@ namespace shibsp {
             const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
             ) const;\r
         auto_ptr_char m_formatter;\r
+        bool m_defaultQualifiers;\r
     };\r
 \r
     AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)\r
@@ -69,7 +76,6 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
     auto_ptr<NameIDAttribute> nameid(\r
         new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
         );\r
-    nameid->setCaseSensitive(m_caseSensitive);\r
     vector<NameIDAttribute::Value>& dest = nameid->getValues();\r
     vector<XMLObject*>::const_iterator v,stop;\r
 \r
@@ -131,7 +137,7 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
             }\r
         }\r
 \r
-        return dest.empty() ? NULL : nameid.release();\r
+        return dest.empty() ? NULL : _decode(nameid.release());\r
     }\r
 \r
     const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);\r
@@ -160,7 +166,7 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
         }\r
     }\r
 \r
-    return dest.empty() ? NULL : nameid.release();\r
+    return dest.empty() ? NULL : _decode(nameid.release());\r
 }\r
 \r
 void NameIDAttributeDecoder::extract(\r
@@ -181,14 +187,14 @@ void NameIDAttributeDecoder::extract(
         str = toUTF8(n->getNameQualifier());\r
         if (str && *str)\r
             val.m_NameQualifier = str;\r
-        else if (assertingParty)\r
+        else if (m_defaultQualifiers && assertingParty)\r
             val.m_NameQualifier = assertingParty;\r
         delete[] str;\r
 \r
         str = toUTF8(n->getSPNameQualifier());\r
         if (str && *str)\r
             val.m_SPNameQualifier = str;\r
-        else if (relyingParty)\r
+        else if (m_defaultQualifiers && relyingParty)\r
             val.m_SPNameQualifier = relyingParty;\r
         delete[] str;\r
 \r
@@ -218,11 +224,11 @@ void NameIDAttributeDecoder::extract(
         str = toUTF8(n->getNameQualifier());\r
         if (str && *str)\r
             val.m_NameQualifier = str;\r
-        else if (assertingParty)\r
+        else if (m_defaultQualifiers && assertingParty)\r
             val.m_NameQualifier = assertingParty;\r
         delete[] str;\r
 \r
-        if (relyingParty)\r
+        if (m_defaultQualifiers && relyingParty)\r
             val.m_SPNameQualifier = relyingParty;\r
     }\r
 }\r
index 7e807b9..ab72dfb 100644 (file)
@@ -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.
@@ -34,20 +34,28 @@ using namespace xmltooling;
 using namespace std;
 
 namespace shibsp {
-    static XMLCh format[] =                 UNICODE_LITERAL_6(f,o,r,m,a,t);
-    static 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);
+    static const XMLCh format[] =           UNICODE_LITERAL_6(f,o,r,m,a,t);
+    static const XMLCh formatter[] =        UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
     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);
 
     class SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoder : virtual public AttributeDecoder
     {
     public:
-        NameIDFromScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@'),
-                m_format(e ? e->getAttributeNS(NULL,format) : NULL), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {
+        NameIDFromScopedAttributeDecoder(const DOMElement* e)
+            : AttributeDecoder(e),
+                m_delimeter('@'),
+                m_format(e ? e->getAttributeNS(NULL,format) : NULL),
+                m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL),
+                m_defaultQualifiers(false) {
             if (e && e->hasAttributeNS(NULL,scopeDelimeter)) {
                 auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));
                 m_delimeter = *(d.get());
             }
+            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;
+            if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+                m_defaultQualifiers = true;
         }
         ~NameIDFromScopedAttributeDecoder() {}
 
@@ -59,6 +67,7 @@ namespace shibsp {
         char m_delimeter;
         auto_ptr_char m_format;
         auto_ptr_char m_formatter;
+        bool m_defaultQualifiers;
     };
 
     AttributeDecoder* SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoderFactory(const DOMElement* const & e)
@@ -75,11 +84,10 @@ shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
     char* val;
     char* scope;
     const XMLCh* xmlscope;
-    QName scopeqname(NULL,Scope);
+    xmltooling::QName scopeqname(NULL,Scope);
     auto_ptr<NameIDAttribute> nameid(
         new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
         );
-    nameid->setCaseSensitive(m_caseSensitive);
     vector<NameIDAttribute::Value>& dest = nameid->getValues();
     vector<XMLObject*>::const_iterator v,stop;
 
@@ -135,9 +143,9 @@ shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
                     destval.m_Name = val;
                     if (m_format.get() && *m_format.get())
                         destval.m_Format = m_format.get();
-                    if (assertingParty)
+                    if (m_defaultQualifiers && assertingParty)
                         destval.m_NameQualifier = assertingParty;
-                    if (relyingParty)
+                    if (m_defaultQualifiers && relyingParty)
                         destval.m_SPNameQualifier = relyingParty;
                 }
                 else {
@@ -150,7 +158,7 @@ shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
             }
         }
 
-        return dest.empty() ? NULL : nameid.release();
+        return dest.empty() ? NULL : _decode(nameid.release());
     }
 
     log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");
index d72cd0c..a8acac5 100644 (file)
@@ -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.
@@ -84,6 +84,17 @@ namespace shibsp {
             return m_values;
         }
 
+        /**
+         * Returns the set of values encoded as UTF-8 strings.
+         * 
+         * <p>Each compound value is a pair containing the simple value and the scope. 
+         * 
+         * @return  an immutable vector of the values
+         */
+        const std::vector< std::pair<std::string,std::string> >& getValues() const {
+            return m_values;
+        }
+
         size_t valueCount() const {
             return m_values.size();
         }
index 2044d6b..c3054c8 100644 (file)
@@ -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.
@@ -69,9 +69,8 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
     char* val;
     char* scope;
     const XMLCh* xmlscope;
-    QName scopeqname(NULL,Scope);
+    xmltooling::QName scopeqname(NULL,Scope);
     auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimeter));
-    scoped->setCaseSensitive(m_caseSensitive);
     vector< pair<string,string> >& dest = scoped->getValues();
     vector<XMLObject*>::const_iterator v,stop;
 
@@ -146,7 +145,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
             }
         }
 
-        return dest.empty() ? NULL : scoped.release();
+        return dest.empty() ? NULL : _decode(scoped.release());
     }
 
     const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
@@ -192,5 +191,5 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
         log.warn("ignoring empty NameID");
     }
     delete[] val;
-    return dest.empty() ? NULL : scoped.release();
+    return dest.empty() ? NULL : _decode(scoped.release());
 }
index ca86390..f2a9d6f 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -57,7 +57,6 @@ shibsp::Attribute* StringAttributeDecoder::decode(
 {\r
     char* val;\r
     auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));\r
-    simple->setCaseSensitive(m_caseSensitive);\r
     vector<string>& dest = simple->getValues();\r
     vector<XMLObject*>::const_iterator v,stop;\r
 \r
@@ -111,7 +110,7 @@ shibsp::Attribute* StringAttributeDecoder::decode(
             }\r
         }\r
 \r
-        return dest.empty() ? NULL : simple.release();\r
+        return dest.empty() ? NULL : _decode(simple.release());\r
     }\r
 \r
     const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
@@ -145,5 +144,5 @@ shibsp::Attribute* StringAttributeDecoder::decode(
     else\r
         log.warn("ignoring empty NameID");\r
     delete[] val;\r
-    return dest.empty() ? NULL : simple.release();\r
+    return dest.empty() ? NULL : _decode(simple.release());\r
 }\r
diff --git a/shibsp/attribute/XMLAttribute.h b/shibsp/attribute/XMLAttribute.h
new file mode 100644 (file)
index 0000000..3c9a4f6
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  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.
+ */
+
+/**
+ * @file shibsp/attribute/XMLAttribute.h
+ *
+ * An Attribute whose values are serialized XML.
+ */
+
+#ifndef __shibsp_xmlattr_h__
+#define __shibsp_xmlattr_h__
+
+#include <shibsp/attribute/Attribute.h>
+
+namespace shibsp {
+
+    /**
+     * An Attribute whose values are serialized XML.
+     */
+    class SHIBSP_API XMLAttribute : public Attribute
+    {
+    public:
+        /**
+         * Constructor.
+         *
+         * @param ids   array with primary identifier in first position, followed by any aliases
+         */
+        XMLAttribute(const std::vector<std::string>& ids) : Attribute(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();
+            }
+        }
+
+        virtual ~XMLAttribute() {}
+
+        /**
+         * Returns the set of values encoded as XML.
+         *
+         * @return  a mutable vector of the values
+         */
+        std::vector<std::string>& getValues() {
+            return m_values;
+        }
+
+        /**
+         * Returns the set of values encoded as XML.
+         *
+         * @return  an immutable vector of the values
+         */
+        const std::vector<std::string>& getValues() const {
+            return m_values;
+        }
+
+        size_t valueCount() const {
+            return m_values.size();
+        }
+
+        void clearSerializedValues() {
+            m_serialized.clear();
+        }
+
+        const char* getString(size_t index) const {
+            return m_values[index].c_str();
+        }
+
+        void removeValue(size_t index) {
+            Attribute::removeValue(index);
+            if (index < m_values.size())
+                m_values.erase(m_values.begin() + index);
+        }
+
+        const std::vector<std::string>& getSerializedValues() const;
+
+        DDF marshall() const {
+            DDF ddf = Attribute::marshall();
+            ddf.name("XML");
+            DDF vlist = ddf.first();
+            for (std::vector<std::string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+                vlist.add(DDF(NULL).string(i->c_str()));
+            return ddf;
+        }
+
+    private:
+        std::vector<std::string> m_values;
+    };
+
+};
+
+#endif /* __shibsp_xmlattr_h__ */
diff --git a/shibsp/attribute/XMLAttributeDecoder.cpp b/shibsp/attribute/XMLAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..2d59528
--- /dev/null
@@ -0,0 +1,138 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * XMLAttributeDecoder.cpp\r
+ *\r
+ * Decodes arbitrary XML into an XMLAttribute.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "attribute/AttributeDecoder.h"\r
+#include "attribute/XMLAttribute.h"\r
+\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+using namespace shibsp;\r
+using namespace opensaml;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
+    {\r
+    public:\r
+        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
+        ~XMLAttributeDecoder() {}\r
+\r
+        Attribute* decode(\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            ) const;\r
+\r
+    private:\r
+        DDF convert(DOMElement* e, bool nameit=true) const;\r
+        auto_ptr_char m_formatter;\r
+        map<pair<xstring,xstring>,string> m_tagMap;\r
+    };\r
+\r
+    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
+    {\r
+        return new XMLAttributeDecoder(e);\r
+    }\r
+};\r
+\r
+\r
+Attribute* XMLAttributeDecoder::decode(\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    ) const\r
+{\r
+    if (!xmlObject)\r
+        return NULL;\r
+\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
+\r
+    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
+    vector<string>& dest = attr->getValues();\r
+\r
+    // Handle any non-Attribute object directly.\r
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
+        DOMElement* e = xmlObject->getDOM();\r
+        if (e) {\r
+            if (log.isDebugEnabled()) {\r
+                log.debug(\r
+                    "decoding XMLAttribute (%s) from XMLObject (%s)",\r
+                    ids.front().c_str(),\r
+                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
+                    );\r
+            }\r
+            dest.push_back(string());\r
+            XMLHelper::serialize(e, dest.back());\r
+        }\r
+        else {\r
+            log.warn("skipping XMLObject without a backing DOM");\r
+        }\r
+        return dest.empty() ? NULL : _decode(attr.release());\r
+    }\r
+\r
+    vector<XMLObject*>::const_iterator v,stop;\r
+\r
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
+    if (saml2attr) {\r
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
+        v = values.begin();\r
+        stop = values.end();\r
+        if (log.isDebugEnabled()) {\r
+            auto_ptr_char n(saml2attr->getName());\r
+            log.debug(\r
+                "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                );\r
+        }\r
+    }\r
+    else {\r
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
+        if (saml1attr) {\r
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
+            v = values.begin();\r
+            stop = values.end();\r
+            if (log.isDebugEnabled()) {\r
+                auto_ptr_char n(saml1attr->getAttributeName());\r
+                log.debug(\r
+                    "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
+            }\r
+        }\r
+        else {\r
+            log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");\r
+            return NULL;\r
+        }\r
+    }\r
+\r
+    for (; v!=stop; ++v) {\r
+        DOMElement* e = (*v)->getDOM();\r
+        if (e) {\r
+            dest.push_back(string());\r
+            XMLHelper::serialize(e, dest.back());\r
+        }\r
+        else\r
+            log.warn("skipping AttributeValue without a backing DOM");\r
+    }\r
+\r
+    return dest.empty() ? NULL : _decode(attr.release());\r
+}\r
index 857050d..35cea2c 100644 (file)
@@ -109,7 +109,7 @@ MatchFunctor* AndMatchFunctor::buildFunctor(const DOMElement* e, const FilterPol
     if (*id && functorMap->getMatchFunctors().count(id))
         id = "";
 
-    auto_ptr<QName> type(XMLHelper::getXSIType(e));
+    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
     if (!type.get())
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
index 06fd7b2..1ba0ec6 100644 (file)
@@ -31,13 +31,13 @@ using namespace xmltooling;
 using namespace std;
 
 #define DECL_FACTORY(name) \
-    SHIBSP_DLLLOCAL PluginManager< MatchFunctor,QName,pair<const FilterPolicyContext*,const DOMElement*> >::Factory name##Factory
+    SHIBSP_DLLLOCAL PluginManager< MatchFunctor,xmltooling::QName,pair<const FilterPolicyContext*,const DOMElement*> >::Factory name##Factory
 
 #define DECL_BASIC_QNAME(name,lit) \
-    QName shibsp::name##Type(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, lit)
+    xmltooling::QName shibsp::name##Type(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, lit)
 
 #define DECL_SAML_QNAME(name,lit) \
-    QName shibsp::name##Type(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS, lit)
+    xmltooling::QName shibsp::name##Type(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS, lit)
 
 #define REGISTER_FACTORY(name) \
     mgr.registerFactory(name##Type, name##Factory)
@@ -104,7 +104,7 @@ DECL_SAML_QNAME(AttributeScopeMatchesShibMDScope, AttributeScopeMatchesShibMDSco
 
 void SHIBSP_API shibsp::registerMatchFunctors()
 {
-    PluginManager< MatchFunctor,QName,pair<const FilterPolicyContext*,const DOMElement*> >& mgr =
+    PluginManager< MatchFunctor,xmltooling::QName,pair<const FilterPolicyContext*,const DOMElement*> >& mgr =
         SPConfig::getConfig().MatchFunctorManager;
     REGISTER_FACTORY(AnyMatchFunctor);
     REGISTER_FACTORY(AndMatchFunctor);
index 0f79a84..9a22474 100644 (file)
@@ -99,7 +99,7 @@ MatchFunctor* NotMatchFunctor::buildFunctor(const DOMElement* e, const FilterPol
     if (*id && functorMap->getMatchFunctors().count(id))
         id = "";
 
-    auto_ptr<QName> type(XMLHelper::getXSIType(e));
+    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
     if (!type.get())
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
index cd29548..2649f42 100644 (file)
@@ -105,7 +105,7 @@ MatchFunctor* OrMatchFunctor::buildFunctor(const DOMElement* e, const FilterPoli
     if (*id && functorMap->getMatchFunctors().count(id))
         id = "";
 
-    auto_ptr<QName> type(XMLHelper::getXSIType(e));
+    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
     if (!type.get())
         throw ConfigurationException("Child Rule found with no xsi:type.");
 
index b01cf1f..32fab83 100644 (file)
@@ -228,7 +228,7 @@ MatchFunctor* XMLFilterImpl::buildFunctor(
             id = "";
     }
 
-    auto_ptr<QName> type(XMLHelper::getXSIType(e));
+    auto_ptr<xmltooling::QName> type(XMLHelper::getXSIType(e));
     if (type.get()) {
         try {
             MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(&functorMap,e));
@@ -300,10 +300,13 @@ pair< string,pair<const MatchFunctor*,const MatchFunctor*> > XMLFilterImpl::buil
     }
 
     if (perm || deny) {
-        if (*id)
-            return m_attrRules[id] = pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(attrID.get(), pair<const MatchFunctor*,const MatchFunctor*>(perm,deny));
-        else
+        if (*id) {
+            m_attrRules[id] = pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(attrID.get(), pair<const MatchFunctor*,const MatchFunctor*>(perm,deny));
+            return m_attrRules[id];
+        }
+        else {
             return pair< string,pair<const MatchFunctor*,const MatchFunctor*> >(attrID.get(), pair<const MatchFunctor*,const MatchFunctor*>(perm,deny));
+        }
     }
 
     m_log.warn("skipping AttributeRule (%s), permit and denial rule(s) invalid or missing", id);
@@ -430,18 +433,19 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector<Att
                 if (row[index-1])
                     attr->removeValue(index-1);
             }
+        }
 
-            // Check for no values.
-            if (attr->valueCount() == 0) {
-                m_log.warn(
-                    "no values left, removing attribute (%s) from (%s)",
-                    attr->getId(), issuer.get() ? issuer.get() : "unknown source"
-                    );
-                delete attr;
-                attributes.erase(attributes.begin() + a);
-                continue;
-            }
+        // Check for no values.
+        if (attr->valueCount() == 0) {
+            m_log.warn(
+                "no values left, removing attribute (%s) from (%s)",
+                attr->getId(), issuer.get() ? issuer.get() : "unknown source"
+                );
+            delete attr;
+            attributes.erase(attributes.begin() + a);
+            continue;
         }
+
         ++a;
     }
 }
index a0b0a14..63644ca 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/attribute/resolver/AttributeExtractor.h
- * 
+ *
  * A service that extracts and decodes attributes from XML objects.
  */
 
@@ -45,12 +45,12 @@ namespace shibsp {
 
         /**
          * Extracts the attributes found in an XMLObject.
-         * 
+         *
          * @param application   Application performing the extraction
          * @param issuer        source of object, if known
          * @param xmlObject     object to extract
          * @param attributes    an array to populate with the extracted attributes
-         * 
+         *
          * @throws AttributeExtractionException thrown if there is a problem extracting attributes
          */
         virtual void extractAttributes(
@@ -76,6 +76,12 @@ namespace shibsp {
     /** AttributeExtractor based on an XML mapping schema. */
     #define XML_ATTRIBUTE_EXTRACTOR "XML"
 
+    /** AttributeExtractor for DelegationRestriction information. */
+    #define DELEGATION_ATTRIBUTE_EXTRACTOR "Delegation"
+
+    /** AttributeExtractor for KeyInfo information. */
+    #define KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR "KeyDescriptor"
+
     /** AttributeExtractor based on chaining together other extractors. */
     #define CHAINING_ATTRIBUTE_EXTRACTOR "Chaining"
 };
index 73adab1..524dde8 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/attribute/resolver/AttributeResolver.h
- * 
+ *
  * A service that transforms or resolves additional attributes for a particular subject.
  */
 
@@ -54,10 +54,10 @@ namespace shibsp {
 
         /**
          * Creates a ResolutionContext based on session bootstrap material.
-         * 
+         *
          * <p>This enables resolution to occur ahead of session creation so that
          * Attributes can be supplied while creating the session.
-         * 
+         *
          * @param application       reference to Application that owns the eventual Session
          * @param issuer            issuing metadata of assertion issuer, if known
          * @param protocol          protocol used to establish Session
@@ -81,19 +81,19 @@ namespace shibsp {
 
         /**
          * Creates a ResolutionContext for an existing Session.
-         * 
+         *
          * @param application   reference to Application that owns the Session
          * @param session       reference to Session
          * @return  newly created ResolutionContext, owned by caller
          */
         virtual ResolutionContext* createResolutionContext(const Application& application, const Session& session) const=0;
-        
+
 
         /**
          * Resolves attributes for a given subject and returns them in the supplied context.
-         * 
+         *
          * @param ctx           resolution context to use to resolve attributes
-         * 
+         *
          * @throws AttributeResolutionException thrown if there is a problem resolving the attributes for the subject
          */
         virtual void resolveAttributes(ResolutionContext& ctx) const=0;
@@ -118,6 +118,9 @@ namespace shibsp {
     /** AttributeResolver based on SAML queries to an IdP during SSO. */
     #define QUERY_ATTRIBUTE_RESOLVER "Query"
 
+    /** AttributeResolver based on free-standing SAML queries to additional AAs. */
+    #define SIMPLEAGGREGATION_ATTRIBUTE_RESOLVER "SimpleAggregation"
+
     /** AttributeResolver based on chaining together other resolvers. */
     #define CHAINING_ATTRIBUTE_RESOLVER "Chaining"
 };
index de77496..523cdc3 100644 (file)
@@ -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.
@@ -71,6 +71,8 @@ namespace shibsp {
     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 _type[] =                UNICODE_LITERAL_4(t,y,p,e);
 
+    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory DelegationAttributeExtractorFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory KeyDescriptorAttributeExtractorFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory XMLAttributeExtractorFactory;
     AttributeExtractor* SHIBSP_DLLLOCAL ChainingExtractorFactory(const DOMElement* const & e)
     {
@@ -80,6 +82,8 @@ namespace shibsp {
 
 void SHIBSP_API shibsp::registerAttributeExtractors()
 {
+    SPConfig::getConfig().AttributeExtractorManager.registerFactory(DELEGATION_ATTRIBUTE_EXTRACTOR, DelegationAttributeExtractorFactory);
+    SPConfig::getConfig().AttributeExtractorManager.registerFactory(KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR, KeyDescriptorAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(XML_ATTRIBUTE_EXTRACTOR, XMLAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
 }
index 90e3776..d0b63f1 100644 (file)
@@ -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.
@@ -134,6 +134,8 @@ namespace shibsp {
     static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);
 
     SHIBSP_DLLLOCAL PluginManager<AttributeResolver,string,const DOMElement*>::Factory QueryResolverFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeResolver,string,const DOMElement*>::Factory SimpleAggregationResolverFactory;
+
     AttributeResolver* SHIBSP_DLLLOCAL ChainingResolverFactory(const DOMElement* const & e)
     {
         return new ChainingAttributeResolver(e);
@@ -143,6 +145,7 @@ namespace shibsp {
 void SHIBSP_API shibsp::registerAttributeResolvers()
 {
     SPConfig::getConfig().AttributeResolverManager.registerFactory(QUERY_ATTRIBUTE_RESOLVER, QueryResolverFactory);
+    SPConfig::getConfig().AttributeResolverManager.registerFactory(SIMPLEAGGREGATION_ATTRIBUTE_RESOLVER, SimpleAggregationResolverFactory);
     SPConfig::getConfig().AttributeResolverManager.registerFactory(CHAINING_ATTRIBUTE_RESOLVER, ChainingResolverFactory);
 }
 
@@ -184,7 +187,7 @@ void ChainingAttributeResolver::resolveAttributes(ResolutionContext& ctx) const
         (*i)->resolveAttributes(*context.get());
 
         chain.m_attributes.insert(chain.m_attributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
-        chain.m_ownedAttributes.insert(chain.m_attributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
+        chain.m_ownedAttributes.insert(chain.m_ownedAttributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
         context->getResolvedAttributes().clear();
 
         chain.m_tokens.insert(chain.m_tokens.end(), context->getResolvedAssertions().begin(), context->getResolvedAssertions().end());
diff --git a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
new file mode 100644 (file)
index 0000000..d44311e
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *  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.
+ */
+
+/**
+ * DelegationAttributeExtractor.cpp
+ *
+ * AttributeExtractor for DelegationRestriction information.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "ServiceProvider.h"
+#include "attribute/ExtensibleAttribute.h"
+#include "attribute/resolver/AttributeExtractor.h"
+#include "util/SPConstants.h"
+
+#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class DelegationExtractor : public AttributeExtractor
+    {
+    public:
+        DelegationExtractor(const DOMElement* e);
+        ~DelegationExtractor() {}
+
+        Lockable* lock() {
+            return this;
+        }
+
+        void unlock() {
+        }
+
+        void extractAttributes(
+            const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+            ) const;
+
+        void getAttributeIds(std::vector<std::string>& attributes) const {
+            attributes.push_back(m_attributeId);
+        }
+
+    private:
+        string m_attributeId,m_formatter;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AttributeExtractor* SHIBSP_DLLLOCAL DelegationAttributeExtractorFactory(const DOMElement* const & e)
+    {
+        return new DelegationExtractor(e);
+    }
+
+    static const XMLCh attributeId[] =  UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
+    static const XMLCh formatter[] =    UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DelegationExtractor::DelegationExtractor(const DOMElement* e) : m_attributeId("delegate"), m_formatter("$Name")
+{
+    if (e) {
+        const XMLCh* a = e->getAttributeNS(NULL, attributeId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_attributeId = temp.get();
+        }
+        a = e->getAttributeNS(NULL, formatter);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_formatter = temp.get();
+        }
+    }
+}
+
+void DelegationExtractor::extractAttributes(
+    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+    ) const
+{
+    const saml2::Assertion* assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
+    if (!assertion || !assertion->getConditions())
+        return;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.Delegation");
+
+    const vector<saml2::Condition*>& conditions = const_cast<const saml2::Conditions*>(assertion->getConditions())->getConditions();
+    for (vector<saml2::Condition*>::const_iterator c = conditions.begin(); c != conditions.end(); ++c) {
+        const saml2::DelegationRestrictionType* drt = dynamic_cast<const saml2::DelegationRestrictionType*>(*c);
+        if (drt) {
+            auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
+
+            const vector<saml2::Delegate*>& dels = drt->getDelegates();
+            for (vector<saml2::Delegate*>::const_iterator d = dels.begin(); d != dels.end(); ++d) {
+                if ((*d)->getBaseID()) {
+                    log.error("delegate identified by saml:BaseID cannot be processed into an attribute value");
+                    continue;
+                }
+
+                saml2::NameID* n = NULL;
+                if ((*d)->getEncryptedID()) {
+                    CredentialResolver* cr = application.getCredentialResolver();
+                    if (!cr) {
+                        log.warn("found encrypted Delegate, but no CredentialResolver was available");
+                    }
+
+                    try {
+                        const XMLCh* recipient = application.getRelyingParty(
+                            issuer ? dynamic_cast<EntityDescriptor*>(issuer->getParent()) : NULL
+                            )->getXMLString("entityID").second;
+                        Locker credlocker(cr);
+                        if (issuer) {
+                            MetadataCredentialCriteria mcc(*issuer);
+                            auto_ptr<XMLObject> decrypted((*d)->getEncryptedID()->decrypt(*cr, recipient, &mcc));
+                            n = dynamic_cast<saml2::NameID*>(decrypted.release());
+                        }
+                        else {
+                            auto_ptr<XMLObject> decrypted((*d)->getEncryptedID()->decrypt(*cr, recipient));
+                            n = dynamic_cast<saml2::NameID*>(decrypted.release());
+                        }
+                        if (n && log.isDebugEnabled())
+                            log.debugStream() << "decrypted Delegate: " << *n << logging::eol;
+                    }
+                    catch (exception& ex) {
+                        log.error("caught exception decrypting Delegate: %s", ex.what());
+                    }
+                }
+                else {
+                    n = (*d)->getNameID();
+                }
+
+                if (n) {
+                    DDF val = DDF(NULL).structure();
+                    if ((*d)->getConfirmationMethod()) {
+                        auto_ptr_char temp((*d)->getConfirmationMethod());
+                        val.addmember("ConfirmationMethod").string(temp.get());
+                    }
+                    if ((*d)->getDelegationInstant()) {
+                        auto_ptr_char temp((*d)->getDelegationInstant()->getRawData());
+                        val.addmember("DelegationInstant").string(temp.get());
+                    }
+
+                    auto_arrayptr<char> name(toUTF8(n->getName()));\r
+                    if (name.get() && *name.get()) {\r
+                        val.addmember("Name").string(name.get());\r
+                        char* str = toUTF8(n->getFormat());\r
+                        if (str && *str)\r
+                            val.addmember("Format").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getNameQualifier());\r
+                        if (str && *str)\r
+                            val.addmember("NameQualifier").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getSPNameQualifier());\r
+                        if (str && *str)\r
+                            val.addmember("SPNameQualifier").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getSPProvidedID());\r
+                        if (str && *str)\r
+                            val.addmember("SPProvidedID").string(str);\r
+                        delete[] str;\r
+                    }\r
+
+                    if (n != (*d)->getNameID())
+                        delete n;
+
+                    if (val.integer())
+                        attr->getValues().add(val);
+                    else
+                        val.destroy();
+                }
+            }
+
+            attributes.push_back(attr.release());
+        }
+    }
+}
diff --git a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
new file mode 100644 (file)
index 0000000..d730b35
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  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.
+ */
+
+/**
+ * KeyDescriptorAttributeExtractor.cpp
+ *
+ * AttributeExtractor for KeyDescriptor information.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+#include "attribute/resolver/AttributeExtractor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class KeyDescriptorExtractor : public AttributeExtractor
+    {
+    public:
+        KeyDescriptorExtractor(const DOMElement* e);
+        ~KeyDescriptorExtractor() {}
+
+        Lockable* lock() {
+            return this;
+        }
+
+        void unlock() {
+        }
+
+        void extractAttributes(
+            const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+            ) const;
+
+        void getAttributeIds(std::vector<std::string>& attributes) const {
+            if (!m_hashId.empty())
+                attributes.push_back(m_hashId.front());
+            if (!m_signingId.empty())
+                attributes.push_back(m_signingId.front());
+            if (!m_encryptionId.empty())
+                attributes.push_back(m_encryptionId.front());
+        }
+
+    private:
+        vector<string> m_hashId;
+        vector<string> m_signingId;
+        vector<string> m_encryptionId;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AttributeExtractor* SHIBSP_DLLLOCAL KeyDescriptorAttributeExtractorFactory(const DOMElement* const & e)
+    {
+        return new KeyDescriptorExtractor(e);
+    }
+
+    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 signingId[] =    UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
+};
+
+KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e)
+{
+    if (e) {
+        const XMLCh* a = e->getAttributeNS(NULL, hashId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_hashId.push_back(temp.get());
+        }
+        a = e->getAttributeNS(NULL, signingId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_signingId.push_back(temp.get());
+        }
+        a = e->getAttributeNS(NULL, encryptionId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_encryptionId.push_back(temp.get());
+        }
+    }
+    if (m_hashId.empty() && m_signingId.empty() && m_encryptionId.empty())
+        throw ConfigurationException("KeyDescriptor AttributeExtractor requires hashId, signingId, or encryptionId property.");
+}
+
+void KeyDescriptorExtractor::extractAttributes(
+    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+    ) const
+{
+    const RoleDescriptor* role = dynamic_cast<const RoleDescriptor*>(&xmlObject);
+    if (!role)
+        return;
+
+    vector<const Credential*> creds;
+    MetadataCredentialCriteria mcc(*role);
+
+    if (!m_signingId.empty() || !m_hashId.empty()) {
+        mcc.setUsage(Credential::SIGNING_CREDENTIAL);
+        if (application.getMetadataProvider()->resolve(creds, &mcc)) {
+            if (!m_hashId.empty()) {
+                auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
+                vector<string>& vals = attr->getValues();
+                for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                    if (vals.empty() || !vals.back().empty())
+                        vals.push_back(string());
+                    vals.back() = SecurityHelper::getDEREncoding(*(*c), true);
+                }
+                if (vals.back().empty())
+                    vals.pop_back();
+                if (!vals.empty())
+                    attributes.push_back(attr.release());
+            }
+            if (!m_signingId.empty()) {
+                auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_signingId));
+                vector<string>& vals = attr->getValues();
+                for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                    if (vals.empty() || !vals.back().empty())
+                        vals.push_back(string());
+                    vals.back() = SecurityHelper::getDEREncoding(*(*c));
+                }
+                if (vals.back().empty())
+                    vals.pop_back();
+                if (!vals.empty())
+                    attributes.push_back(attr.release());
+            }
+            creds.clear();
+        }
+    }
+
+    if (!m_encryptionId.empty()) {
+        mcc.setUsage(Credential::ENCRYPTION_CREDENTIAL);
+        if (application.getMetadataProvider()->resolve(creds, &mcc)) {
+            auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_encryptionId));
+            vector<string>& vals = attr->getValues();
+            for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                if (vals.empty() || !vals.back().empty())
+                    vals.push_back(string());
+                vals.back() = SecurityHelper::getDEREncoding(*(*c));
+            }
+            if (vals.back().empty())
+                vals.pop_back();
+            if (!vals.empty())
+                attributes.push_back(attr.release());
+        }
+    }
+}
index e6e231e..ceff508 100644 (file)
@@ -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.
 #include <saml/saml1/binding/SAML1SOAPClient.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml1/core/Protocols.h>
-#include <saml/saml1/profile/AssertionValidator.h>
 #include <saml/saml2/binding/SAML2SOAPClient.h>
 #include <saml/saml2/core/Protocols.h>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
-#include <saml/saml2/profile/AssertionValidator.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -78,8 +76,7 @@ namespace shibsp {
             const NameID* nameid=NULL,
             const XMLCh* authncontext_class=NULL,
             const XMLCh* authncontext_decl=NULL,
-            const vector<const opensaml::Assertion*>* tokens=NULL,
-            const vector<Attribute*>* attributes=NULL
+            const vector<const opensaml::Assertion*>* tokens=NULL
             ) : m_query(true), m_app(application), m_session(NULL), m_metadata(NULL), m_entity(issuer),
                 m_protocol(protocol), m_nameid(nameid), m_class(authncontext_class), m_decl(authncontext_decl) {
 
@@ -188,7 +185,7 @@ namespace shibsp {
             const vector<const opensaml::Assertion*>* tokens=NULL,
             const vector<shibsp::Attribute*>* attributes=NULL
             ) const {
-            return new QueryContext(application,issuer,protocol,nameid,authncontext_class,authncontext_decl,tokens,attributes);
+            return new QueryContext(application,issuer,protocol,nameid,authncontext_class,authncontext_decl,tokens);
         }
 
         ResolutionContext* createResolutionContext(const Application& application, const Session& session) const {
@@ -206,6 +203,7 @@ namespace shibsp {
         bool SAML2Query(QueryContext& ctx) const;
 
         Category& m_log;
+        string m_policyId;
         vector<AttributeDesignator*> m_SAML1Designators;
         vector<saml2::Attribute*> m_SAML2Designators;
     };
@@ -215,6 +213,7 @@ namespace shibsp {
         return new QueryResolver(e);
     }
 
+    static const XMLCh _policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
 };
 
 QueryResolver::QueryResolver(const DOMElement* e) : m_log(Category::getInstance(SHIBSP_LOGCAT".AttributeResolver.Query"))
@@ -223,10 +222,16 @@ QueryResolver::QueryResolver(const DOMElement* e) : m_log(Category::getInstance(
     xmltooling::NDC ndc("QueryResolver");
 #endif
 
+    const XMLCh* pid = e ? e->getAttributeNS(NULL, _policyId) : NULL;
+    if (pid && *pid) {
+        auto_ptr_char temp(pid);
+        m_policyId = temp.get();
+    }
+
     DOMElement* child = XMLHelper::getFirstChildElement(e);
     while (child) {
         try {
-            if (XMLHelper::isNodeNamed(e, samlconstants::SAML20_NS, saml2::Attribute::LOCAL_NAME)) {
+            if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, saml2::Attribute::LOCAL_NAME)) {
                 auto_ptr<XMLObject> obj(saml2::AttributeBuilder::buildOneFromElement(child));
                 saml2::Attribute* down = dynamic_cast<saml2::Attribute*>(obj.get());
                 if (down) {
@@ -234,7 +239,7 @@ QueryResolver::QueryResolver(const DOMElement* e) : m_log(Category::getInstance(
                     obj.release();
                 }
             }
-            else if (XMLHelper::isNodeNamed(e, samlconstants::SAML1P_NS, AttributeDesignator::LOCAL_NAME)) {
+            else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1P_NS, AttributeDesignator::LOCAL_NAME)) {
                 auto_ptr<XMLObject> obj(AttributeDesignatorBuilder::buildOneFromElement(child));
                 AttributeDesignator* down = dynamic_cast<AttributeDesignator*>(obj.get());
                 if (down) {
@@ -266,7 +271,16 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const
 
     const Application& application = ctx.getApplication();
     const PropertySet* relyingParty = application.getRelyingParty(ctx.getEntityDescriptor());
-    shibsp::SecurityPolicy policy(application);
+
+    // Locate policy key.
+    const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
+
+    // Access policy properties.
+    const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId);
+    pair<bool,bool> validate = settings->getBool("validate");
+
+    shibsp::SecurityPolicy policy(application, NULL, validate.first && validate.second, policyId);
+    policy.getAudiences().push_back(relyingParty->getXMLString("entityID").second);
     MetadataCredentialCriteria mcc(*AA);
     shibsp::SOAPClient soaper(policy);
 
@@ -274,7 +288,7 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const
     saml1p::Response* response=NULL;
     const vector<AttributeService*>& endpoints=AA->getAttributeServices();
     for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) {
-        if (!XMLString::equals((*ep)->getBinding(),binding.get()))
+        if (!XMLString::equals((*ep)->getBinding(),binding.get()) || !(*ep)->getLocation())
             continue;
         auto_ptr_char loc((*ep)->getLocation());
         try {
@@ -344,13 +358,9 @@ bool QueryResolver::SAML1Query(QueryContext& ctx) const
         // Now we can check the security status of the policy.
         if (!policy.isAuthenticated())
             throw SecurityPolicyException("Security of SAML 1.x query result not established.");
-
-        // Lastly, check it over.
-        saml1::AssertionValidator tokval(relyingParty->getXMLString("entityID").second, application.getAudiences(), time(NULL));
-        tokval.validateAssertion(*newtoken);
     }
     catch (exception& ex) {
-        m_log.error("assertion failed policy/validation: %s", ex.what());
+        m_log.error("assertion failed policy validation: %s", ex.what());
         return true;
     }
 
@@ -396,19 +406,28 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const
     }
 
     const Application& application = ctx.getApplication();
-    shibsp::SecurityPolicy policy(application);
-    MetadataCredentialCriteria mcc(*AA);
-    shibsp::SOAPClient soaper(policy);
-
     const PropertySet* relyingParty = application.getRelyingParty(ctx.getEntityDescriptor());
+
+    // Locate policy key.
+    const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
+
+    // Access policy properties.
+    const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId);
+    pair<bool,bool> validate = settings->getBool("validate");
+
     pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
     pair<bool,const char*> encryption = relyingParty->getString("encryption");
 
+    shibsp::SecurityPolicy policy(application, NULL, validate.first && validate.second, policyId);
+    policy.getAudiences().push_back(relyingParty->getXMLString("entityID").second);
+    MetadataCredentialCriteria mcc(*AA);
+    shibsp::SOAPClient soaper(policy);
+
     auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
     saml2p::StatusResponseType* srt=NULL;
     const vector<AttributeService*>& endpoints=AA->getAttributeServices();
     for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !srt && ep!=endpoints.end(); ++ep) {
-        if (!XMLString::equals((*ep)->getBinding(),binding.get()))
+        if (!XMLString::equals((*ep)->getBinding(),binding.get())  || !(*ep)->getLocation())
             continue;
         auto_ptr_char loc((*ep)->getLocation());
         try {
@@ -495,13 +514,9 @@ bool QueryResolver::SAML2Query(QueryContext& ctx) const
         // Now we can check the security status of the policy.
         if (!policy.isAuthenticated())
             throw SecurityPolicyException("Security of SAML 2.0 query result not established.");
-
-        // Lastly, check it over.
-        saml2::AssertionValidator tokval(relyingParty->getXMLString("entityID").second, application.getAudiences(), time(NULL));
-        tokval.validateAssertion(*newtoken);
     }
     catch (exception& ex) {
-        m_log.error("assertion failed policy/validation: %s", ex.what());
+        m_log.error("assertion failed policy validation: %s", ex.what());
         return true;
     }
 
diff --git a/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp b/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
new file mode 100644 (file)
index 0000000..abd1cad
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ *  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.
+ */
+
+/**
+ * SimpleAggregationAttributeResolver.cpp
+ *
+ * AttributeResolver based on SAML queries to third-party AA sources.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "ServiceProvider.h"
+#include "SessionCache.h"
+#include "attribute/NameIDAttribute.h"
+#include "attribute/filtering/AttributeFilter.h"
+#include "attribute/filtering/BasicFilteringContext.h"
+#include "attribute/resolver/AttributeExtractor.h"
+#include "attribute/resolver/AttributeResolver.h"
+#include "attribute/resolver/ResolutionContext.h"
+#include "binding/SOAPClient.h"
+#include "metadata/MetadataProviderCriteria.h"
+#include "util/SPConstants.h"
+
+#include <saml/exceptions.h>
+#include <saml/SAMLConfig.h>
+#include <saml/binding/SecurityPolicy.h>
+#include <saml/saml2/binding/SAML2SOAPClient.h>
+#include <saml/saml2/core/Protocols.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2;
+using namespace opensaml::saml2p;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+    class SHIBSP_DLLLOCAL SimpleAggregationContext : public ResolutionContext
+    {
+    public:
+        SimpleAggregationContext(const Application& application, const Session& session)
+            : m_app(application),
+              m_session(&session),
+              m_nameid(NULL),
+              m_class(XMLString::transcode(session.getAuthnContextClassRef())),
+              m_decl(XMLString::transcode(session.getAuthnContextDeclRef())),
+              m_inputTokens(NULL),
+              m_inputAttributes(NULL) {
+        }
+
+        SimpleAggregationContext(
+            const Application& application,
+            const NameID* nameid=NULL,
+            const XMLCh* authncontext_class=NULL,
+            const XMLCh* authncontext_decl=NULL,
+            const vector<const opensaml::Assertion*>* tokens=NULL,
+            const vector<shibsp::Attribute*>* attributes=NULL
+            ) : m_app(application),
+                m_session(NULL),
+                m_nameid(nameid),
+                m_class(const_cast<XMLCh*>(authncontext_class)),
+                m_decl(const_cast<XMLCh*>(authncontext_decl)),
+                m_inputTokens(tokens),
+                m_inputAttributes(attributes) {
+        }
+
+        ~SimpleAggregationContext() {
+            for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<shibsp::Attribute>());
+            for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup<opensaml::Assertion>());
+            if (m_session) {
+                XMLString::release(&m_class);
+                XMLString::release(&m_decl);
+            }
+        }
+
+        const Application& getApplication() const {
+            return m_app;
+        }
+        const NameID* getNameID() const {
+            return m_session ? m_session->getNameID() : m_nameid;
+        }
+        const XMLCh* getClassRef() const {
+            return m_class;
+        }
+        const XMLCh* getDeclRef() const {
+            return m_decl;
+        }
+        const Session* getSession() const {
+            return m_session;
+        }
+        const vector<shibsp::Attribute*>* getInputAttributes() const {
+            return m_inputAttributes;
+        }
+        const vector<const opensaml::Assertion*>* getInputTokens() const {
+            return m_inputTokens;
+        }
+        vector<shibsp::Attribute*>& getResolvedAttributes() {
+            return m_attributes;
+        }
+        vector<opensaml::Assertion*>& getResolvedAssertions() {
+            return m_assertions;
+        }
+
+    private:
+        const Application& m_app;
+        const Session* m_session;
+        const NameID* m_nameid;
+        XMLCh* m_class;
+        XMLCh* m_decl;
+        const vector<const opensaml::Assertion*>* m_inputTokens;
+        const vector<shibsp::Attribute*>* m_inputAttributes;
+        vector<shibsp::Attribute*> m_attributes;
+        vector<opensaml::Assertion*> m_assertions;
+    };
+
+    class SHIBSP_DLLLOCAL SimpleAggregationResolver : public AttributeResolver
+    {
+    public:
+        SimpleAggregationResolver(const DOMElement* e);
+        ~SimpleAggregationResolver() {
+            delete m_trust;
+            delete m_metadata;
+            for_each(m_designators.begin(), m_designators.end(), xmltooling::cleanup<saml2::Attribute>());
+        }
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        ResolutionContext* createResolutionContext(
+            const Application& application,
+            const EntityDescriptor* issuer,
+            const XMLCh* protocol,
+            const NameID* nameid=NULL,
+            const XMLCh* authncontext_class=NULL,
+            const XMLCh* authncontext_decl=NULL,
+            const vector<const opensaml::Assertion*>* tokens=NULL,
+            const vector<shibsp::Attribute*>* attributes=NULL
+            ) const {
+            return new SimpleAggregationContext(application,nameid,authncontext_class,authncontext_decl,tokens,attributes);
+        }
+
+        ResolutionContext* createResolutionContext(const Application& application, const Session& session) const {
+            return new SimpleAggregationContext(application,session);
+        }
+
+        void resolveAttributes(ResolutionContext& ctx) const;
+
+        void getAttributeIds(vector<string>& attributes) const {
+            // Nothing to do, only the extractor would actually generate them.
+        }
+
+    private:
+        bool doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const;
+
+        Category& m_log;
+        string m_policyId;
+        vector<string> m_attributeIds;
+        xstring m_format;
+        MetadataProvider* m_metadata;
+        TrustEngine* m_trust;
+        vector<saml2::Attribute*> m_designators;
+        vector< pair<string,bool> > m_sources;
+    };
+
+    AttributeResolver* SHIBSP_DLLLOCAL SimpleAggregationResolverFactory(const DOMElement* const & e)
+    {
+        return new SimpleAggregationResolver(e);
+    }
+
+    static const XMLCh attributeId[] =          UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
+    static const XMLCh Entity[] =               UNICODE_LITERAL_6(E,n,t,i,t,y);
+    static const XMLCh EntityReference[] =      UNICODE_LITERAL_15(E,n,t,i,t,y,R,e,f,e,r,e,n,c,e);
+    static const XMLCh format[] =               UNICODE_LITERAL_6(f,o,r,m,a,t);
+    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 policyId[] =             UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
+    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);
+};
+
+SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e)
+    : m_log(Category::getInstance(SHIBSP_LOGCAT".AttributeResolver.SimpleAggregation")), m_metadata(NULL), m_trust(NULL)
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("SimpleAggregationResolver");
+#endif
+
+    const XMLCh* pid = e ? e->getAttributeNS(NULL, policyId) : NULL;
+    if (pid && *pid) {
+        auto_ptr_char temp(pid);
+        m_policyId = temp.get();
+    }
+
+    pid = e ? e->getAttributeNS(NULL, attributeId) : NULL;
+    if (pid && *pid) {
+        char* dup = XMLString::transcode(pid);
+        char* pos;
+        char* start = dup;
+        while (start && *start) {
+            while (*start && isspace(*start))
+                start++;
+            if (!*start)
+                break;
+            pos = strchr(start,' ');
+            if (pos)
+                *pos=0;
+            m_attributeIds.push_back(start);
+            start = pos ? pos+1 : NULL;
+        }
+        XMLString::release(&dup);
+
+        pid = e->getAttributeNS(NULL, format);
+        if (pid && *pid)
+            m_format = pid;
+
+    }
+
+    DOMElement* child = XMLHelper::getFirstChildElement(e, _MetadataProvider);
+    if (child) {
+        auto_ptr_char type(child->getAttributeNS(NULL, _type));
+        if (!type.get() || !*type.get())
+            throw ConfigurationException("MetadataProvider element missing type attribute.");
+        m_log.info("building MetadataProvider of type %s...", type.get());
+        auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(type.get(), child));
+        mp->init();
+        m_metadata = mp.release();
+    }
+
+    child = XMLHelper::getFirstChildElement(e,  _TrustEngine);
+    if (child) {
+        try {
+            auto_ptr_char type(child->getAttributeNS(NULL, _type));
+            if (!type.get() || !*type.get())
+                throw ConfigurationException("TrustEngine element missing type attribute.");
+            m_log.info("building TrustEngine of type %s...", type.get());
+            m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(type.get(), child);
+        }
+        catch (exception&) {
+            delete m_metadata;
+            throw;
+        }
+    }
+
+    child = XMLHelper::getFirstChildElement(e);
+    while (child) {
+        if (child->hasChildNodes() && XMLString::equals(child->getLocalName(), Entity)) {
+            pid = child->getFirstChild()->getNodeValue();
+            if (pid && *pid) {
+                auto_ptr_char tpid(pid);
+                m_sources.push_back(pair<string,bool>(tpid.get(),true));
+            }
+        }
+        else if (child->hasChildNodes() && XMLString::equals(child->getLocalName(), EntityReference)) {
+            pid = child->getFirstChild()->getNodeValue();
+            if (pid && *pid) {
+                auto_ptr_char tpid(pid);
+                m_sources.push_back(pair<string,bool>(tpid.get(),false));
+            }
+        }
+        else if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, saml2::Attribute::LOCAL_NAME)) {
+            try {
+                auto_ptr<XMLObject> obj(saml2::AttributeBuilder::buildOneFromElement(child));
+                saml2::Attribute* down = dynamic_cast<saml2::Attribute*>(obj.get());
+                if (down) {
+                    m_designators.push_back(down);
+                    obj.release();
+                }
+            }
+            catch (exception& ex) {
+                m_log.error("exception loading attribute designator: %s", ex.what());
+            }
+        }
+        child = XMLHelper::getNextSiblingElement(child);
+    }
+
+}
+
+bool SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("doQuery");
+#endif
+    const Application& application = ctx.getApplication();
+    MetadataProviderCriteria mc(application, entityID, &AttributeAuthorityDescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
+    Locker mlocker(m_metadata);
+    const AttributeAuthorityDescriptor* AA=NULL;
+    pair<const EntityDescriptor*,const RoleDescriptor*> mdresult =
+        (m_metadata ? m_metadata : application.getMetadataProvider())->getEntityDescriptor(mc);
+    if (!mdresult.first) {
+        m_log.warn("unable to locate metadata for provider (%s)", entityID);
+        return false;
+    }
+    else if (!(AA=dynamic_cast<const AttributeAuthorityDescriptor*>(mdresult.second))) {
+        m_log.warn("no SAML 2 AttributeAuthority role found in metadata for (%s)", entityID);
+        return false;
+    }
+
+    const PropertySet* relyingParty = application.getRelyingParty(mdresult.first);
+
+    // Locate policy key.
+    const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
+
+    // Access policy properties.
+    const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId);
+    pair<bool,bool> validate = settings->getBool("validate");
+
+    pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
+    pair<bool,const char*> encryption = relyingParty->getString("encryption");
+
+    shibsp::SecurityPolicy policy(application, NULL, validate.first && validate.second, policyId);
+    if (m_metadata)
+        policy.setMetadataProvider(m_metadata);
+    if (m_trust)
+        policy.setTrustEngine(m_trust);
+    policy.getAudiences().push_back(relyingParty->getXMLString("entityID").second);
+
+    MetadataCredentialCriteria mcc(*AA);
+    shibsp::SOAPClient soaper(policy);
+
+    auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
+    saml2p::StatusResponseType* srt=NULL;
+    const vector<AttributeService*>& endpoints=AA->getAttributeServices();
+    for (vector<AttributeService*>::const_iterator ep=endpoints.begin(); !srt && ep!=endpoints.end(); ++ep) {
+        if (!XMLString::equals((*ep)->getBinding(),binding.get())  || !(*ep)->getLocation())
+            continue;
+        auto_ptr_char loc((*ep)->getLocation());
+        try {
+            auto_ptr<saml2::Subject> subject(saml2::SubjectBuilder::buildSubject());
+
+            // Encrypt the NameID?
+            if (encryption.first && (!strcmp(encryption.second, "true") || !strcmp(encryption.second, "back"))) {
+                auto_ptr<EncryptedID> encrypted(EncryptedIDBuilder::buildEncryptedID());
+                MetadataCredentialCriteria mcc(*AA);
+                encrypted->encrypt(
+                    *name,
+                    *(policy.getMetadataProvider()),
+                    mcc,
+                    false,
+                    relyingParty->getXMLString("encryptionAlg").second
+                    );
+                subject->setEncryptedID(encrypted.release());
+            }
+            else {
+                subject->setNameID(name->cloneNameID());
+            }
+
+            saml2p::AttributeQuery* query = saml2p::AttributeQueryBuilder::buildAttributeQuery();
+            query->setSubject(subject.release());
+            Issuer* iss = IssuerBuilder::buildIssuer();
+            iss->setName(relyingParty->getXMLString("entityID").second);
+            query->setIssuer(iss);
+            for (vector<saml2::Attribute*>::const_iterator ad = m_designators.begin(); ad!=m_designators.end(); ++ad)
+                query->getAttributes().push_back((*ad)->cloneAttribute());
+
+            SAML2SOAPClient client(soaper, false);
+            client.sendSAML(query, application.getId(), mcc, loc.get());
+            srt = client.receiveSAML();
+        }
+        catch (exception& ex) {
+            m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
+            soaper.reset();
+        }
+    }
+
+    if (!srt) {
+        m_log.error("unable to obtain a SAML response from attribute authority (%s)", entityID);
+        return false;
+    }
+    saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt);
+    if (!response) {
+        delete srt;
+        m_log.error("message was not a samlp:Response");
+        return true;
+    }
+    else if (!response->getStatus() || !response->getStatus()->getStatusCode() ||
+            !XMLString::equals(response->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
+        delete srt;
+        m_log.error("attribute authority (%s) returned a SAML error", entityID);
+        return true;
+    }
+
+    const vector<saml2::Assertion*>& assertions = const_cast<const saml2p::Response*>(response)->getAssertions();
+    if (assertions.empty()) {
+        delete srt;
+        m_log.warn("response from attribute authority (%s) was empty", entityID);
+        return true;
+    }
+    else if (assertions.size()>1)
+        m_log.warn("resolver only supports one assertion in the query response");
+
+    auto_ptr<saml2p::StatusResponseType> wrapper(srt);
+    saml2::Assertion* newtoken = assertions.front();
+
+    if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
+        m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
+        return true;
+    }
+
+    try {
+        // We're going to insist that the assertion issuer is the same as the peer.
+        // Reset the policy's message bits and extract them from the assertion.
+        policy.reset(true);
+        policy.setMessageID(newtoken->getID());
+        policy.setIssueInstant(newtoken->getIssueInstantEpoch());
+        policy.setIssuer(newtoken->getIssuer());
+        policy.evaluate(*newtoken);
+
+        // Now we can check the security status of the policy.
+        if (!policy.isAuthenticated())
+            throw SecurityPolicyException("Security of SAML 2.0 query result not established.");
+    }
+    catch (exception& ex) {
+        m_log.error("assertion failed policy validation: %s", ex.what());
+        return true;
+    }
+
+    newtoken->detach();
+    wrapper.release();
+    ctx.getResolvedAssertions().push_back(newtoken);
+
+    // Finally, extract and filter the result.
+    try {
+        AttributeExtractor* extractor = application.getAttributeExtractor();
+        if (extractor) {
+            Locker extlocker(extractor);
+            extractor->extractAttributes(application, AA, *newtoken, ctx.getResolvedAttributes());
+        }
+
+        AttributeFilter* filter = application.getAttributeFilter();
+        if (filter) {
+            BasicFilteringContext fc(application, ctx.getResolvedAttributes(), AA, ctx.getClassRef(), ctx.getDeclRef());
+            Locker filtlocker(filter);
+            filter->filterAttributes(fc, ctx.getResolvedAttributes());
+        }
+    }
+    catch (exception& ex) {
+        m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
+        for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
+        ctx.getResolvedAttributes().clear();
+    }
+
+    return true;
+}
+
+void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("resolveAttributes");
+#endif
+
+    SimpleAggregationContext& qctx = dynamic_cast<SimpleAggregationContext&>(ctx);
+
+    // First we manufacture the appropriate NameID to use.
+    NameID* n=NULL;
+    for (vector<string>::const_iterator a = m_attributeIds.begin(); !n && a != m_attributeIds.end(); ++a) {
+        const Attribute* attr=NULL;
+        if (qctx.getSession()) {
+            // Input attributes should be available via multimap.
+            pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> range =
+                qctx.getSession()->getIndexedAttributes().equal_range(*a);
+            for (; !attr && range.first != range.second; ++range.first) {
+                if (range.first->second->valueCount() > 0)
+                    attr = range.first->second;
+            }
+        }
+        else if (qctx.getInputAttributes()) {
+            // Have to loop over unindexed set.
+            const vector<Attribute*>* matches = qctx.getInputAttributes();
+            for (vector<Attribute*>::const_iterator match = matches->begin(); !attr && match != matches->end(); ++match) {
+                if (*a == (*match)->getId() && (*match)->valueCount() > 0)
+                    attr = *match;
+            }
+        }
+
+        if (attr) {
+            m_log.debug("using input attribute (%s) as identifier for queries", attr->getId());
+            n = NameIDBuilder::buildNameID();
+            const NameIDAttribute* down = dynamic_cast<const NameIDAttribute*>(attr);
+            if (down) {
+                // We can create a NameID directly from the source material.
+                const NameIDAttribute::Value& v = down->getValues().front();
+                XMLCh* val = fromUTF8(v.m_Name.c_str());
+                n->setName(val);
+                delete[] val;
+                if (!v.m_Format.empty()) {
+                    val = fromUTF8(v.m_Format.c_str());
+                    n->setFormat(val);
+                    delete[] val;
+                }
+                if (!v.m_NameQualifier.empty()) {
+                    val = fromUTF8(v.m_NameQualifier.c_str());
+                    n->setNameQualifier(val);
+                    delete[] val;
+                }
+                if (!v.m_SPNameQualifier.empty()) {
+                    val = fromUTF8(v.m_SPNameQualifier.c_str());
+                    n->setSPNameQualifier(val);
+                    delete[] val;
+                }
+                if (!v.m_SPProvidedID.empty()) {
+                    val = fromUTF8(v.m_SPProvidedID.c_str());
+                    n->setSPProvidedID(val);
+                    delete[] val;
+                }
+            }
+            else {
+                // We have to mock up the NameID.
+                XMLCh* val = fromUTF8(attr->getSerializedValues().front().c_str());
+                n->setName(val);
+                delete[] val;
+                if (!m_format.empty())
+                    n->setFormat(m_format.c_str());
+            }
+        }
+    }
+
+    if (!n) {
+        if (qctx.getNameID() && m_attributeIds.empty()) {
+            m_log.debug("using authenticated NameID as identifier for queries");
+        }
+        else {
+            m_log.warn("unable to resolve attributes, no suitable query identifier found");
+            return;
+        }
+    }
+
+    auto_ptr<NameID> wrapper(n);
+
+    set<string> history;
+
+    // We have a master loop over all the possible sources of material.
+    for (vector< pair<string,bool> >::const_iterator source = m_sources.begin(); source != m_sources.end(); ++source) {
+        if (source->second) {
+            // A literal entityID to query.
+            if (history.count(source->first) == 0) {
+                m_log.debug("issuing SAML query to (%s)", source->first.c_str());
+                doQuery(qctx, source->first.c_str(), n ? n : qctx.getNameID());
+                history.insert(source->first);
+            }
+            else {
+                m_log.debug("skipping previously queried attribute source (%s)", source->first.c_str());
+            }
+        }
+        else {
+            m_log.debug("using attribute sources referenced in attribute (%s)", source->first.c_str());
+            if (qctx.getSession()) {
+                // Input attributes should be available via multimap.
+                pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> range =
+                    qctx.getSession()->getIndexedAttributes().equal_range(source->first);
+                for (; range.first != range.second; ++range.first) {
+                    const vector<string>& links = range.first->second->getSerializedValues();
+                    for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
+                        if (history.count(*link) == 0) {
+                            m_log.debug("issuing SAML query to (%s)", link->c_str());
+                            doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+                            history.insert(*link);
+                        }
+                        else {
+                            m_log.debug("skipping previously queried attribute source (%s)", link->c_str());
+                        }
+                    }
+                }
+            }
+            else if (qctx.getInputAttributes()) {
+                // Have to loop over unindexed set.
+                const vector<Attribute*>* matches = qctx.getInputAttributes();
+                for (vector<Attribute*>::const_iterator match = matches->begin(); match != matches->end(); ++match) {
+                    if (source->first == (*match)->getId()) {
+                        const vector<string>& links = (*match)->getSerializedValues();
+                        for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
+                            if (history.count(*link) == 0) {
+                                m_log.debug("issuing SAML query to (%s)", link->c_str());
+                                doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+                                history.insert(*link);
+                            }
+                            else {
+                                m_log.debug("skipping previously queried attribute source (%s)", link->c_str());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
index eeead9f..c27df80 100644 (file)
@@ -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.
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "attribute/AttributeDecoder.h"
+#include "attribute/filtering/AttributeFilter.h"
+#include "attribute/filtering/BasicFilteringContext.h"
 #include "attribute/resolver/AttributeExtractor.h"
+#include "security/SecurityPolicy.h"
 #include "util/SPConstants.h"
 
+#include <saml/SAMLConfig.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/core/Assertions.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/saml2/metadata/ObservableMetadataProvider.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/XMLHelper.h>
@@ -51,13 +56,22 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class XMLExtractorImpl
+    class XMLExtractorImpl : public ObservableMetadataProvider::Observer
     {
     public:
         XMLExtractorImpl(const DOMElement* e, Category& log);
         ~XMLExtractorImpl() {
-            for (attrmap_t::iterator i = m_attrMap.begin(); i!=m_attrMap.end(); ++i)
-                delete i->second.first;
+            for (map<const ObservableMetadataProvider*,decoded_t>::iterator i=m_decodedMap.begin(); i!=m_decodedMap.end(); ++i) {
+                i->first->removeObserver(this);
+                for (decoded_t::iterator attrs = i->second.begin(); attrs!=i->second.end(); ++attrs)
+                    for_each(attrs->second.begin(), attrs->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
+            }
+            delete m_attrLock;
+            delete m_trust;
+            delete m_metadata;
+            delete m_filter;
+            for (attrmap_t::iterator j = m_attrMap.begin(); j!=m_attrMap.end(); ++j)
+                delete j->second.first;
             if (m_document)
                 m_document->release();
         }
@@ -66,20 +80,51 @@ namespace shibsp {
             m_document = doc;
         }
 
+        void onEvent(const ObservableMetadataProvider& metadata) const {
+            // Destroy attributes we cached from this provider.
+            m_attrLock->wrlock();
+            decoded_t& d = m_decodedMap[&metadata];
+            for (decoded_t::iterator a = d.begin(); a!=d.end(); ++a)
+                for_each(a->second.begin(), a->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
+            d.clear();
+            m_attrLock->unlock();
+        }
+
         void extractAttributes(
-            const Application& application, const char* assertingParty, const NameIdentifier& nameid, vector<Attribute*>& attributes
+            const Application& application,
+            const char* assertingParty,
+            const char* relyingParty,
+            const NameIdentifier& nameid,
+            vector<Attribute*>& attributes
             ) const;
         void extractAttributes(
-            const Application& application, const char* assertingParty, const NameID& nameid, vector<Attribute*>& attributes
+            const Application& application,
+            const char* assertingParty,
+            const char* relyingParty,
+            const NameID& nameid,
+            vector<Attribute*>& attributes
             ) const;
         void extractAttributes(
-            const Application& application, const char* assertingParty, const saml1::Attribute& attr, vector<Attribute*>& attributes
+            const Application& application,
+            const char* assertingParty,
+            const char* relyingParty,
+            const saml1::Attribute& attr,
+            vector<Attribute*>& attributes
             ) const;
         void extractAttributes(
-            const Application& application, const char* assertingParty, const saml2::Attribute& attr, vector<Attribute*>& attributes
+            const Application& application,
+            const char* assertingParty,
+            const char* relyingParty,
+            const saml2::Attribute& attr,
+            vector<Attribute*>& attributes
             ) const;
         void extractAttributes(
-            const Application& application, const char* assertingParty, const Extensions& ext, vector<Attribute*>& attributes
+            const Application& application,
+            const ObservableMetadataProvider* observable,
+            const XMLCh* entityID,
+            const char* relyingParty,
+            const Extensions& ext,
+            vector<Attribute*>& attributes
             ) const;
 
         void getAttributeIds(vector<string>& attributes) const {
@@ -96,6 +141,18 @@ namespace shibsp {
 #endif
         attrmap_t m_attrMap;
         vector<string> m_attributeIds;
+
+        // settings for embedded assertions in metadata
+        auto_ptr_char m_policyId;
+        MetadataProvider* m_metadata;
+        TrustEngine* m_trust;
+        AttributeFilter* m_filter;
+        bool m_entityAssertions;
+
+        // manages caching of decoded Attributes
+        mutable RWLock* m_attrLock;
+        typedef map< const EntityAttributes*,vector<DDF> > decoded_t;
+        mutable map<const ObservableMetadataProvider*,decoded_t> m_decodedMap;
     };
 
     class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile
@@ -133,15 +190,28 @@ namespace shibsp {
         return new XMLExtractor(e);
     }
 
+    static const XMLCh _aliases[] =             UNICODE_LITERAL_7(a,l,i,a,s,e,s);
     static const XMLCh _AttributeDecoder[] =    UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,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 Attributes[] =           UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);
     static const XMLCh _id[] =                  UNICODE_LITERAL_2(i,d);
-    static const XMLCh _aliases[] =             UNICODE_LITERAL_7(a,l,i,a,s,e,s);
+    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 _name[] =                UNICODE_LITERAL_4(n,a,m,e);
     static const XMLCh nameFormat[] =           UNICODE_LITERAL_10(n,a,m,e,F,o,r,m,a,t);
+    static const XMLCh metadataPolicyId[] =     UNICODE_LITERAL_16(m,e,t,a,d,a,t,a,P,o,l,i,c,y,I,d);
+    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);
 };
 
-XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(log), m_document(NULL)
+XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
+    : m_log(log),
+        m_document(NULL),
+        m_policyId(e ? e->getAttributeNS(NULL, metadataPolicyId) : NULL),
+        m_metadata(NULL),
+        m_trust(NULL),
+        m_filter(NULL),
+        m_entityAssertions(true),
+        m_attrLock(NULL)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("XMLExtractorImpl");
@@ -150,7 +220,61 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l
     if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, Attributes))
         throw ConfigurationException("XML AttributeExtractor requires am:Attributes at root of configuration.");
 
-    DOMElement* child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+    DOMElement* child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _MetadataProvider);
+    if (child) {
+        try {
+            auto_ptr_char type(child->getAttributeNS(NULL, _type));
+            if (!type.get() || !*type.get())
+                throw ConfigurationException("MetadataProvider element missing type attribute.");
+            m_log.info("building MetadataProvider of type %s...", type.get());
+            auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(type.get(), child));
+            mp->init();
+            m_metadata = mp.release();
+        }
+        catch (exception& ex) {
+            m_entityAssertions = false;
+            m_log.crit("error building/initializing dedicated MetadataProvider: %s", ex.what());
+            m_log.crit("disabling support for Assertions in EntityAttributes extension");
+        }
+    }
+
+    if (m_entityAssertions) {
+        child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _TrustEngine);
+        if (child) {
+            try {
+                auto_ptr_char type(child->getAttributeNS(NULL, _type));
+                if (!type.get() || !*type.get())
+                    throw ConfigurationException("TrustEngine element missing type attribute.");
+                m_log.info("building TrustEngine of type %s...", type.get());
+                m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(type.get(), child);
+            }
+            catch (exception& ex) {
+                m_entityAssertions = false;
+                m_log.crit("error building/initializing dedicated TrustEngine: %s", ex.what());
+                m_log.crit("disabling support for Assertions in EntityAttributes extension");
+            }
+        }
+    }
+
+    if (m_entityAssertions) {
+        child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeFilter);
+        if (child) {
+            try {
+                auto_ptr_char type(child->getAttributeNS(NULL, _type));
+                if (!type.get() || !*type.get())
+                    throw ConfigurationException("AttributeFilter element missing type attribute.");
+                m_log.info("building AttributeFilter of type %s...", type.get());
+                m_filter = SPConfig::getConfig().AttributeFilterManager.newPlugin(type.get(), child);
+            }
+            catch (exception& ex) {
+                m_entityAssertions = false;
+                m_log.crit("error building/initializing dedicated AttributeFilter: %s", ex.what());
+                m_log.crit("disabling support for Assertions in EntityAttributes extension");
+            }
+        }
+    }
+
+    child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
     while (child) {
         // Check for missing name or id.
         const XMLCh* name = child->getAttributeNS(NULL, _name);
@@ -176,7 +300,7 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l
         try {
             DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);
             if (dchild) {
-                auto_ptr<QName> q(XMLHelper::getXSIType(dchild));
+                auto_ptr<xmltooling::QName> q(XMLHelper::getXSIType(dchild));
                 if (q.get())
                     decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild);
             }
@@ -251,10 +375,16 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l
 
         child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
     }
+
+    m_attrLock = RWLock::create();
 }
 
 void XMLExtractorImpl::extractAttributes(
-    const Application& application, const char* assertingParty, const NameIdentifier& nameid, vector<Attribute*>& attributes
+    const Application& application,
+    const char* assertingParty,
+    const char* relyingParty,
+    const NameIdentifier& nameid,
+    vector<Attribute*>& attributes
     ) const
 {
 #ifdef HAVE_GOOD_STL
@@ -272,7 +402,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp(format);
     if ((rule=m_attrMap.find(pair<string,string>(temp.get(),string()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
         if (a)
             attributes.push_back(a);
     }
@@ -285,7 +415,11 @@ void XMLExtractorImpl::extractAttributes(
 }
 
 void XMLExtractorImpl::extractAttributes(
-    const Application& application, const char* assertingParty, const NameID& nameid, vector<Attribute*>& attributes
+    const Application& application,
+    const char* assertingParty,
+    const char* relyingParty,
+    const NameID& nameid,
+    vector<Attribute*>& attributes
     ) const
 {
 #ifdef HAVE_GOOD_STL
@@ -303,7 +437,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp(format);
     if ((rule=m_attrMap.find(pair<string,string>(temp.get(),string()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
         if (a)
             attributes.push_back(a);
     }
@@ -316,7 +450,11 @@ void XMLExtractorImpl::extractAttributes(
 }
 
 void XMLExtractorImpl::extractAttributes(
-    const Application& application, const char* assertingParty, const saml1::Attribute& attr, vector<Attribute*>& attributes
+    const Application& application,
+    const char* assertingParty,
+    const char* relyingParty,
+    const saml1::Attribute& attr,
+    vector<Attribute*>& attributes
     ) const
 {
 #ifdef HAVE_GOOD_STL
@@ -338,7 +476,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp2(format);
     if ((rule=m_attrMap.find(pair<string,string>(temp1.get(),temp2.get()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
         if (a)
             attributes.push_back(a);
     }
@@ -352,7 +490,11 @@ void XMLExtractorImpl::extractAttributes(
 }
 
 void XMLExtractorImpl::extractAttributes(
-    const Application& application, const char* assertingParty, const saml2::Attribute& attr, vector<Attribute*>& attributes
+    const Application& application,
+    const char* assertingParty,
+    const char* relyingParty,
+    const saml2::Attribute& attr,
+    vector<Attribute*>& attributes
     ) const
 {
 #ifdef HAVE_GOOD_STL
@@ -376,7 +518,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp2(format);
     if ((rule=m_attrMap.find(pair<string,string>(temp1.get(),temp2.get()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
         if (a)
             attributes.push_back(a);
     }
@@ -390,14 +532,246 @@ void XMLExtractorImpl::extractAttributes(
 }
 
 void XMLExtractorImpl::extractAttributes(
-    const Application& application, const char* assertingParty, const Extensions& ext, vector<Attribute*>& attributes
+    const Application& application,
+    const ObservableMetadataProvider* observable,
+    const XMLCh* entityID,
+    const char* relyingParty,
+    const Extensions& ext,
+    vector<Attribute*>& attributes
     ) const
 {
-    const vector<XMLObject*> exts = ext.getUnknownXMLObjects();
+    const vector<XMLObject*>& exts = ext.getUnknownXMLObjects();
     for (vector<XMLObject*>::const_iterator i = exts.begin(); i!=exts.end(); ++i) {
-        const saml2::Attribute* attr = dynamic_cast<const saml2::Attribute*>(*i);
-        if (attr)
-            extractAttributes(application, assertingParty, *attr, attributes);
+        const EntityAttributes* container = dynamic_cast<const EntityAttributes*>(*i);
+        if (!container)
+            continue;
+
+        bool useCache = false;
+        map<const ObservableMetadataProvider*,decoded_t>::iterator cacheEntry;
+
+        // Check for cached result.
+        if (observable) {
+            m_attrLock->rdlock();
+            cacheEntry = m_decodedMap.find(observable);
+            if (cacheEntry == m_decodedMap.end()) {
+                // We need to elevate the lock and retry.
+                m_attrLock->unlock();
+                m_attrLock->wrlock();
+                cacheEntry = m_decodedMap.find(observable);
+                if (cacheEntry==m_decodedMap.end()) {
+
+                    // It's still brand new, so hook it for cache activation.
+                    observable->addObserver(this);
+
+                    // Prime the map reference with an empty decoded map.
+                    cacheEntry = m_decodedMap.insert(make_pair(observable,decoded_t())).first;
+
+                    // Downgrade the lock.
+                    // We don't have to recheck because we never erase the master map entry entirely, even on changes.
+                    m_attrLock->unlock();
+                    m_attrLock->rdlock();
+                }
+            }
+            useCache = true;
+        }
+
+        if (useCache) {
+            // We're holding a read lock, so check the cache.
+            decoded_t::iterator d = cacheEntry->second.find(container);
+            if (d != cacheEntry->second.end()) {
+                SharedLock locker(m_attrLock, false);   // pop the lock when we're done
+                for (vector<DDF>::iterator obj = d->second.begin(); obj != d->second.end(); ++obj) {
+                    auto_ptr<Attribute> wrapper(Attribute::unmarshall(*obj));
+                    m_log.debug("recovered cached metadata attribute (%s)", wrapper->getId());
+                    attributes.push_back(wrapper.release());
+                }
+                break;
+            }
+        }
+
+        // Use a holding area to support caching.
+        vector<Attribute*> holding;
+
+        const vector<saml2::Attribute*>& attrs = container->getAttributes();
+        for (vector<saml2::Attribute*>::const_iterator attr = attrs.begin(); attr != attrs.end(); ++attr) {
+            try {
+                extractAttributes(application, NULL, relyingParty, *(*attr), holding);
+            }
+            catch (...) {
+                if (useCache)
+                    m_attrLock->unlock();
+                for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
+                throw;
+            }
+        }
+
+        if (entityID && m_entityAssertions) {
+            const vector<saml2::Assertion*>& asserts = container->getAssertions();
+            for (vector<saml2::Assertion*>::const_iterator assert = asserts.begin(); assert != asserts.end(); ++assert) {
+                if (!(*assert)->getSignature()) {
+                    if (m_log.isDebugEnabled()) {
+                        auto_ptr_char eid(entityID);
+                        m_log.debug("skipping unsigned assertion in metadata extension for entity (%s)", eid.get());
+                    }
+                    continue;
+                }
+                else if ((*assert)->getAttributeStatements().empty()) {
+                    if (m_log.isDebugEnabled()) {
+                        auto_ptr_char eid(entityID);
+                        m_log.debug("skipping assertion with no AttributeStatement in metadata extension for entity (%s)", eid.get());
+                    }
+                    continue;
+                }
+                else {
+                    // Check subject.
+                    const NameID* subject = (*assert)->getSubject() ? (*assert)->getSubject()->getNameID() : NULL;
+                    if (!subject ||
+                            !XMLString::equals(subject->getFormat(), NameID::ENTITY) ||
+                            !XMLString::equals(subject->getName(), entityID)) {
+                        if (m_log.isDebugEnabled()) {
+                            auto_ptr_char eid(entityID);
+                            m_log.debug("skipping assertion with improper Subject in metadata extension for entity (%s)", eid.get());
+                        }
+                        continue;
+                    }
+                }
+
+                // Use a private holding area for filtering purposes.
+                vector<Attribute*> holding2;
+
+                try {
+                    // Set up and evaluate a policy for an AA asserting attributes to us.
+                    shibsp::SecurityPolicy policy(application, &AttributeAuthorityDescriptor::ELEMENT_QNAME, false, m_policyId.get());
+                    Locker locker(m_metadata);
+                    if (m_metadata)
+                        policy.setMetadataProvider(m_metadata);
+                    if (m_trust)
+                        policy.setTrustEngine(m_trust);
+                    // Populate recipient as audience.
+                    const XMLCh* issuer = (*assert)->getIssuer() ? (*assert)->getIssuer()->getName() : NULL;
+                    policy.getAudiences().push_back(application.getRelyingParty(issuer)->getXMLString("entityID").second);
+
+                    // Extract assertion information for policy.
+                    policy.setMessageID((*assert)->getID());
+                    policy.setIssueInstant((*assert)->getIssueInstantEpoch());
+                    policy.setIssuer((*assert)->getIssuer());
+
+                    // Look up metadata for issuer.
+                    if (policy.getIssuer() && policy.getMetadataProvider()) {
+                        if (policy.getIssuer()->getFormat() && !XMLString::equals(policy.getIssuer()->getFormat(), saml2::NameIDType::ENTITY)) {
+                            m_log.debug("non-system entity issuer, skipping metadata lookup");
+                        }
+                        else {
+                            m_log.debug("searching metadata for entity assertion issuer...");
+                            pair<const EntityDescriptor*,const RoleDescriptor*> lookup;
+                            MetadataProvider::Criteria& mc = policy.getMetadataProviderCriteria();
+                            mc.entityID_unicode = policy.getIssuer()->getName();
+                            mc.role = &AttributeAuthorityDescriptor::ELEMENT_QNAME;
+                            mc.protocol = samlconstants::SAML20P_NS;
+                            lookup = policy.getMetadataProvider()->getEntityDescriptor(mc);
+                            if (!lookup.first) {
+                                auto_ptr_char iname(policy.getIssuer()->getName());
+                                m_log.debug("no metadata found, can't establish identity of issuer (%s)", iname.get());
+                            }
+                            else if (!lookup.second) {
+                                m_log.debug("unable to find compatible AA role in metadata");
+                            }
+                            else {
+                                policy.setIssuerMetadata(lookup.second);
+                            }
+                        }
+                    }
+
+                    // Authenticate the assertion. We have to clone and marshall it to establish the signature for verification.
+                    auto_ptr<saml2::Assertion> tokencopy((*assert)->cloneAssertion());
+                    tokencopy->marshall();
+                    policy.evaluate(*tokencopy);
+                    if (!policy.isAuthenticated()) {
+                        if (m_log.isDebugEnabled()) {
+                            auto_ptr_char tempid(tokencopy->getID());
+                            auto_ptr_char eid(entityID);
+                            m_log.debug(
+                                "failed to authenticate assertion (%s) in metadata extension for entity (%s)", tempid.get(), eid.get()
+                                );
+                        }
+                        continue;
+                    }
+
+                    // Override the asserting/relying party names based on this new issuer.
+                    const EntityDescriptor* inlineEntity =
+                        policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
+                    auto_ptr_char inlineAssertingParty(inlineEntity ? inlineEntity->getEntityID() : NULL);
+                    relyingParty = application.getRelyingParty(inlineEntity)->getString("entityID").second;
+                    const vector<saml2::Attribute*>& attrs2 =
+                        const_cast<const saml2::AttributeStatement*>(tokencopy->getAttributeStatements().front())->getAttributes();
+                    for (vector<saml2::Attribute*>::const_iterator a = attrs2.begin(); a!=attrs2.end(); ++a)
+                        extractAttributes(application, inlineAssertingParty.get(), relyingParty, *(*a), holding2);
+
+                    // Now we locally filter the attributes so that the actual issuer can be properly set.
+                    // If we relied on outside filtering, the attributes couldn't be distinguished from the
+                    // ones that come from the user's IdP.
+                    if (m_filter && !holding2.empty()) {
+                        BasicFilteringContext fc(application, holding2, policy.getIssuerMetadata());
+                        Locker filtlocker(m_filter);
+                        try {
+                            m_filter->filterAttributes(fc, holding2);
+                        }
+                        catch (exception& ex) {
+                            m_log.error("caught exception filtering attributes: %s", ex.what());
+                            m_log.error("dumping extracted attributes due to filtering exception");
+                            for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
+                            holding2.clear();
+                        }
+                    }
+
+                    if (!holding2.empty()) {
+                        // Copy them over to the main holding tank.
+                        holding.insert(holding.end(), holding2.begin(), holding2.end());
+                    }
+                }
+                catch (exception& ex) {
+                    // Known exceptions are handled gracefully by skipping the assertion.
+                    if (m_log.isDebugEnabled()) {
+                        auto_ptr_char tempid((*assert)->getID());
+                        auto_ptr_char eid(entityID);
+                        m_log.debug(
+                            "exception authenticating assertion (%s) in metadata extension for entity (%s): %s",
+                            tempid.get(),
+                            eid.get(),
+                            ex.what()
+                            );
+                    }
+                    for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
+                    continue;
+                }
+                catch (...) {
+                    // Unknown exceptions are fatal.
+                    if (useCache)
+                        m_attrLock->unlock();
+                    for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
+                    for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
+                    throw;
+                }
+            }
+        }
+
+        if (!holding.empty()) {
+            if (useCache) {
+                m_attrLock->unlock();
+                m_attrLock->wrlock();
+                SharedLock locker(m_attrLock, false);   // pop the lock when we're done
+                if (cacheEntry->second.count(container) == 0) {
+                    for (vector<Attribute*>::const_iterator held = holding.begin(); held != holding.end(); ++held)
+                        cacheEntry->second[container].push_back((*held)->marshall());
+                }
+            }
+            attributes.insert(attributes.end(), holding.begin(), holding.end());
+        }
+        else if (useCache) {
+            m_attrLock->unlock();
+        }
+
+        break;  // only process a single extension element
     }
 }
 
@@ -408,16 +782,19 @@ void XMLExtractor::extractAttributes(
     if (!m_impl)
         return;
 
+    const EntityDescriptor* entity = issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent()) : NULL;
+    const char* relyingParty = application.getRelyingParty(entity)->getString("entityID").second;
+
     // Check for assertions.
     if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Assertion::LOCAL_NAME)) {
         const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(&xmlObject);
         if (token2) {
-            auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+            auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
             const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
             for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
                 const vector<saml2::Attribute*>& attrs = const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
                 for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
-                    m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);
+                    m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*a), attributes);
 
                 const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();
                 for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
@@ -428,12 +805,12 @@ void XMLExtractor::extractAttributes(
 
         const saml1::Assertion* token1 = dynamic_cast<const saml1::Assertion*>(&xmlObject);
         if (token1) {
-            auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+            auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
             const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
             for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
                 const vector<saml1::Attribute*>& attrs = const_cast<const saml1::AttributeStatement*>(*s)->getAttributes();
                 for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
-                    m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);
+                    m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*a), attributes);
             }
             return;
         }
@@ -443,18 +820,34 @@ void XMLExtractor::extractAttributes(
 
     // Check for metadata.
     if (XMLString::equals(xmlObject.getElementQName().getNamespaceURI(), samlconstants::SAML20MD_NS)) {
-        const EntityDescriptor* entity = dynamic_cast<const EntityDescriptor*>(&xmlObject);
-        if (!entity)
+        const RoleDescriptor* roleToExtract = dynamic_cast<const RoleDescriptor*>(&xmlObject);
+        const EntityDescriptor* entityToExtract = roleToExtract ? dynamic_cast<const EntityDescriptor*>(roleToExtract->getParent()) : NULL;
+        if (!entityToExtract)
             throw AttributeExtractionException("Unable to extract attributes, unknown metadata object type.");
-        auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
-        const Extensions* ext = entity->getExtensions();
-        if (ext)
-            m_impl->extractAttributes(application, assertingParty.get(), *ext, attributes);
-        const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(entity->getParent());
+        const Extensions* ext = entityToExtract->getExtensions();
+        if (ext) {
+            m_impl->extractAttributes(
+                application,
+                dynamic_cast<const ObservableMetadataProvider*>(application.getMetadataProvider(false)),
+                entityToExtract->getEntityID(),
+                relyingParty,
+                *ext,
+                attributes
+                );
+        }
+        const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(entityToExtract->getParent());
         while (group) {
             ext = group->getExtensions();
-            if (ext)
-                m_impl->extractAttributes(application, assertingParty.get(), *ext, attributes);
+            if (ext) {
+                m_impl->extractAttributes(
+                    application,
+                    dynamic_cast<const ObservableMetadataProvider*>(application.getMetadataProvider(false)),
+                    NULL,   // not an entity, so inline assertions won't be processed
+                    relyingParty,
+                    *ext,
+                    attributes
+                    );
+            }
             group = dynamic_cast<const EntitiesDescriptor*>(group->getParent());
         }
         return;
@@ -462,15 +855,14 @@ void XMLExtractor::extractAttributes(
 
     // Check for attributes.
     if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Attribute::LOCAL_NAME)) {
-        auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
-
+        auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
         const saml2::Attribute* attr2 = dynamic_cast<const saml2::Attribute*>(&xmlObject);
         if (attr2)
-            return m_impl->extractAttributes(application, assertingParty.get(), *attr2, attributes);
+            return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *attr2, attributes);
 
         const saml1::Attribute* attr1 = dynamic_cast<const saml1::Attribute*>(&xmlObject);
         if (attr1)
-            return m_impl->extractAttributes(application, assertingParty.get(), *attr1, attributes);
+            return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *attr1, attributes);
 
         throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
     }
@@ -511,14 +903,14 @@ void XMLExtractor::extractAttributes(
     // Check for NameIDs.
     const NameID* name2 = dynamic_cast<const NameID*>(&xmlObject);
     if (name2) {
-        auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
-        return m_impl->extractAttributes(application, assertingParty.get(), *name2, attributes);
+        auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
+        return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *name2, attributes);
     }
 
     const NameIdentifier* name1 = dynamic_cast<const NameIdentifier*>(&xmlObject);
     if (name1) {
-        auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
-        return m_impl->extractAttributes(application, assertingParty.get(), *name1, attributes);
+        auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
+        return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *name1, attributes);
     }
 
     throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
index 9eb4cf3..7e7def0 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/base.h
- * 
+ *
  * Base header file definitions
  * Must be included prior to including any other header
  */
 
 #ifdef WIN32
 
-/**
- * Default catalog path on Windows.
- */
+/** Default catalog path on Windows. */
 # define SHIBSP_SCHEMAS "c:/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml;c:/opt/shibboleth-sp/share/xml/opensaml/saml20-catalog.xml;c:/opt/shibboleth-sp/share/xml/opensaml/saml11-catalog.xml;c:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"
 
-/**
- * Default name of configuration file on Windows.
- */
+/** Default name of configuration file on Windows. */
 # define SHIBSP_CONFIG "shibboleth2.xml"
 
 /**
  */
 #define SHIBSP_LOGGING "console.logger"
 
-/**
- * Default prefix for installation (used to resolve relative paths).
- */
+/** Default prefix for installation (used to resolve relative paths). */
 #define SHIBSP_PREFIX  "c:/opt/shibboleth-sp"
 
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR  "lib"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR  "var/log"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR  "etc"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR  "var/run"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR  "share/xml"
+
 #else
 # include <shibsp/paths.h>
 #endif
 
-/**
- * Logging category for Service Provider functions.
- */
+/** Logging category for Service Provider functions. */
 #define SHIBSP_LOGCAT "Shibboleth"
 
-/**
- * Logging category for Service Provider auditing.
- */
+/** Logging category for Service Provider auditing. */
 #define SHIBSP_TX_LOGCAT "Shibboleth-TRANSACTION"
 
 #endif /* __shibsp_base_h__ */
index 573f3f1..eedebc0 100644 (file)
@@ -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.
@@ -72,9 +72,6 @@ namespace shibsp {
         /** Application supplied to client. */
         const Application& m_app;
 
-        /** Properties associated with the Application's security policy. */
-        const PropertySet* m_settings;
-
         /** RelyingParty properties, set after transport prep. */
         const PropertySet* m_relyingParty;
 
index 332549f..52e68fc 100644 (file)
@@ -87,7 +87,7 @@ saml1p::Response* ArtifactResolver::resolve(
         throw MetadataException("No compatible endpoint found in issuer's metadata.");
     else if (!response)
         throw BindingException("Unable to resolve artifact(s) into a SAML response.");
-    const QName* code = (response->getStatus() && response->getStatus()->getStatusCode()) ? response->getStatus()->getStatusCode()->getValue() : NULL;
+    const xmltooling::QName* code = (response->getStatus() && response->getStatus()->getStatusCode()) ? response->getStatus()->getStatusCode()->getValue() : NULL;
     if (!code || *code != saml1p::StatusCode::SUCCESS) {
         delete response;
         throw BindingException("Identity provider returned a SAML error in response to artifact(s).");
index ad3d3cb..cc5c6dc 100644 (file)
@@ -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,8 @@ using namespace xmltooling;
 using namespace std;
 
 SOAPClient::SOAPClient(SecurityPolicy& policy)
-    : opensaml::SOAPClient(policy), m_app(policy.getApplication()), m_settings(NULL), m_relyingParty(NULL), m_credResolver(NULL)
+    : opensaml::SOAPClient(policy), m_app(policy.getApplication()), m_relyingParty(NULL), m_credResolver(NULL)
 {
-    m_settings = m_app.getServiceProvider().getPolicySettings(m_app.getString("policyId").second);
-    pair<bool,bool> validate = m_settings->getBool("validate");
-    policy.setValidating(validate.first && validate.second);
-    setValidating(validate.first && validate.second);
 }
 
 void SOAPClient::send(const soap11::Envelope& env, const char* from, MetadataCredentialCriteria& to, const char* endpoint)
@@ -114,8 +110,7 @@ void SOAPClient::prepareTransport(SOAPTransport& transport)
     if ((!flag.first || flag.second) && !transport.isConfidential())
         throw opensaml::BindingException("Transport confidentiality required, but not available."); 
 
-    flag = m_settings->getBool("validate");
-    setValidating(flag.first && flag.second);
+    setValidating(getPolicy().getValidating());
     flag = m_relyingParty->getBool("requireTransportAuth");
     forceTransportAuthentication(!flag.first || flag.second);
 
index 140fa11..20a480b 100644 (file)
@@ -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_abshandler_h__
 
 #include <shibsp/handler/Handler.h>
+#include <shibsp/remoting/ddf.h>
 #include <shibsp/util/DOMPropertySet.h>
 
 #ifndef SHIBSP_LITE
@@ -155,6 +156,56 @@ namespace shibsp {
             bool clear=true
             ) const;
         
+        /**
+         * Implements a mechanism to preserve form post data.
+         *
+         * @param application   the associated Application
+         * @param request       incoming HTTP request
+         * @param response      outgoing HTTP response
+         * @param relayState    relay state information attached to current sequence, if any
+         */
+        virtual void preservePostData(
+            const Application& application,
+            const xmltooling::HTTPRequest& request,
+            xmltooling::HTTPResponse& response,
+            const char* relayState
+            ) const;
+
+        /**
+         * Implements storage service and cookie mechanism to recover PostData.
+         *
+         * <p>If a supported mechanism can be identified, the return value will be
+         * the recovered state information.
+         *
+         * @param application   the associated Application
+         * @param request       incoming HTTP request
+         * @param response      outgoing HTTP response
+         * @param relayState    relay state information attached to current sequence, if any
+         * @return  recovered form post data associated with request as a DDF list of string members
+         */
+        virtual DDF recoverPostData(
+            const Application& application,
+            const xmltooling::HTTPRequest& request,
+            xmltooling::HTTPResponse& response,
+            const char* relayState
+            ) const;
+
+        /**
+         * Post a redirect response with post data.
+         * 
+         * @param application   the associated Application
+         * @param response      outgoing HTTP response
+         * @param request       incoming HTTP request
+         * @param url           action url for the form
+         * @param postData      list of parameters to load into the form, as DDF string members
+         */
+        virtual long sendPostResponse(
+            const Application& application,
+            xmltooling::HTTPResponse& httpResponse,
+            const char* url,
+            DDF& postData
+            ) const;
+
         /** Logging object. */
         xmltooling::logging::Category& m_log;
         
@@ -163,6 +214,10 @@ namespace shibsp {
 
     public:
         virtual ~AbstractHandler() {}
+
+    private:
+        std::pair<std::string,const char*> getPostCookieNameProps(const Application& app, const char* relayState) const;
+        DDF getPostData(const Application& application, const xmltooling::HTTPRequest& request) const;
     };
 
 #if defined (_MSC_VER)
index a7289fe..752e86c 100644 (file)
@@ -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.
@@ -76,6 +76,23 @@ namespace shibsp {
         void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const;
         
         /**
+         * Returns a SecurityPolicy instance to use for an incoming request.
+         *
+         * <p>Allows handlers to customize the type of policy object their policy rules might require.
+         * <p>The caller <strong>MUST</strong> lock the application's MetadataProvider for the life
+         * of the returned object.
+         *
+         * @param application   reference to application receiving message
+         * @param role          identifies the role (generally IdP or SP) of the policy peer
+         * @param validate      true iff XML parsing should be done with validation
+         * @param policyId      identifies policy rules to auto-attach, defaults to the application's set
+         * @return  a new policy instance, which the caller is responsible for freeing
+         */
+        virtual opensaml::SecurityPolicy* createSecurityPolicy(
+            const Application& application, const xmltooling::QName* role, bool validate, const char* policyId
+            ) const;
+
+        /**
          * Implement protocol-specific handling of the incoming decoded message.
          * 
          * <p>The result of implementing the protocol should be an exception or
index cd9039c..e42ef5b 100644 (file)
@@ -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.
 #include "handler/AbstractHandler.h"
 #include "handler/LogoutHandler.h"
 #include "remoting/ListenerService.h"
+#include "util/CGIParser.h"
 #include "util/SPConstants.h"
+#include "util/TemplateParameters.h"
+
+#include <vector>
+#include <fstream>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/PathResolver.h>
+#include <xmltooling/util/URLEncoder.h>
+
 
 #ifndef SHIBSP_LITE
 # include <saml/saml1/core/Protocols.h>
@@ -36,6 +45,8 @@
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 # include <saml/util/SAMLConstants.h>
+# include <saml/SAMLConfig.h>
+# include <saml/binding/SAMLArtifact.h>
 # include <xmltooling/util/StorageService.h>
 using namespace opensaml::saml2md;
 #else
@@ -145,7 +156,7 @@ void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleD
         const saml1p::Status* status = r1->getStatus();
         if (status) {
             const saml1p::StatusCode* sc = status->getStatusCode();
-            const QName* code = sc ? sc->getValue() : NULL;
+            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());
@@ -305,7 +316,7 @@ void AbstractHandler::preserveRelayState(const Application& application, HTTPRes
                 else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
                     DDF out,in = DDF("set::RelayState").structure();
                     in.addmember("id").string(mech.second);
-                    in.addmember("value").string(relayState.c_str());
+                    in.addmember("value").unsafe_string(relayState.c_str());
                     DDFJanitor jin(in),jout(out);
                     out = application.getServiceProvider().getListenerService()->send(in);
                     if (!out.isstring())
@@ -348,9 +359,7 @@ void AbstractHandler::recoverRelayState(
                             relayState.erase();
                     }
                     else {
-                        Category::getInstance(SHIBSP_LOGCAT".Handler").error(
-                            "Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str()
-                            );
+                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());
                         relayState.erase();
                     }
 #endif
@@ -402,13 +411,244 @@ void AbstractHandler::recoverRelayState(
         relayState.erase();
     }
 
-    // Check for "default" value.
-    if (relayState.empty() || relayState == "default") {
+    // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).
+    if (relayState.empty() || relayState == "default" || relayState == "cookie") {
         pair<bool,const char*> homeURL=application.getString("homeURL");
-        relayState=homeURL.first ? homeURL.second : "/";
+        if (homeURL.first)
+            relayState=homeURL.second;
+        else {
+            // Compute a URL to the root of the site.
+            int port = request.getPort();
+            const char* scheme = request.getScheme();
+            relayState = string(scheme) + "://" + request.getHostname();
+            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+                ostringstream portstr;
+                portstr << port;
+                relayState += ":" + portstr.str();
+            }
+            relayState += '/';
+        }
+    }
+}
+
+void AbstractHandler::preservePostData(
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
+    ) const
+{
+#ifdef HAVE_STRCASECMP
+    if (strcasecmp(request.getMethod(), "POST")) return;
+#else
+    if (stricmp(request.getMethod(), "POST")) return;
+#endif
+
+    // No specs mean no save.
+    const PropertySet* props=application.getPropertySet("Sessions");
+    pair<bool,const char*> mech = props->getString("postData");
+    if (!mech.first) {
+        m_log.info("postData property not supplied, form data will not be preserved across SSO");
+        return;
+    }
+
+    DDF postData = getPostData(application, request);
+    if (postData.isnull())
         return;
+
+    if (strstr(mech.second,"ss:") == mech.second) {
+        mech.second+=3;
+        if (!*mech.second) {
+            postData.destroy();
+            throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3));
+        }
+
+        string postkey;
+        if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
+            DDFJanitor postjan(postData);
+#ifndef SHIBSP_LITE
+            StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
+            if (storage) {
+                // Use a random key
+                string rsKey;
+                SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
+                rsKey = SAMLArtifact::toHex(rsKey);
+                ostringstream out;
+                out << postData;
+                if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))
+                    throw IOException("Attempted to insert duplicate storage key.");
+                postkey = string(mech.second-3) + ':' + rsKey;
+            }
+            else {
+                m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second);
+            }
+#endif
+        }
+        else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
+            DDF out,in = DDF("set::PostData").structure();
+            DDFJanitor jin(in),jout(out);
+            in.addmember("id").string(mech.second);
+            in.add(postData);
+            out = application.getServiceProvider().getListenerService()->send(in);
+            if (!out.isstring())
+                throw IOException("StorageService-backed PostData mechanism did not return a state key.");
+            postkey = string(mech.second-3) + ':' + out.string();
+        }
+
+        // Set a cookie with key info.
+        pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
+        postkey += shib_cookie.second;
+        response.setCookie(shib_cookie.first.c_str(), postkey.c_str());
+    }
+    else {
+        postData.destroy();
+        throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second));
+    }
+}
+
+DDF AbstractHandler::recoverPostData(
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
+    ) const
+{
+    // First we need the post recovery cookie.
+    pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
+    const char* cookie = request.getCookie(shib_cookie.first.c_str());
+    if (!cookie || !*cookie)
+        return DDF();
+
+    // Clear the cookie.
+    string exp(shib_cookie.second);
+    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+    response.setCookie(shib_cookie.first.c_str(), exp.c_str());
+
+    // Look for StorageService-backed state of the form "ss:SSID:key".
+    const char* state = cookie;
+    if (strstr(state, "ss:") == state) {
+        state += 3;
+        const char* key = strchr(state, ':');
+        if (key) {
+            string ssid = string(cookie).substr(3, key - state);
+            key++;
+            if (!ssid.empty() && *key) {
+                SPConfig& conf = SPConfig::getConfig();
+                if (conf.isEnabled(SPConfig::OutOfProcess)) {
+#ifndef SHIBSP_LITE
+                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
+                    if (storage) {
+                        if (storage->readString("PostData", key, &ssid) > 0) {
+                            storage->deleteString("PostData", key);
+                            istringstream inret(ssid);
+                            DDF ret;
+                            inret >> ret;
+                            return ret;
+                        }
+                        else {
+                            m_log.error("failed to recover form post data using key (%s)", key);
+                        }
+                    }
+                    else {
+                        m_log.error("storage-backed PostData with invalid StorageService ID (%s)", ssid.c_str());
+                    }
+#endif
+                }
+                else if (conf.isEnabled(SPConfig::InProcess)) {
+                    DDF in = DDF("get::PostData").structure();
+                    DDFJanitor jin(in);
+                    in.addmember("id").string(ssid.c_str());
+                    in.addmember("key").string(key);
+                    DDF out = application.getServiceProvider().getListenerService()->send(in);
+                    if (out.islist())
+                        return out;
+                    out.destroy();
+                    m_log.error("storageService-backed PostData mechanism did not return preserved data.");
+                }
+            }
+        }
+    }
+    return DDF();
+}
+
+long AbstractHandler::sendPostResponse(
+    const Application& application, HTTPResponse& httpResponse, const char* url, DDF& postData
+    ) const
+{
+    const PropertySet* props=application.getPropertySet("Sessions");
+    pair<bool,const char*> postTemplate = props->getString("postTemplate");
+    if (!postTemplate.first)
+        throw ConfigurationException("Missing postTemplate property, unable to recreate form post.");
+
+    string fname(postTemplate.second);
+    ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
+    if (!infile)
+        throw ConfigurationException("Unable to access HTML template ($1).", params(1, fname.c_str()));
+    TemplateParameters respParam;
+    respParam.m_map["action"] = url;
+
+    // Load the parameters into objects for the template.
+    multimap<string,string>& collection = respParam.m_collectionMap["PostedData"];
+    DDF param = postData.first();
+    while (param.isstring()) {
+        collection.insert(pair<const string,string>(param.name(), (param.string() ? param.string() : "")));
+        param = postData.next();
     }
 
-    if (relayState == "default")
-        relayState.empty();
+    stringstream str;
+    XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam);
+
+    pair<bool,bool> postExpire = props->getBool("postExpire");
+
+    httpResponse.setContentType("text/html");
+    if (!postExpire.first || postExpire.second) {
+        httpResponse.setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
+        httpResponse.setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
+        httpResponse.setResponseHeader("Pragma", "no-cache");
+    }
+    return httpResponse.sendResponse(str);
+}
+
+pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const
+{
+    // Decorates the name of the cookie with the relay state key, if any.
+    // Doing so gives a better assurance that the recovered data really
+    // belongs to the relayed request.
+    pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");
+    if (strstr(relayState, "cookie:") == relayState) {
+        shib_cookie.first = string("_shibpost_") + (relayState + 7);
+    }
+    else if (strstr(relayState, "ss:") == relayState) {
+        const char* pch = strchr(relayState + 3, ':');
+        if (pch)
+            shib_cookie.first = string("_shibpost_") + (pch + 1);
+    }
+    return shib_cookie;
+}
+
+DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const
+{
+    string contentType = request.getContentType();
+    if (contentType.compare("application/x-www-form-urlencoded") == 0) {
+        const PropertySet* props=application.getPropertySet("Sessions");
+        pair<bool,unsigned int> plimit = props->getUnsignedInt("postLimit");
+        if (!plimit.first)
+            plimit.second = 1024 * 1024;
+        if (plimit.second == 0 || request.getContentLength() <= plimit.second) {
+            CGIParser cgi(request);
+            pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);
+            if (params.first == params.second)
+                return DDF();
+            DDF child;
+            DDF ret = DDF("parameters").list();
+            for (; params.first != params.second; ++params.first) {
+                if (!params.first->first.empty()) {
+                    child = DDF(params.first->first.c_str()).unsafe_string(params.first->second);
+                    ret.add(child);
+                }
+            }
+            return ret;
+        }
+        else {
+            m_log.warn("POST limit exceeded, ignoring %d bytes of posted data", request.getContentLength());
+        }
+    }
+    else {
+        m_log.info("ignoring POST data with non-standard encoding (%s)", contentType.c_str());
+    }
+    return DDF();
 }
index 8f3b008..52f747b 100644 (file)
@@ -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.
@@ -147,28 +147,48 @@ pair<bool,long> AssertionConsumerService::processMessage(
     Locker metadataLocker(application.getMetadataProvider());
 
     // Create the policy.
-    shibsp::SecurityPolicy policy(application, &m_role, validate.first && validate.second);
+    auto_ptr<opensaml::SecurityPolicy> policy(
+        createSecurityPolicy(application, &m_role, validate.first && validate.second, policyId.second)
+        );
 
     string relayState;
-
     try {
         // Decode the message and process it in a protocol-specific way.
-        auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, policy));
+        auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, *(policy.get())));
         if (!msg.get())
             throw BindingException("Failed to decode an SSO protocol response.");
+        DDF postData = recoverPostData(application, httpRequest, httpResponse, relayState.c_str());
+        DDFJanitor postjan(postData);
         recoverRelayState(application, httpRequest, httpResponse, relayState);
-        implementProtocol(application, httpRequest, httpResponse, policy, settings, *msg.get());
+        implementProtocol(application, httpRequest, httpResponse, *(policy.get()), settings, *msg.get());
 
-        auto_ptr_char issuer(policy.getIssuer() ? policy.getIssuer()->getName() : NULL);
+        auto_ptr_char issuer(policy->getIssuer() ? policy->getIssuer()->getName() : NULL);
 
         // History cookie.
         if (issuer.get() && *issuer.get())
             maintainHistory(application, httpRequest, httpResponse, issuer.get());
 
         // Now redirect to the state value. By now, it should be set to *something* usable.
-        return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+        // First check for POST data.
+        if (!postData.islist()) {
+            m_log.debug("ACS returning via redirect to: %s", relayState.c_str());
+            return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+        }
+        else {
+            m_log.debug("ACS returning via POST to: %s", relayState.c_str());
+            return make_pair(true, sendPostResponse(application, httpResponse, relayState.c_str(), postData));
+        }
     }
     catch (XMLToolingException& ex) {
+        // Check for isPassive error condition.
+        const char* sc2 = ex.getProperty("statusCode2");
+        if (sc2 && !strcmp(sc2, "urn:oasis:names:tc:SAML:2.0:status:NoPassive")) {
+            validate = getBool("ignoreNoPassive", m_configNS.get());  // namespace-qualified if inside handler element
+            if (validate.first && validate.second && !relayState.empty()) {
+                m_log.debug("ignoring SAML status of NoPassive and redirecting to resource...");
+                return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+            }
+        }
         if (!relayState.empty())
             ex.addProperty("RelayState", relayState.c_str());
         throw;
@@ -203,7 +223,8 @@ void AssertionConsumerService::checkAddress(const Application& application, cons
 
 #ifndef SHIBSP_LITE
 
-void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
+void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const
+{
     const char* loc = getString("Location").second;
     string hurl(handlerURL);
     if (*loc != '/')
@@ -226,6 +247,13 @@ void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const cha
     role.getAssertionConsumerServices().push_back(ep);
 }
 
+opensaml::SecurityPolicy* AssertionConsumerService::createSecurityPolicy(
+    const Application& application, const xmltooling::QName* role, bool validate, const char* policyId
+    ) const
+{
+    return new SecurityPolicy(application, role, validate, policyId);
+}
+
 class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext
 {
 public:
@@ -261,19 +289,18 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
     const vector<const Assertion*>* tokens
     ) const
 {
-    const saml2md::EntityDescriptor* entity = issuer ? dynamic_cast<const saml2md::EntityDescriptor*>(issuer->getParent()) : NULL;
-
     // First we do the extraction of any pushed information, including from metadata.
     vector<Attribute*> resolvedAttributes;
     AttributeExtractor* extractor = application.getAttributeExtractor();
     if (extractor) {
         Locker extlocker(extractor);
-        if (entity) {
+        if (issuer) {
             pair<bool,const char*> mprefix = application.getString("metadataAttributePrefix");
             if (mprefix.first) {
                 m_log.debug("extracting metadata-derived attributes...");
                 try {
-                    extractor->extractAttributes(application, issuer, *entity, resolvedAttributes);
+                    // We pass NULL for "issuer" because the IdP isn't the one asserting metadata-based attributes.
+                    extractor->extractAttributes(application, NULL, *issuer, resolvedAttributes);
                     for (vector<Attribute*>::iterator a = resolvedAttributes.begin(); a != resolvedAttributes.end(); ++a) {
                         vector<string>& ids = (*a)->getAliases();
                         for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
@@ -338,7 +365,7 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
             auto_ptr<ResolutionContext> ctx(
                 resolver->createResolutionContext(
                     application,
-                    entity,
+                    issuer ? dynamic_cast<const saml2md::EntityDescriptor*>(issuer->getParent()) : NULL,
                     protocol,
                     nameid,
                     authncontext_class,
@@ -351,17 +378,6 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
             // Copy over any pushed attributes.
             if (!resolvedAttributes.empty())
                 ctx->getResolvedAttributes().insert(ctx->getResolvedAttributes().end(), resolvedAttributes.begin(), resolvedAttributes.end());
-
-            // Attach global prefix if needed.
-            pair<bool,const char*> prefix = application.getString("attributePrefix");
-            if (prefix.first) {
-                for (vector<Attribute*>::iterator a = ctx->getResolvedAttributes().begin(); a != ctx->getResolvedAttributes().end(); ++a) {
-                    vector<string>& ids = (*a)->getAliases();
-                    for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
-                        *id = prefix.second + *id;
-                }
-            }
-
             return ctx.release();
         }
     }
@@ -369,19 +385,8 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
         m_log.error("attribute resolution failed: %s", ex.what());
     }
 
-    if (!resolvedAttributes.empty()) {
-        // Attach global prefix if needed.
-        pair<bool,const char*> prefix = application.getString("attributePrefix");
-        if (prefix.first) {
-            for (vector<Attribute*>::iterator a = resolvedAttributes.begin(); a != resolvedAttributes.end(); ++a) {
-                vector<string>& ids = (*a)->getAliases();
-                for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
-                    *id = prefix.second + *id;
-            }
-        }
-
+    if (!resolvedAttributes.empty())
         return new DummyContext(resolvedAttributes);
-    }
     return NULL;
 }
 
@@ -412,15 +417,11 @@ void AssertionConsumerService::extractMessageDetails(const Assertion& assertion,
         }
         m_log.debug("searching metadata for assertion issuer...");
         pair<const EntityDescriptor*,const RoleDescriptor*> entity;
-        shibsp::SecurityPolicy* sppol = dynamic_cast<shibsp::SecurityPolicy*>(&policy);
-        if (sppol) {
-            MetadataProviderCriteria mc(sppol->getApplication(), policy.getIssuer()->getName(), &IDPSSODescriptor::ELEMENT_QNAME, protocol);
-            entity = policy.getMetadataProvider()->getEntityDescriptor(mc);
-        }
-        else {
-            MetadataProvider::Criteria mc(policy.getIssuer()->getName(), &IDPSSODescriptor::ELEMENT_QNAME, protocol);
-            entity = policy.getMetadataProvider()->getEntityDescriptor(mc);
-        }
+        MetadataProvider::Criteria& mc = policy.getMetadataProviderCriteria();
+        mc.entityID_unicode = policy.getIssuer()->getName();
+        mc.role = &IDPSSODescriptor::ELEMENT_QNAME;
+        mc.protocol = protocol;
+        entity = policy.getMetadataProvider()->getEntityDescriptor(mc);
         if (!entity.first) {
             auto_ptr_char iname(policy.getIssuer()->getName());
             m_log.warn("no metadata found, can't establish identity of issuer (%s)", iname.get());
index 990d7d7..adeb711 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,7 +16,7 @@
 
 /**
  * AssertionLookup.cpp
- * 
+ *
  * Handler for looking assertions in SessionCache
  */
 
@@ -45,7 +45,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
@@ -112,10 +117,10 @@ pair<bool,long> AssertionLookup::run(SPRequest& request, bool isHandler) const
         if (m_acl.count(request.getRemoteAddr()) == 0) {
             m_log.error("request for assertion lookup blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Assertion Lookup Blocked");
-            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_UNAUTHORIZED));
+            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
         }
     }
-    
+
     try {
         if (conf.isEnabled(SPConfig::OutOfProcess)) {
             // When out of process, we run natively and directly process the message.
@@ -125,7 +130,7 @@ pair<bool,long> AssertionLookup::run(SPRequest& request, bool isHandler) const
             // When not out of process, we remote all the message processing.
             DDF out,in = wrap(request);
             DDFJanitor jin(in), jout(out);
-            
+
             out=request.getServiceProvider().getListenerService()->send(in);
             return unwrap(request, out);
         }
@@ -147,7 +152,7 @@ void AssertionLookup::receive(DDF& in, ostream& out)
         m_log.error("couldn't find application (%s) for assertion lookup", aid ? aid : "(missing)");
         throw ConfigurationException("Unable to locate application for assertion lookup, deleted?");
     }
-    
+
     // Unpack the request.
     auto_ptr<HTTPRequest> req(getRequest(in));
     //m_log.debug("found %d client certificates", req->getClientCertificates().size());
@@ -156,7 +161,7 @@ void AssertionLookup::receive(DDF& in, ostream& out)
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-        
+
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
index e8de4d6..4fc6776 100644 (file)
@@ -75,7 +75,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL LogoutInitiatorNodeFilter : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,_LogoutInitiator))
                 return FILTER_REJECT;
             return FILTER_ACCEPT;
index dcd29d6..1cbc45b 100644 (file)
@@ -71,7 +71,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL SessionInitiatorNodeFilter : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,_SessionInitiator))
                 return FILTER_REJECT;
             return FILTER_ACCEPT;
index 161dcc3..dfa43ed 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,7 +16,7 @@
 
 /**
  * LogoutHandler.cpp
- * 
+ *
  * Base class for logout-related handlers.
  */
 
@@ -71,7 +71,7 @@ pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
     // If we're inside a chain, do nothing.
     if (getParent())
         return make_pair(false,0L);
-    
+
     // If this isn't a LogoutInitiator, we only "continue" a notification loop, rather than starting one.
     if (!m_initiator && !request.getParameter("notifying"))
         return make_pair(false,0L);
@@ -172,6 +172,7 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
 #include <xmltooling/impl/AnyElement.h>
 #include <xmltooling/soap/SOAP.h>
 #include <xmltooling/soap/SOAPClient.h>
+#include <xmltooling/soap/HTTPSOAPTransport.h>
 using namespace soap11;
 namespace {
     static const XMLCh LogoutNotification[] =   UNICODE_LITERAL_18(L,o,g,o,u,t,N,o,t,i,f,i,c,a,t,i,o,n);
@@ -188,6 +189,12 @@ namespace {
     private:
         void prepareTransport(SOAPTransport& transport) {
             transport.setVerifyHost(false);
+            HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(&transport);
+            if (http) {
+                http->useChunkedEncoding(false);
+                http->setRequestHeader("User-Agent", PACKAGE_NAME);
+                http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
+            }
         }
     };
 };
@@ -197,6 +204,11 @@ bool LogoutHandler::notifyBackChannel(
     const Application& application, const char* requestURL, const vector<string>& sessions, bool local
     ) const
 {
+    if (sessions.empty()) {
+        Category::getInstance(SHIBSP_LOGCAT".Logout").error("no sessions supplied to back channel notification method");
+        return false;
+    }
+
     unsigned int index = 0;
     string endpoint = application.getNotificationURL(requestURL, false, index++);
     if (endpoint.empty())
@@ -209,7 +221,7 @@ bool LogoutHandler::notifyBackChannel(
         env->setBody(body);
         ElementProxy* msg = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, LogoutNotification);
         body->getUnknownXMLObjects().push_back(msg);
-        msg->setAttribute(QName(NULL, _type), local ? _local : _global);
+        msg->setAttribute(xmltooling::QName(NULL, _type), local ? _local : _global);
         for (vector<string>::const_iterator s = sessions.begin(); s!=sessions.end(); ++s) {
             auto_ptr_XMLCh temp(s->c_str());
             ElementProxy* child = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, SessionID);
index 08e73e0..2a847cb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,7 +16,7 @@
 
 /**
  * MetadataGenerator.cpp
- * 
+ *
  * Handler for generating "approximate" metadata based on SP configuration.
  */
 
@@ -29,6 +29,7 @@
 
 #ifndef SHIBSP_LITE
 # include "metadata/MetadataProviderCriteria.h"
+# include <xmltooling/util/PathResolver.h>
 #endif
 
 #include <xercesc/framework/LocalFileInputSource.hpp>
@@ -53,7 +54,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
@@ -121,14 +127,14 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
 
 #ifndef SHIBSP_LITE
     static XMLCh EndpointBase[] = UNICODE_LITERAL_12(E,n,d,p,o,i,n,t,B,a,s,e);
-    
+
     pair<bool,bool> flag = getBool("http");
     if (flag.first)
         m_http = flag.second ? 1 : -1;
     flag = getBool("https");
     if (flag.first)
         m_https = flag.second ? 1 : -1;
-    
+
     e = XMLHelper::getFirstChildElement(e, EndpointBase);
     while (e) {
         if (e->hasChildNodes()) {
@@ -148,10 +154,10 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
         if (!m_acl.empty() && m_acl.count(request.getRemoteAddr()) == 0) {
             m_log.error("request for metadata blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Metadata Request Blocked");
-            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_UNAUTHORIZED));
+            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
         }
     }
-    
+
     try {
         if (conf.isEnabled(SPConfig::OutOfProcess)) {
             // When out of process, we run natively and directly process the message.
@@ -165,7 +171,7 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
             if (request.getParameter("entityID"))
                 in.addmember("entity_id").string(request.getParameter("entityID"));
             DDFJanitor jin(in), jout(out);
-            
+
             out=request.getServiceProvider().getListenerService()->send(in);
             return unwrap(request, out);
         }
@@ -191,12 +197,12 @@ void MetadataGenerator::receive(DDF& in, ostream& out)
     else if (!hurl) {
         throw ConfigurationException("Missing handler_url parameter in remoted method call.");
     }
-    
+
     // Wrap a response shim.
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-        
+
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
@@ -226,7 +232,10 @@ pair<bool,long> MetadataGenerator::processMessage(
     pair<bool,const char*> prop = getString("template");
     if (prop.first) {
         // Load a template to use for our metadata.
-        LocalFileInputSource src(getXMLString("template").second);
+        string templ(prop.second);
+        XMLToolingConfig::getConfig().getPathResolver()->resolve(templ, PathResolver::XMLTOOLING_CFG_FILE);
+        auto_ptr_XMLCh widenit(templ.c_str());
+        LocalFileInputSource src(widenit.get());
         Wrapper4InputSource dsrc(&src,false);
         DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
         XercesJanitor<DOMDocument> docjan(doc);
@@ -234,7 +243,7 @@ pair<bool,long> MetadataGenerator::processMessage(
         docjan.release();
         entity = dynamic_cast<EntityDescriptor*>(xmlobj.get());
         if (!entity)
-            throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, prop.second));
+            throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, templ.c_str()));
         xmlobj.release();
     }
     else {
@@ -243,8 +252,14 @@ pair<bool,long> MetadataGenerator::processMessage(
 
     auto_ptr<EntityDescriptor> wrapper(entity);
     pair<bool,unsigned int> cache = getUnsignedInt("cacheDuration");
-    if (cache.first)
-        entity->setValidUntil(time(NULL) + cache.second);
+    if (cache.first) {
+        entity->setCacheDuration(cache.second);
+    }
+    else {
+        cache = getUnsignedInt("validUntil");
+        if (cache.first)
+            entity->setValidUntil(time(NULL) + cache.second);
+    }
     entity->setEntityID(relyingParty->getXMLString("entityID").second);
 
     SPSSODescriptor* role;
@@ -355,7 +370,7 @@ pair<bool,long> MetadataGenerator::processMessage(
             XMLHelper::serialize(entity->marshall(), pretty, true);
             DOMDocument* prettydoc = XMLToolingConfig::getConfig().getParser().parse(pretty);
             auto_ptr<XMLObject> prettyentity(XMLObjectBuilder::buildOneFromElement(prettydoc->getDocumentElement(), true));
-    
+
             Signature* sig = SignatureBuilder::buildSignature();
             dynamic_cast<EntityDescriptor*>(prettyentity.get())->setSignature(sig);
             if (sigalg.first)
index b8580e2..2ee35a1 100644 (file)
@@ -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.
@@ -206,7 +206,7 @@ long RemotedResponse::sendRedirect(const char* url)
 {
     if (!m_output.isstruct())
         m_output.structure();
-    m_output.addmember("redirect").string(url);
+    m_output.addmember("redirect").unsafe_string(url);
     return HTTPResponse::XMLTOOLING_HTTP_STATUS_MOVED;
 }
 
@@ -240,7 +240,7 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
     DDF in = DDF(m_address.c_str()).structure();
     in.addmember("application_id").string(request.getApplication().getId());
     in.addmember("scheme").string(request.getScheme());
-    in.addmember("hostname").string(request.getHostname());
+    in.addmember("hostname").unsafe_string(request.getHostname());
     in.addmember("port").integer(request.getPort());
     in.addmember("content_type").string(request.getContentType().c_str());
     in.addmember("content_length").integer(request.getContentLength());
@@ -248,8 +248,8 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
     in.addmember("remote_user").string(request.getRemoteUser().c_str());
     in.addmember("client_addr").string(request.getRemoteAddr().c_str());
     in.addmember("method").string(request.getMethod());
-    in.addmember("uri").string(request.getRequestURI());
-    in.addmember("url").string(request.getRequestURL());
+    in.addmember("uri").unsafe_string(request.getRequestURI());
+    in.addmember("url").unsafe_string(request.getRequestURL());
     in.addmember("query").string(request.getQueryString());
 
     if (headers) {
index d1c46b8..239d7d2 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * SAML1Consumer.cpp
- * 
- * SAML 1.x assertion consumer service 
+ *
+ * SAML 1.x assertion consumer service
  */
 
 #include "internal.h"
@@ -29,9 +29,9 @@
 # include "ServiceProvider.h"
 # include "SessionCache.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <saml/SAMLConfig.h>
 # include <saml/saml1/core/Assertions.h>
 # include <saml/saml1/core/Protocols.h>
-# include <saml/saml1/profile/BrowserSSOProfileValidator.h>
 # include <saml/saml2/metadata/Metadata.h>
 using namespace opensaml::saml1;
 using namespace opensaml::saml1p;
@@ -55,18 +55,25 @@ namespace shibsp {
     #pragma warning( push )
     #pragma warning( disable : 4250 )
 #endif
-    
+
     class SHIBSP_DLLLOCAL SAML1Consumer : public AssertionConsumerService
     {
     public:
         SAML1Consumer(const DOMElement* e, const char* appId)
-                : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.SAML1")) {
+            : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.SAML1")) {
 #ifndef SHIBSP_LITE
+            m_ssoRule = NULL;
             m_post = XMLString::equals(getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_POST);
+            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
+                m_ssoRule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(SAML1BROWSERSSO_POLICY_RULE, e);
 #endif
         }
-        virtual ~SAML1Consumer() {}
-        
+        virtual ~SAML1Consumer() {
+#ifndef SHIBSP_LITE
+            delete m_ssoRule;
+#endif
+        }
+
 #ifndef SHIBSP_LITE
         void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
             AssertionConsumerService::generateMetadata(role, handlerURL);
@@ -83,7 +90,9 @@ namespace shibsp {
             const PropertySet* settings,
             const XMLObject& xmlObject
             ) const;
+
         bool m_post;
+        SecurityPolicyRule* m_ssoRule;
 #endif
     };
 
@@ -95,7 +104,19 @@ namespace shibsp {
     {
         return new SAML1Consumer(p.first, p.second);
     }
-    
+
+#ifndef SHIBSP_LITE
+    class SHIBSP_DLLLOCAL _rulenamed : std::unary_function<const SecurityPolicyRule*,bool>
+    {
+    public:
+        _rulenamed(const char* name) : m_name(name) {}
+        bool operator()(const SecurityPolicyRule* rule) const {
+            return rule ? !strcmp(m_name, rule->getType()) : false;
+        }
+    private:
+        const char* m_name;
+    };
+#endif
 };
 
 #ifndef SHIBSP_LITE
@@ -125,7 +146,7 @@ void SAML1Consumer::implementProtocol(
             throw MetadataException("Security of SAML 1.x SSO POST response not established.");
         throw SecurityPolicyException("Security of SAML 1.x SSO POST response not established.");
     }
-        
+
     // Remember whether we already established trust.
     bool alreadySecured = policy.isAuthenticated();
 
@@ -158,10 +179,14 @@ void SAML1Consumer::implementProtocol(
     // Saves off error messages potentially helpful for users.
     string contextualError;
 
-    // Profile validator.
-    time_t now = time(NULL);
-    BrowserSSOProfileValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now);
+    // Ensure the BrowserSSO rule is in the policy set.
+    if (find_if(policy.getRules(), _rulenamed(SAML1BROWSERSSO_POLICY_RULE)) == NULL)
+        policy.getRules().push_back(m_ssoRule);
+
+    // Populate recipient as audience.
+    policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
 
+    time_t now = time(NULL);
     for (vector<saml1::Assertion*>::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) {
         try {
             // Skip unsigned assertion?
@@ -178,16 +203,14 @@ void SAML1Consumer::implementProtocol(
                 );
 
             // Run the policy over the assertion. Handles replay, freshness, and
-            // signature verification, assuming the relevant rules are configured.
-            policy.evaluate(*(*a));
-            
+            // signature verification, assuming the relevant rules are configured,
+            // along with condition and profile enforcement.
+            policy.evaluate(*(*a), &httpRequest);
+
             // If no security is in place now, we kick it.
             if (!alreadySecured && !policy.isAuthenticated())
                 throw SecurityPolicyException("Unable to establish security of incoming assertion.");
 
-            // Now do profile and core semantic validation to ensure we can use it for SSO.
-            ssoValidator.validateAssertion(*(*a));
-
             // Track it as a valid token.
             tokens.push_back(*a);
 
index ef85778..6b98392 100644 (file)
@@ -90,7 +90,7 @@ namespace shibsp {
 
         MessageEncoder* m_encoder;
         MessageDecoder* m_decoder;
-        QName m_role;
+        xmltooling::QName m_role;
 #endif
     };
 
@@ -121,7 +121,7 @@ SAML2ArtifactResolution::SAML2ArtifactResolution(const DOMElement* e, const char
                 getString("Binding").second,pair<const DOMElement*,const XMLCh*>(e,NULL)
                 );
         }
-        catch (exception& ex) {
+        catch (exception&) {
             m_log.error("error building MessageEncoder/Decoder pair for binding (%s)", getString("Binding").second);
             delete m_encoder;
             delete m_decoder;
index 0a2ebd8..532c0ac 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * SAML2Consumer.cpp
- * 
- * SAML 2.0 assertion consumer service 
+ *
+ * SAML 2.0 assertion consumer service
  */
 
 #include "internal.h"
 # include "ServiceProvider.h"
 # include "SessionCache.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
-# include <saml/saml2/profile/BrowserSSOProfileValidator.h>
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/saml2/profile/SAML2AssertionPolicy.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
@@ -52,15 +53,24 @@ namespace shibsp {
     #pragma warning( push )
     #pragma warning( disable : 4250 )
 #endif
-    
+
     class SHIBSP_DLLLOCAL SAML2Consumer : public AssertionConsumerService
     {
     public:
         SAML2Consumer(const DOMElement* e, const char* appId)
             : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.SAML2")) {
+#ifndef SHIBSP_LITE
+            m_ssoRule = NULL;
+            if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
+                m_ssoRule = SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(BEARER_POLICY_RULE, e);
+#endif
         }
-        virtual ~SAML2Consumer() {}
-        
+        virtual ~SAML2Consumer() {
+#ifndef SHIBSP_LITE
+            delete m_ssoRule;
+#endif
+        }
+
 #ifndef SHIBSP_LITE
         void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
             AssertionConsumerService::generateMetadata(role, handlerURL);
@@ -76,6 +86,8 @@ namespace shibsp {
             const PropertySet* settings,
             const XMLObject& xmlObject
             ) const;
+
+        SecurityPolicyRule* m_ssoRule;
 #endif
     };
 
@@ -87,7 +99,19 @@ namespace shibsp {
     {
         return new SAML2Consumer(p.first, p.second);
     }
-    
+
+#ifndef SHIBSP_LITE
+    class SHIBSP_DLLLOCAL _rulenamed : std::unary_function<const SecurityPolicyRule*,bool>
+    {
+    public:
+        _rulenamed(const char* name) : m_name(name) {}
+        bool operator()(const SecurityPolicyRule* rule) const {
+            return rule ? !strcmp(m_name, rule->getType()) : false;
+        }
+    private:
+        const char* m_name;
+    };
+#endif
 };
 
 #ifndef SHIBSP_LITE
@@ -109,7 +133,7 @@ void SAML2Consumer::implementProtocol(
     bool alreadySecured = policy.isAuthenticated();
 
     // Check for errors...this will throw if it's not a successful message.
-    checkError(&xmlObject);
+    checkError(&xmlObject, policy.getIssuerMetadata());
 
     const Response* response = dynamic_cast<const Response*>(&xmlObject);
     if (!response)
@@ -140,9 +164,6 @@ void SAML2Consumer::implementProtocol(
         flag = application.getRelyingParty(entity)->getBool("requireSignedAssertions");
     }
 
-    time_t now = time(NULL);
-    string dest = httpRequest.getRequestURL();
-
     // authnskew allows rejection of SSO if AuthnInstant is too old.
     const PropertySet* sessionProps = application.getPropertySet("Sessions");
     pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
@@ -150,6 +171,14 @@ void SAML2Consumer::implementProtocol(
     // Saves off error messages potentially helpful for users.
     string contextualError;
 
+    // Ensure the Bearer rule is in the policy set.
+    if (find_if(policy.getRules(), _rulenamed(BEARER_POLICY_RULE)) == NULL)
+        policy.getRules().push_back(m_ssoRule);
+
+    // Populate recipient as audience.
+    policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
+
+    time_t now = time(NULL);
     for (vector<saml2::Assertion*>::const_iterator a = assertions.begin(); a!=assertions.end(); ++a) {
         try {
             // Skip unsigned assertion?
@@ -164,9 +193,10 @@ void SAML2Consumer::implementProtocol(
             extractMessageDetails(*(*a), samlconstants::SAML20P_NS, policy);
 
             // Run the policy over the assertion. Handles replay, freshness, and
-            // signature verification, assuming the relevant rules are configured.
-            policy.evaluate(*(*a));
-            
+            // signature verification, assuming the relevant rules are configured,
+            // along with condition and profile enforcement.
+            policy.evaluate(*(*a), &httpRequest);
+
             // If no security is in place now, we kick it.
             if (!alreadySecured && !policy.isAuthenticated())
                 throw SecurityPolicyException("Unable to establish security of incoming assertion.");
@@ -179,14 +209,14 @@ void SAML2Consumer::implementProtocol(
                     throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
             }
 
-            // Now do profile and core semantic validation to ensure we can use it for SSO.
-            BrowserSSOProfileValidator ssoValidator(
-                application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now, dest.substr(0,dest.find('?')).c_str()
-                );
-            ssoValidator.validateAssertion(*(*a));
-
             // Address checking.
-            checkAddress(application, httpRequest, ssoValidator.getAddress());
+            SubjectConfirmationData* subcondata = dynamic_cast<SubjectConfirmationData*>(
+                dynamic_cast<SAML2AssertionPolicy&>(policy).getSubjectConfirmation()->getSubjectConfirmationData()
+                );
+            if (subcondata && subcondata->getAddress()) {
+                auto_ptr_char boundip(subcondata->getAddress());
+                checkAddress(application, httpRequest, boundip.get());
+            }
 
             // Track it as a valid token.
             tokens.push_back(*a);
@@ -241,10 +271,6 @@ void SAML2Consumer::implementProtocol(
             continue;
 
         try {
-            // Skip unsigned assertion?
-            if (!decrypted->getSignature() && flag.first && flag.second)
-                throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
-
             // We clear the security flag, so we can tell whether the token was secured on its own.
             policy.setAuthenticated(false);
             policy.reset(true);
@@ -253,24 +279,33 @@ void SAML2Consumer::implementProtocol(
             extractMessageDetails(*decrypted, samlconstants::SAML20P_NS, policy);
 
             // 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 and profile enforcement.
             // We have to marshall the object first to ensure signatures can be checked.
             if (!decrypted->getDOM())
                 decrypted->marshall();
-            policy.evaluate(*decrypted);
-            
+            policy.evaluate(*decrypted, &httpRequest);
+
             // If no security is in place now, we kick it.
             if (!alreadySecured && !policy.isAuthenticated())
                 throw SecurityPolicyException("Unable to establish security of incoming assertion.");
 
-            // Now do profile and core semantic validation to ensure we can use it for SSO.
-            BrowserSSOProfileValidator ssoValidator(
-                application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now, dest.substr(0,dest.find('?')).c_str()
-                );
-            ssoValidator.validateAssertion(*decrypted);
+            // If we hadn't established Issuer yet, redo the signedAssertions check.
+            if (!entity && policy.getIssuerMetadata()) {
+                entity = dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent());
+                flag = application.getRelyingParty(entity)->getBool("requireSignedAssertions");
+                if (!decrypted->getSignature() && flag.first && flag.second)
+                    throw SecurityPolicyException("The decrypted assertion was unsigned, violating local security policy.");
+            }
 
             // Address checking.
-            checkAddress(application, httpRequest, ssoValidator.getAddress());
+            SubjectConfirmationData* subcondata = dynamic_cast<SubjectConfirmationData*>(
+                dynamic_cast<SAML2AssertionPolicy&>(policy).getSubjectConfirmation()->getSubjectConfirmationData()
+                );
+            if (subcondata && subcondata->getAddress()) {
+                auto_ptr_char boundip(subcondata->getAddress());
+                checkAddress(application, httpRequest, boundip.get());
+            }
 
             // Track it as a valid token.
             tokens.push_back(decrypted);
@@ -341,7 +376,8 @@ void SAML2Consumer::implementProtocol(
     // Now we have to extract the authentication details for session setup.
 
     // Session expiration for SAML 2.0 is jointly IdP- and SP-driven.
-    time_t sessionExp = ssoStatement->getSessionNotOnOrAfter() ? ssoStatement->getSessionNotOnOrAfterEpoch() : 0;
+    time_t sessionExp = ssoStatement->getSessionNotOnOrAfter() ?
+        (ssoStatement->getSessionNotOnOrAfterEpoch() + XMLToolingConfig::getConfig().clock_skew_secs) : 0;
     pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
     if (!lifetime.first || lifetime.second == 0)
         lifetime.second = 28800;
index d917407..9a2e71a 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * SAML2Logout.cpp
- * 
+ *
  * Handles SAML 2.0 single logout protocol messages.
  */
 
@@ -55,7 +55,7 @@ namespace shibsp {
     #pragma warning( push )
     #pragma warning( disable : 4250 )
 #endif
-    
+
     class SHIBSP_DLLLOCAL SAML2Logout : public AbstractHandler, public LogoutHandler
     {
     public:
@@ -69,7 +69,7 @@ namespace shibsp {
             }
 #endif
         }
-        
+
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
@@ -109,7 +109,7 @@ namespace shibsp {
             bool front
             ) const;
 
-        QName m_role;
+        xmltooling::QName m_role;
         MessageDecoder* m_decoder;
         XMLCh* m_outgoing;
         vector<const XMLCh*> m_bindings;
@@ -133,8 +133,8 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
         ,m_role(samlconstants::SAML20MD_NS, IDPSSODescriptor::LOCAL_NAME), m_decoder(NULL), m_outgoing(NULL)
 #endif
 {
-#ifndef SHIBSP_LITE
     m_initiator = false;
+#ifndef SHIBSP_LITE
     m_preserve.push_back("ID");
     m_preserve.push_back("entityID");
     m_preserve.push_back("RelayState");
@@ -174,8 +174,14 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
                     MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
                         b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
                         );
-                    m_encoders[start] = encoder;
-                    m_log.debug("supporting outgoing front-channel binding (%s)", b.get());
+                    if (encoder->isUserAgentPresent()) {
+                        m_encoders[start] = encoder;
+                        m_log.debug("supporting outgoing binding (%s)", b.get());
+                    }
+                    else {
+                        delete encoder;
+                        m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                    }
                 }
                 catch (exception& ex) {
                     m_log.error("error building MessageEncoder: %s", ex.what());
@@ -233,7 +239,7 @@ void SAML2Logout::receive(DDF& in, ostream& out)
         m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
         throw ConfigurationException("Unable to locate application for logout, deleted?");
     }
-    
+
     // Unpack the request.
     auto_ptr<HTTPRequest> req(getRequest(in));
 
@@ -241,7 +247,7 @@ void SAML2Logout::receive(DDF& in, ostream& out)
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-    
+
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
@@ -324,7 +330,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
     pair<bool,const char*> policyId = getString("policyId", m_configNS.get());  // namespace-qualified if inside handler element
     if (!policyId.first)
         policyId = application.getString("policyId");   // unqualified in Application(s) element
-        
+
     // Access policy properties.
     const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId.second);
     pair<bool,bool> validate = settings->getBool("validate");
@@ -334,7 +340,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
 
     // Create the policy.
     shibsp::SecurityPolicy policy(application, &m_role, validate.first && validate.second);
-    
+
     // Decode the message.
     string relayState;
     auto_ptr<XMLObject> msg(m_decoder->decode(relayState, request, policy));
@@ -344,7 +350,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
             throw SecurityPolicyException("Security of LogoutRequest not established.");
 
         // Message from IdP to logout one or more sessions.
-        
+
         // If this is front-channel, we have to have a session_id to use already.
         if (m_decoder->isUserAgentPresent() && session_id.empty()) {
             m_log.error("no active session");
@@ -441,6 +447,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
             if (cacheex) {
                 time_t expires = logoutRequest->getNotOnOrAfter() ? logoutRequest->getNotOnOrAfterEpoch() : 0;
                 cacheex->logout(application, entity, *nameid, &indexes, expires, sessions);
+                m_log.debug("session cache returned %d sessions bound to NameID in logout request", sessions.size());
 
                 // Now we actually terminate everything except for the active session,
                 // if this is front-channel, for notification purposes.
@@ -482,17 +489,17 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
             if (result.first)
                 return result;
         }
-        
+
         // For back-channel requests, or if no front-channel notification is needed...
-        bool worked1 = false,worked2 = false;
-        worked1 = notifyBackChannel(application, request.getRequestURL(), sessions, false);
+        bool worked1 = notifyBackChannel(application, request.getRequestURL(), sessions, false);
+        bool worked2 = true;
         if (!session_id.empty()) {
             // One last session to yoink...
             try {
                 cache->remove(application, request, &response);
-                worked2 = true;
             }
             catch (exception& ex) {
+                worked2 = false;
                 m_log.error("error removing active session (%s): %s", session_id.c_str(), ex.what());
             }
         }
index e5a6bbb..249eb8f 100644 (file)
@@ -139,8 +139,14 @@ SAML2LogoutInitiator::SAML2LogoutInitiator(const DOMElement* e, const char* appI
                 auto_ptr_char b(start);
                 MessageEncoder * encoder =
                     SAMLConfig::getConfig().MessageEncoderManager.newPlugin(b.get(),pair<const DOMElement*,const XMLCh*>(e,NULL));
-                m_encoders[start] = encoder;
-                m_log.debug("supporting outgoing binding (%s)", b.get());
+                if (encoder->isUserAgentPresent()) {
+                    m_encoders[start] = encoder;
+                    m_log.debug("supporting outgoing binding (%s)", b.get());
+                }
+                else {
+                    delete encoder;
+                    m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                }
             }
             catch (exception& ex) {
                 m_log.error("error building MessageEncoder: %s", ex.what());
index 4aba9a6..3af13a5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,7 +16,7 @@
 
 /**
  * SAML2NameIDMgmt.cpp
- * 
+ *
  * Handles SAML 2.0 NameID management protocol messages.
  */
 
@@ -54,7 +54,7 @@ namespace shibsp {
     #pragma warning( push )
     #pragma warning( disable : 4250 )
 #endif
-    
+
     class SHIBSP_DLLLOCAL SAML2NameIDMgmt : public AbstractHandler, public RemotedHandler
     {
     public:
@@ -68,7 +68,7 @@ namespace shibsp {
             }
 #endif
         }
-        
+
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
@@ -110,7 +110,7 @@ namespace shibsp {
             bool front
             ) const;
 
-        QName m_role;
+        xmltooling::QName m_role;
         MessageDecoder* m_decoder;
         XMLCh* m_outgoing;
         vector<const XMLCh*> m_bindings;
@@ -170,8 +170,14 @@ SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
                     MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
                         b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
                         );
-                    m_encoders[start] = encoder;
-                    m_log.debug("supporting outgoing front-channel binding (%s)", b.get());
+                    if (encoder->isUserAgentPresent()) {
+                        m_encoders[start] = encoder;
+                        m_log.debug("supporting outgoing binding (%s)", b.get());
+                    }
+                    else {
+                        delete encoder;
+                        m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                    }
                 }
                 catch (exception& ex) {
                     m_log.error("error building MessageEncoder: %s", ex.what());
@@ -223,7 +229,7 @@ void SAML2NameIDMgmt::receive(DDF& in, ostream& out)
         m_log.error("couldn't find application (%s) for NameID mgmt", aid ? aid : "(missing)");
         throw ConfigurationException("Unable to locate application for NameID mgmt, deleted?");
     }
-    
+
     // Unpack the request.
     auto_ptr<HTTPRequest> req(getRequest(in));
 
@@ -231,7 +237,7 @@ void SAML2NameIDMgmt::receive(DDF& in, ostream& out)
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-    
+
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
@@ -250,7 +256,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
     pair<bool,const char*> policyId = getString("policyId", m_configNS.get());  // namespace-qualified if inside handler element
     if (!policyId.first)
         policyId = application.getString("policyId");   // unqualified in Application(s) element
-        
+
     // Access policy properties.
     const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId.second);
     pair<bool,bool> validate = settings->getBool("validate");
@@ -260,7 +266,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(
 
     // Create the policy.
     shibsp::SecurityPolicy policy(application, &m_role, validate.first && validate.second);
-    
+
     // Decode the message.
     string relayState;
     auto_ptr<XMLObject> msg(m_decoder->decode(relayState, request, policy));
@@ -533,6 +539,7 @@ pair<bool,long> SAML2NameIDMgmt::sendResponse(
 #include <xmltooling/impl/AnyElement.h>
 #include <xmltooling/soap/SOAP.h>
 #include <xmltooling/soap/SOAPClient.h>
+#include <xmltooling/soap/HTTPSOAPTransport.h>
 using namespace soap11;
 namespace {
     static const XMLCh NameIDNotification[] =   UNICODE_LITERAL_18(N,a,m,e,I,D,N,o,t,i,f,i,c,a,t,i,o,n);
@@ -545,6 +552,12 @@ namespace {
     private:
         void prepareTransport(SOAPTransport& transport) {
             transport.setVerifyHost(false);
+            HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(&transport);
+            if (http) {
+                http->useChunkedEncoding(false);
+                http->setRequestHeader("User-Agent", PACKAGE_NAME);
+                http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
+            }
         }
     };
 };
index 7121176..ae14e44 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * SAML2SessionInitiator.cpp
- * 
+ *
  * SAML 2.0 AuthnRequest support.
  */
 
@@ -66,20 +66,24 @@ namespace shibsp {
                 XMLString::release(&m_outgoing);
                 for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair<const XMLCh*,MessageEncoder>());
                 delete m_requestTemplate;
+                delete m_ecp;
             }
 #endif
         }
-        
+
         void setParent(const PropertySet* parent);
         void receive(DDF& in, ostream& out);
+        pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
     private:
         pair<bool,long> doRequest(
             const Application& application,
+            const HTTPRequest* httpRequest,
             HTTPResponse& httpResponse,
             const char* entityID,
             const XMLCh* acsIndex,
+            bool artifactInbound,
             const char* acsLocation,
             const XMLCh* acsBinding,
             bool isPassive,
@@ -170,8 +174,14 @@ SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* ap
                 MessageEncoder * encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
                     b.get(),pair<const DOMElement*,const XMLCh*>(e,NULL)
                     );
-                m_encoders[start] = encoder;
-                m_log.debug("supporting outgoing binding (%s)", b.get());
+                if (encoder->isUserAgentPresent()) {
+                    m_encoders[start] = encoder;
+                    m_log.debug("supporting outgoing binding (%s)", b.get());
+                }
+                else {
+                    delete encoder;
+                    m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                }
             }
             catch (exception& ex) {
                 m_log.error("error building MessageEncoder: %s", ex.what());
@@ -220,6 +230,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         return make_pair(false,0L);
 
     string target;
+    string postData;
     const Handler* ACS=NULL;
     const char* option;
     pair<bool,const char*> acClass;
@@ -245,7 +256,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         option = request.getParameter("target");
         if (option)
             target = option;
-            
+
         // Always need to recover target URL to compute handler below.
         recoverRelayState(request.getApplication(), request, request, target, false);
 
@@ -328,15 +339,33 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         }
     }
 
+    // Validate the ACS for use with this protocol.
+    if (!ECP) {
+        pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,NULL);
+        if (ACSbinding.first) {
+            pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
+            if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
+                m_log.info("configured or requested ACS has non-SAML 2.0 binding");
+                return make_pair(false,0L);
+            }
+            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);
+            }
+        }
+    }
+
     // To invoke the request builder, the key requirement is to figure out how
     // to express the ACS, by index or value, and if by value, where.
     // We have to compute the handlerURL no matter what, because we may need to
     // flip the index to an SSL-version.
     string ACSloc=request.getHandlerURL(target.c_str());
-    
+
     SPConfig& conf = SPConfig::getConfig();
     if (conf.isEnabled(SPConfig::OutOfProcess)) {
-       if (!acsByIndex.first || acsByIndex.second) {
+       if (acsByIndex.first && acsByIndex.second) {
             // Pass by Index.
             if (isHandler) {
                 // We may already have RelayState set if we looped back here,
@@ -346,7 +375,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
                 if (option)
                     target = option;
             }
-            
+
             // Determine index to use.
             pair<bool,const XMLCh*> ix = pair<bool,const XMLCh*>(false,NULL);
             if (ACS) {
@@ -359,10 +388,12 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
                        ix = ACS->getXMLString("index");
                }
             }
-            
+
             return doRequest(
-                app, request, entityID.c_str(),
-                ix.second, NULL, NULL,
+                app, &request, request, entityID.c_str(),
+                ix.second,
+                ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) : false,
+                NULL, NULL,
                 isPassive, forceAuthn,
                 acClass.first ? acClass.second : NULL,
                 acComp.first ? acComp.second : NULL,
@@ -385,8 +416,10 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         }
 
         return doRequest(
-            app, request, entityID.c_str(),
-            NULL, ACSloc.c_str(), ACS ? ACS->getXMLString("Binding").second : NULL,
+            app, &request, request, entityID.c_str(),
+            NULL,
+            ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) : false,
+            ACSloc.c_str(), ACS ? ACS->getXMLString("Binding").second : NULL,
             isPassive, forceAuthn,
             acClass.first ? acClass.second : NULL,
             acComp.first ? acComp.second : NULL,
@@ -408,7 +441,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         in.addmember("authnContextClassRef").string(acClass.second);
     if (acComp.first)
         in.addmember("authnContextComparison").string(acComp.second);
-    if (!acsByIndex.first || acsByIndex.second) {
+    if (acsByIndex.first && acsByIndex.second) {
         if (ACS) {
             // Determine index to use.
             pair<bool,const char*> ix = pair<bool,const char*>(false,NULL);
@@ -421,6 +454,8 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
                        ix = ACS->getString("index");
                }
             in.addmember("acsIndex").string(ix.second);
+            if (XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT))
+                in.addmember("artifact").integer(1);
         }
     }
     else {
@@ -429,8 +464,12 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
         if (loc.first) ACSloc+=loc.second;
         in.addmember("acsLocation").string(ACSloc.c_str());
-        if (ACS)
-            in.addmember("acsBinding").string(ACS->getString("Binding").second);
+        if (ACS) {
+            loc = ACS->getString("Binding");
+            in.addmember("acsBinding").string(loc.second);
+            if (XMLString::equals(loc.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT))
+                in.addmember("artifact").integer(1);
+        }
     }
 
     if (isHandler) {
@@ -442,13 +481,23 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
             target = option;
     }
     if (!target.empty())
-        in.addmember("RelayState").string(target.c_str());
+        in.addmember("RelayState").unsafe_string(target.c_str());
 
     // Remote the processing.
     out = request.getServiceProvider().getListenerService()->send(in);
     return unwrap(request, out);
 }
 
+pair<bool,long> SAML2SessionInitiator::unwrap(SPRequest& request, DDF& out) const
+{
+    // See if there's any response to send back.
+    if (!out["redirect"].isnull() || !out["response"].isnull()) {
+        // If so, we're responsible for handling the POST data, probably by dropping a cookie.
+        preservePostData(request.getApplication(), request, request, out["RelayState"].string());
+    }
+    return RemotedHandler::unwrap(request, out);
+}
+
 void SAML2SessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
@@ -470,17 +519,23 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
     auto_ptr_XMLCh bind(in["acsBinding"].string());
 
     string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
+    string postData(in["PostData"].string() ? in["PostData"].string() : "");
 
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
     doRequest(
-        *app, *http.get(), in["entity_id"].string(),
-        index.get(), in["acsLocation"].string(), bind.get(),
+        *app, NULL, *http.get(), in["entity_id"].string(),
+        index.get(),
+        (in["artifact"].integer() != 0),
+        in["acsLocation"].string(), bind.get(),
         in["isPassive"].integer()==1, in["forceAuthn"].integer()==1,
         in["authnContextClassRef"].string(), in["authnContextComparison"].string(),
         relayState
         );
+    if (!ret.isstruct())
+        ret.structure();
+    ret.addmember("RelayState").unsafe_string(relayState.c_str());
     out << ret;
 }
 
@@ -498,9 +553,11 @@ namespace {
 
 pair<bool,long> SAML2SessionInitiator::doRequest(
     const Application& app,
+    const HTTPRequest* httpRequest,
     HTTPResponse& httpResponse,
     const char* entityID,
     const XMLCh* acsIndex,
+    bool artifactInbound,
     const char* acsLocation,
     const XMLCh* acsBinding,
     bool isPassive,
@@ -521,7 +578,7 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
     // We won't need this for ECP, but safety dictates we get the lock here.
     MetadataProvider* m=app.getMetadataProvider();
     Locker locker(m);
-    
+
     if (ECP) {
         encoder = m_ecp;
         if (!encoder) {
@@ -538,11 +595,17 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
             throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
         }
         else if (!entity.second) {
-            m_log.warn("unable to locate SAML 2.0 identity provider role for provider (%s)", entityID);
+            m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate SAML 2.0 identity provider role for provider (%s)", entityID);
             if (getParent())
                 return make_pair(false,0L);
             throw MetadataException("Unable to locate SAML 2.0 identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
         }
+        else if (artifactInbound && !SPConfig::getConfig().getArtifactResolver()->isSupported(dynamic_cast<const SSODescriptorType&>(*entity.second))) {
+            m_log.warn("artifact binding selected for response, but identity provider lacks support");
+            if (getParent())
+                return make_pair(false,0L);
+            throw MetadataException("Identity provider ($entityID) lacks SAML 2.0 artifact support.", namedparams(1, "entityID", entityID));
+        }
 
         // Loop over the supportable outgoing bindings.
         role = dynamic_cast<const IDPSSODescriptor*>(entity.second);
@@ -609,7 +672,7 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
             cref->setReference(wideclass.get());
             reqContext->getAuthnContextClassRefs().push_back(cref);
         }
-        
+
         if (reqContext->getAuthnContextClassRefs().empty() && reqContext->getAuthnContextDeclRefs().empty()) {
                req->setRequestedAuthnContext(NULL);
         }
@@ -619,6 +682,24 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
         }
     }
 
+    pair<bool,bool> requestDelegation = getBool("requestDelegation");
+    if (requestDelegation.first && requestDelegation.second && entity.first) {
+        // Request delegation by including the IdP as an Audience.
+        // Also specify the expected session lifetime as the bound on the assertion lifetime.
+        const PropertySet* sessionProps = app.getPropertySet("Sessions");
+        pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
+        if (!lifetime.first || lifetime.second == 0)
+            lifetime.second = 28800;
+        if (!req->getConditions())
+            req->setConditions(ConditionsBuilder::buildConditions());
+        req->getConditions()->setNotOnOrAfter(time(NULL) + lifetime.second + 300);
+        AudienceRestriction* audrest = AudienceRestrictionBuilder::buildAudienceRestriction();
+        req->getConditions()->getConditions().push_back(audrest);
+        Audience* aud = AudienceBuilder::buildAudience();
+        audrest->getAudiences().push_back(aud);
+        aud->setAudienceURI(entity.first->getEntityID());
+    }
+
     if (ECP && entityID) {
         auto_ptr_XMLCh wideid(entityID);
         Scoping* scoping = req->getScoping();
@@ -641,6 +722,11 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
 
     auto_ptr_char dest(ep ? ep->getLocation() : NULL);
 
+    if (httpRequest) {
+        // If the request object is available, we're responsible for the POST data.
+        preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
+    }
+
     long ret = sendMessage(
         *encoder, req.get(), relayState.c_str(), dest.get(), role, app, httpResponse, role ? role->WantAuthnRequestsSigned() : false
         );
index 90d189c..5ff0878 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * SAMLDSSessionInitiator.cpp
- * 
+ *
  * SAML Discovery Service support.
  */
 
@@ -65,7 +65,7 @@ namespace shibsp {
                 m_returnParam = url.second;
         }
         virtual ~SAMLDSSessionInitiator() {}
-        
+
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
 #ifndef SHIBSP_LITE
@@ -78,11 +78,11 @@ namespace shibsp {
             hurl += loc;
             auto_ptr_XMLCh widen(hurl.c_str());
             ElementProxy* ep = new AnyElementImpl(m_discoNS.get(), LOCAL_NAME);
-            ep->setAttribute(QName(NULL,EndpointType::LOCATION_ATTRIB_NAME), widen.get());
-            ep->setAttribute(QName(NULL,EndpointType::BINDING_ATTRIB_NAME), getXMLString("Binding").second);
+            ep->setAttribute(xmltooling::QName(NULL,EndpointType::LOCATION_ATTRIB_NAME), widen.get());
+            ep->setAttribute(xmltooling::QName(NULL,EndpointType::BINDING_ATTRIB_NAME), m_discoNS.get());
             pair<bool,const XMLCh*> ix = getXMLString("index");
-            ep->setAttribute(QName(NULL,IndexedEndpointType::INDEX_ATTRIB_NAME), ix.first ? ix.second : xmlconstants::XML_ONE);
-            
+            ep->setAttribute(xmltooling::QName(NULL,IndexedEndpointType::INDEX_ATTRIB_NAME), ix.first ? ix.second : xmlconstants::XML_ONE);
+
             Extensions* ext = role.getExtensions();
             if (!ext) {
                 ext = ExtensionsBuilder::buildExtensions();
@@ -131,7 +131,7 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
             ex.addProperty("statusCode2", "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP");
             ex.raise();
         }
-        
+
         option = request.getParameter("target");
         if (option)
             target = option;
@@ -166,6 +166,8 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
             target = option;
     }
     preserveRelayState(request.getApplication(), request, target);
+    if (!isHandler)
+        preservePostData(request.getApplication(), request, request, target.c_str());
 
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
     if (isHandler) {
index 789793c..813aad9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,7 +16,7 @@
 
 /**
  * SessionHandler.cpp
- * 
+ *
  * Handler for dumping information about an active session.
  */
 
@@ -45,7 +45,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
@@ -102,7 +107,7 @@ pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
     if (!m_acl.empty() && m_acl.count(request.getRemoteAddr()) == 0) {
         m_log.error("session handler request blocked from invalid address (%s)", request.getRemoteAddr().c_str());
         istringstream msg("Session Handler Blocked");
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_UNAUTHORIZED));
+        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
     }
 
     stringstream s;
@@ -186,7 +191,7 @@ pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
 
     if (!m_values && !attributes.empty())
         s << count << " value(s)" << endl;
-    
+
     s << "</pre></body></html>";
     request.setContentType("text/html; charset=UTF-8");
     request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
index aeda3c7..c9de163 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * Shib1SessionInitiator.cpp
- * 
+ *
  * Shibboleth 1.x AuthnRequest support.
  */
 
@@ -64,17 +64,20 @@ namespace shibsp {
             }
         }
         virtual ~Shib1SessionInitiator() {}
-        
+
         void setParent(const PropertySet* parent);
         void receive(DDF& in, ostream& out);
+        pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
     private:
         pair<bool,long> doRequest(
             const Application& application,
+            const HTTPRequest* httpRequest,
             HTTPResponse& httpResponse,
             const char* entityID,
             const char* acsLocation,
+            bool artifact,
             string& relayState
             ) const;
         string m_appId;
@@ -111,6 +114,7 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
         return make_pair(false,0L);
 
     string target;
+    string postData;
     const Handler* ACS=NULL;
     const char* option;
     const Application& app=request.getApplication();
@@ -149,6 +153,21 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
             ACS = app.getDefaultAssertionConsumerService();
     }
 
+    // Validate the ACS for use with this protocol.
+    pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,NULL);
+    if (ACSbinding.first) {
+        pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
+        if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
+            m_log.info("configured or requested ACS has non-SAML 1.x binding");
+            return make_pair(false,0L);
+        }
+        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);
+        }
+    }
+
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
     string ACSloc=request.getHandlerURL(target.c_str());
     pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
@@ -163,10 +182,17 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
             target = option;
     }
 
+    // Is the in-bound binding artifact?
+    bool artifactInbound = ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT) : false;
+
     m_log.debug("attempting to initiate session using Shibboleth with provider (%s)", entityID.c_str());
 
-    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
-        return doRequest(app, request, entityID.c_str(), ACSloc.c_str(), target);
+    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
+        // Out of process means the POST data via the request can be exposed directly to the private method.
+        // The method will handle POST preservation if necessary *before* issuing the response, but only if
+        // it dispatches to an IdP.
+        return doRequest(app, &request, request, entityID.c_str(), ACSloc.c_str(), artifactInbound, target);
+    }
 
     // Remote the call.
     DDF out,in = DDF(m_address.c_str()).structure();
@@ -174,14 +200,26 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
     in.addmember("application_id").string(app.getId());
     in.addmember("entity_id").string(entityID.c_str());
     in.addmember("acsLocation").string(ACSloc.c_str());
+    if (artifactInbound)
+        in.addmember("artifact").integer(1);
     if (!target.empty())
-        in.addmember("RelayState").string(target.c_str());
+        in.addmember("RelayState").unsafe_string(target.c_str());
 
-    // Remote the processing.
+    // Remote the processing. Our unwrap method will handle POST data if necessary.
     out = request.getServiceProvider().getListenerService()->send(in);
     return unwrap(request, out);
 }
 
+pair<bool,long> Shib1SessionInitiator::unwrap(SPRequest& request, DDF& out) const
+{
+    // See if there's any response to send back.
+    if (!out["redirect"].isnull() || !out["response"].isnull()) {
+        // If so, we're responsible for handling the POST data, probably by dropping a cookie.
+        preservePostData(request.getApplication(), request, request, out["RelayState"].string());
+    }
+    return RemotedHandler::unwrap(request, out);
+}
+
 void Shib1SessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
@@ -209,15 +247,20 @@ void Shib1SessionInitiator::receive(DDF& in, ostream& out)
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, *http.get(), entityID, acsLocation, relayState);
+    doRequest(*app, NULL, *http.get(), entityID, acsLocation, (in["artifact"].integer() != 0), relayState);
+    if (!ret.isstruct())
+        ret.structure();
+    ret.addmember("RelayState").unsafe_string(relayState.c_str());
     out << ret;
 }
 
 pair<bool,long> Shib1SessionInitiator::doRequest(
     const Application& app,
+    const HTTPRequest* httpRequest,
     HTTPResponse& httpResponse,
     const char* entityID,
     const char* acsLocation,
+    bool artifact,
     string& relayState
     ) const
 {
@@ -232,11 +275,18 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
         throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
     }
     else if (!entity.second) {
-        m_log.warn("unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
+        m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
         if (getParent())
             return make_pair(false,0L);
         throw MetadataException("Unable to locate Shibboleth-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
     }
+    else if (artifact && !SPConfig::getConfig().getArtifactResolver()->isSupported(dynamic_cast<const SSODescriptorType&>(*entity.second))) {
+        m_log.warn("artifact profile selected for response, but identity provider lacks support");
+        if (getParent())
+            return make_pair(false,0L);
+        throw MetadataException("Identity provider ($entityID) lacks SAML artifact support.", namedparams(1, "entityID", entityID));
+    }
+
     const EndpointType* ep=EndpointManager<SingleSignOnService>(
         dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleSignOnServices()
         ).getByBinding(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI);
@@ -261,6 +311,11 @@ pair<bool,long> Shib1SessionInitiator::doRequest(
         "&time=" + timebuf + "&target=" + urlenc->encode(relayState.c_str()) +
         "&providerId=" + urlenc->encode(app.getRelyingParty(entity.first)->getString("entityID").second);
 
+    if (httpRequest) {
+        // If the request object is available, we're responsible for the POST data.
+        preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
+    }
+
     return make_pair(true, httpResponse.sendRedirect(req.c_str()));
 #else
     return make_pair(false,0L);
index 41e9f1f..b9e066d 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * StatusHandler.cpp
- * 
+ *
  * Handler for exposing information about the internals of the SP.
  */
 
@@ -50,7 +50,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
@@ -146,17 +151,6 @@ namespace shibsp {
                     m_uri += slash;
                     break;
                 }
-                else if (*slash == ';') {
-                    // If this is Java being stupid, skip everything up to the query string, if any.
-                    if (!strncmp(slash, ";jsessionid=", 12)) {
-                        if (slash = strchr(slash, '?'))
-                            m_uri += slash;
-                        break;
-                    }
-                    else {
-                        m_uri += *slash;
-                    }
-                }
                 else if (*slash != '%') {
                     m_uri += *slash;
                 }
@@ -215,7 +209,7 @@ namespace shibsp {
         {
             if (!m_parser)
                 m_parser=new CGIParser(*this);
-            
+
             pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
             return (bounds.first==bounds.second) ? NULL : bounds.first->second;
         }
@@ -238,7 +232,7 @@ namespace shibsp {
 #ifndef XMLTOOLING_NO_XMLSEC
             std::vector<XSECCryptoX509*>&
 #else
-            std::vector<std::string>& 
+            std::vector<std::string>&
 #endif
             getClientCertificates() const {
                 return g_NoCerts;
@@ -283,7 +277,7 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
         if (!m_acl.empty() && m_acl.count(request.getRemoteAddr()) == 0) {
             m_log.error("status handler request blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Status Handler Blocked");
-            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_UNAUTHORIZED));
+            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
         }
     }
 
@@ -312,7 +306,7 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
         msg << "</StatusHandler>";
         return make_pair(true,request.sendResponse(msg));
     }
-    
+
     try {
         if (conf.isEnabled(SPConfig::OutOfProcess)) {
             // When out of process, we run natively and directly process the message.
@@ -321,7 +315,7 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
         else {
             // When not out of process, we remote all the message processing.
             DDF out,in = wrap(request);
-            DDFJanitor jin(in), jout(out);            
+            DDFJanitor jin(in), jout(out);
             out=request.getServiceProvider().getListenerService()->send(in);
             return unwrap(request, out);
         }
@@ -368,13 +362,13 @@ void StatusHandler::receive(DDF& in, ostream& out)
         m_log.error("couldn't find application (%s) for status request", aid ? aid : "(missing)");
         throw ConfigurationException("Unable to locate application for status request, deleted?");
     }
-    
+
     // Wrap a response shim.
     DDF ret(NULL);
     DDFJanitor jout(ret);
     auto_ptr<HTTPRequest> req(getRequest(in));
     auto_ptr<HTTPResponse> resp(getResponse(ret));
-        
+
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
index 36759f3..390d3d8 100644 (file)
@@ -55,7 +55,12 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL TransformSINodeFilter : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
index 19510ec..f0e075d 100644 (file)
@@ -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.
@@ -80,6 +80,7 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
         return make_pair(false,0L);
 
     string target;
+    string postData;
     const char* option;
     const Handler* ACS=NULL;
     const Application& app=request.getApplication();
@@ -115,6 +116,21 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
             ACS = app.getDefaultAssertionConsumerService();
     }
 
+    // Validate the ACS for use with this protocol.
+    pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,NULL);
+    if (ACSbinding.first) {
+        pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
+        if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
+            m_log.info("configured or requested ACS has non-SAML 1.x binding");
+            return make_pair(false,0L);
+        }
+        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.debug("sending request to WAYF (%s)", m_url);
 
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
@@ -130,6 +146,8 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
             target = option;
     }
     preserveRelayState(request.getApplication(), request, target);
+    if (!isHandler)
+        preservePostData(request.getApplication(), request, request, target.c_str());
 
     // WAYF requires a target value.
     if (target.empty())
diff --git a/shibsp/impl/ChainingAccessControl.cpp b/shibsp/impl/ChainingAccessControl.cpp
new file mode 100644 (file)
index 0000000..8b73906
--- /dev/null
@@ -0,0 +1,136 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ChainingAccessControl.cpp\r
+ *\r
+ * Access control plugin that combines other plugins.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "AccessControl.h"\r
+#include "SessionCache.h"\r
+#include "SPRequest.h"\r
+\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+\r
+    class ChainingAccessControl : public AccessControl\r
+    {\r
+    public:\r
+        ChainingAccessControl(const DOMElement* e);\r
+\r
+        ~ChainingAccessControl() {\r
+            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
+        }\r
+\r
+        Lockable* lock() {\r
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));\r
+            return this;\r
+        }\r
+        void unlock() {\r
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));\r
+        }\r
+\r
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
+\r
+    private:\r
+        enum operator_t { OP_AND, OP_OR } m_op;\r
+        vector<AccessControl*> m_ac;\r
+    };\r
+\r
+    AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)\r
+    {\r
+        return new ChainingAccessControl(e);\r
+    }\r
+\r
+    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+    static const XMLCh _operator[] =        UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);\r
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
+\r
+    extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);\r
+}\r
+\r
+void SHIBSP_API shibsp::registerAccessControls()\r
+{\r
+    SPConfig& conf=SPConfig::getConfig();\r
+    conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);\r
+    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
+    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
+}\r
+\r
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)\r
+{\r
+    const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;\r
+    if (XMLString::equals(op, AND))\r
+        m_op=OP_AND;\r
+    else if (XMLString::equals(op, OR))\r
+        m_op=OP_OR;\r
+    else\r
+        throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");\r
+\r
+    try {\r
+        e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;\r
+        while (e) {\r
+            auto_ptr_char type(e->getAttributeNS(NULL, _type));\r
+            if (type.get() && *type.get()) {\r
+                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());\r
+                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));\r
+            }\r
+            e = XMLHelper::getNextSiblingElement(e, _AccessControl);\r
+        }\r
+    }\r
+    catch (exception&) {\r
+        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
+        throw;\r
+    }\r
+    if (m_ac.empty())\r
+        throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");\r
+}\r
+\r
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const\r
+{\r
+    switch (m_op) {\r
+        case OP_AND:\r
+        {\r
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
+                if ((*i)->authorized(request, session) != shib_acl_true)\r
+                    return shib_acl_false;\r
+            }\r
+            return shib_acl_true;\r
+        }\r
+\r
+        case OP_OR:\r
+        {\r
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
+                if ((*i)->authorized(request,session) == shib_acl_true)\r
+                    return shib_acl_true;\r
+            }\r
+            return shib_acl_false;\r
+        }\r
+    }\r
+    request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");\r
+    return shib_acl_false;\r
+}\r
index cb51042..27f7610 100644 (file)
@@ -847,7 +847,7 @@ void SSCache::insert(const char* key, time_t expires, const char* name, const ch
     }
     else {
         // New record.
-        obj.structure();
+        obj = DDF(NULL).structure();
     }
 
     if (!index || !*index)
index 939ea68..5d9d352 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  *  Copyright 2001-2007 Internet2\r
- * \r
+ *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
  * You may obtain a copy of the License at\r
@@ -40,8 +40,8 @@ using namespace shibsp;
 using namespace xmltooling;\r
 using namespace std;\r
 \r
-namespace {\r
-    \r
+namespace shibsp {\r
+\r
     class Rule : public AccessControl\r
     {\r
     public:\r
@@ -52,12 +52,12 @@ namespace {
         void unlock() {}\r
 \r
         aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-    \r
+\r
     private:\r
         string m_alias;\r
         vector <string> m_vals;\r
     };\r
-    \r
+\r
     class RuleRegex : public AccessControl\r
     {\r
     public:\r
@@ -65,18 +65,18 @@ namespace {
         ~RuleRegex() {\r
             delete m_re;\r
         }\r
-        \r
+\r
         Lockable* lock() {return this;}\r
         void unlock() {}\r
 \r
         aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-        \r
+\r
     private:\r
         string m_alias;\r
         auto_arrayptr<char> m_exp;\r
         RegularExpression* m_re;\r
     };\r
-    \r
+\r
     class Operator : public AccessControl\r
     {\r
     public:\r
@@ -87,7 +87,7 @@ namespace {
         void unlock() {}\r
 \r
         aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-        \r
+\r
     private:\r
         enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
         vector<AccessControl*> m_operands;\r
@@ -102,10 +102,10 @@ namespace {
     {\r
     public:\r
         XMLAccessControl(const DOMElement* e)\r
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl")), m_rootAuthz(NULL) {\r
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {\r
             load(); // guarantees an exception or the policy is loaded\r
         }\r
-        \r
+\r
         ~XMLAccessControl() {\r
             delete m_rootAuthz;\r
         }\r
@@ -140,13 +140,6 @@ namespace {
     static const XMLCh _RuleRegex[] =       UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
 }\r
 \r
-void SHIBSP_API shibsp::registerAccessControls()\r
-{\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
-    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
-}\r
-\r
 Rule::Rule(const DOMElement* e)\r
 {\r
     auto_ptr_char req(e->getAttributeNS(NULL,require));\r
@@ -157,14 +150,14 @@ Rule::Rule(const DOMElement* e)
     auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
     if (!vals.get())\r
         return;\r
-    \r
+\r
     const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
     if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
         if (*vals.get())\r
             m_vals.push_back(vals.get());\r
         return;\r
     }\r
-    \r
+\r
 #ifdef HAVE_STRTOK_R\r
     char* pos=NULL;\r
     const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
@@ -191,7 +184,7 @@ AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Sess
         request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
         return shib_acl_false;\r
     }\r
-    \r
+\r
     if (m_alias == "valid-user") {\r
         if (session) {\r
             request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
@@ -261,11 +254,11 @@ RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e-
     if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
         throw ConfigurationException("Access control rule missing require attribute or element content.");\r
     m_alias=req.get();\r
-    \r
+\r
     const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
     bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
     try {\r
-        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); \r
+        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));\r
     }\r
     catch (XMLException& ex) {\r
         auto_ptr_char tmp(ex.getMessage());\r
@@ -280,7 +273,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
         request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
         return shib_acl_false;\r
     }\r
-    \r
+\r
     if (m_alias == "valid-user") {\r
         if (session) {\r
             request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
@@ -335,7 +328,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
         auto_ptr_char tmp(ex.getMessage());\r
         request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
     }\r
-    \r
+\r
     return shib_acl_false;\r
 }\r
 \r
@@ -349,7 +342,7 @@ Operator::Operator(const DOMElement* e)
         m_op=OP_OR;\r
     else\r
         throw ConfigurationException("Unrecognized operator in access control rule");\r
-    \r
+\r
     try {\r
         e=XMLHelper::getFirstChildElement(e);\r
         if (XMLString::equals(e->getLocalName(),_Rule))\r
@@ -358,10 +351,10 @@ Operator::Operator(const DOMElement* e)
             m_operands.push_back(new RuleRegex(e));\r
         else\r
             m_operands.push_back(new Operator(e));\r
-        \r
+\r
         if (m_op==OP_NOT)\r
             return;\r
-        \r
+\r
         e=XMLHelper::getNextSiblingElement(e);\r
         while (e) {\r
             if (XMLString::equals(e->getLocalName(),_Rule))\r
@@ -396,7 +389,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
                 default:\r
                     return shib_acl_indeterminate;\r
             }\r
-        \r
+\r
         case OP_AND:\r
         {\r
             for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
@@ -405,7 +398,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
             }\r
             return shib_acl_true;\r
         }\r
-        \r
+\r
         case OP_OR:\r
         {\r
             for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
@@ -423,14 +416,14 @@ pair<bool,DOMElement*> XMLAccessControl::load()
 {\r
     // Load from source using base class.\r
     pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
-    \r
+\r
     // If we own it, wrap it.\r
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
 \r
     // Check for AccessControl wrapper and drop a level.\r
     if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
         raw.second = XMLHelper::getFirstChildElement(raw.second);\r
-    \r
+\r
     AccessControl* authz;\r
     if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
         authz=new Rule(raw.second);\r
index 9c5f294..78e6edf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -15,7 +15,7 @@
  */
 
 /** XMLRequestMapper.cpp
- * 
+ *
  * XML-based RequestMapper implementation
  */
 
@@ -39,16 +39,16 @@ using namespace std;
 
 namespace shibsp {
 
-    // Blocks access when an ACL plugin fails to load. 
+    // Blocks access when an ACL plugin fails to load.
     class AccessControlDummy : public AccessControl
     {
     public:
         Lockable* lock() {
             return this;
         }
-        
+
         void unlock() {}
-    
+
         aclresult_t authorized(const SPRequest& request, const Session* session) const {
             return shib_acl_false;
         }
@@ -62,20 +62,25 @@ namespace shibsp {
         ~Override();
 
         // Provides filter to exclude special config elements.
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
 
         const Override* locate(const HTTPRequest& request) const;
         AccessControl* getAC() const { return (m_acl ? m_acl : (getParent() ? dynamic_cast<const Override*>(getParent())->getAC() : NULL)); }
-        
+
     protected:
         void loadACL(const DOMElement* e, Category& log);
-        
+
         map<string,Override*> m_map;
         vector< pair<RegularExpression*,Override*> > m_regexps;
         vector< pair< pair<string,RegularExpression*>,Override*> > m_queries;
-    
+
     private:
         AccessControl* m_acl;
     };
@@ -93,10 +98,10 @@ namespace shibsp {
         void setDocument(DOMDocument* doc) {
             m_document = doc;
         }
-    
+
         const Override* findOverride(const char* vhost, const HTTPRequest& request) const;
 
-    private:    
+    private:
         map<string,Override*> m_extras;
         DOMDocument* m_document;
     };
@@ -193,19 +198,19 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
         // Load the property set.
         load(e,NULL,this);
         setParent(base);
-        
+
         // Load any AccessControl provider.
         loadACL(e,log);
-    
+
         // Handle nested Paths.
         DOMElement* path = XMLHelper::getFirstChildElement(e,Path);
         for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) {
             const XMLCh* n=path->getAttributeNS(NULL,name);
-            
+
             // Skip any leading slashes.
             while (n && *n==chForwardSlash)
                 n++;
-            
+
             // Check for empty name.
             if (!n || !*n) {
                 log.warn("skipping Path element (%d) with empty name attribute", i);
@@ -220,14 +225,14 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
                 for (int pos=0; pos < slash; pos++)
                     namebuf[pos]=n[pos];
                 namebuf[slash]=chNull;
-                
+
                 // Move past the slash in the original pathname.
                 n=n+slash+1;
-                
+
                 // Skip any leading slashes again.
                 while (*n==chForwardSlash)
                     n++;
-                
+
                 if (*n) {
                     // Create a placeholder Path element for the first path segment and replant under it.
                     DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,Path);
@@ -235,7 +240,7 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
                     path->setAttributeNS(NULL,name,n);
                     path->getParentNode()->replaceChild(newpath,path);
                     newpath->appendChild(path);
-                    
+
                     // Repoint our locals at the new parent.
                     path=newpath;
                     n=path->getAttributeNS(NULL,name);
@@ -247,7 +252,7 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
                 }
                 delete[] namebuf;
             }
-            
+
             Override* o=new Override(path,log,this);
             pair<bool,const char*> name=o->getString("name");
             char* dup=strdup(name.second);
@@ -317,7 +322,7 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
                 log.error("caught exception while parsing Query regular expression (%d): %s", i, tmp.get());
                 throw ConfigurationException("Invalid regular expression in Query element.");
             }
-            
+
             log.debug("added <Query> mapping (%s)", ntemp.get());
         }
     }
@@ -384,7 +389,7 @@ const Override* Override::locate(const HTTPRequest& request) const
             break;  // Once there's no match, we've consumed as much of the path as possible here.
         // We found a match, so reset the settings pointer.
         o=i->second;
-        
+
         // We descended a step down the path, so we need to advance the original
         // parameter for the regex step later.
         path += strlen(token);
@@ -451,7 +456,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
 
     // Load the property set.
     load(e,NULL,this);
-    
+
     // Load any AccessControl provider.
     loadACL(e,log);
 
@@ -489,12 +494,12 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
             log.warn("Skipping Host element (%d) with empty name attribute",i);
             continue;
         }
-        
+
         Override* o=new Override(host,log,this);
         pair<bool,const char*> name=o->getString("name");
         pair<bool,const char*> scheme=o->getString("scheme");
         pair<bool,const char*> port=o->getString("port");
-        
+
         char* dup=strdup(name.second);
         for (char* pch=dup; *pch; pch++)
             *pch=tolower(*pch);
@@ -523,7 +528,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
         if (scheme.first) {
             string url(scheme.second);
             url=url + "://" + dup;
-            
+
             // Is this the default port?
             if ((!strcmp(scheme.second,"http") && !strcmp(port.second,"80")) ||
                 (!strcmp(scheme.second,"https") && !strcmp(port.second,"443")) ||
@@ -538,7 +543,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
                 }
                 m_map[url]=o;
                 log.debug("Added <Host> mapping for %s",url.c_str());
-                
+
                 // Now append the port. We use the extras vector, to avoid double freeing the object later.
                 url=url + ':' + port.second;
                 m_extras[url]=o;
@@ -566,7 +571,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
             }
             m_map[url]=o;
             log.debug("Added <Host> mapping for %s",url.c_str());
-            
+
             url = url + ":80";
             if (m_map.count(url) || m_extras.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
@@ -574,7 +579,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
             }
             m_extras[url]=o;
             log.debug("Added <Host> mapping for %s",url.c_str());
-            
+
             url = "https://";
             url = url + dup;
             if (m_map.count(url) || m_extras.count(url)) {
@@ -583,7 +588,7 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
             }
             m_extras[url]=o;
             log.debug("Added <Host> mapping for %s",url.c_str());
-            
+
             url = url + ":443";
             if (m_map.count(url) || m_extras.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
@@ -612,7 +617,7 @@ const Override* XMLRequestMapperImpl::findOverride(const char* vhost, const HTTP
             }
         }
     }
-    
+
     return o ? o->locate(request) : this;
 }
 
@@ -620,12 +625,12 @@ pair<bool,DOMElement*> XMLRequestMapper::load()
 {
     // Load from source using base class.
     pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-    
+
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
 
     XMLRequestMapperImpl* impl = new XMLRequestMapperImpl(raw.second,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());
 
@@ -639,16 +644,6 @@ RequestMapper::Settings XMLRequestMapper::getSettings(const HTTPRequest& request
 {
     ostringstream vhost;
     vhost << request.getScheme() << "://" << request.getHostname() << ':' << request.getPort();
-
     const Override* o=m_impl->findOverride(vhost.str().c_str(), request);
-
-    if (m_log.isDebugEnabled()) {
-#ifdef _DEBUG
-        xmltooling::NDC ndc("getSettings");
-#endif
-        pair<bool,const char*> ret=o->getString("applicationId");
-        m_log.debug("mapped %s%s to %s", vhost.str().c_str(), request.getRequestURI() ? request.getRequestURI() : "", ret.second);
-    }
-
     return Settings(o,o->getAC());
 }
index fb16a21..5b9de5f 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
 
 #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"
 #endif
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/version.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/TemplateEngine.h>
 #include <xmltooling/util/XMLHelper.h>
 
 #ifndef SHIBSP_LITE
 # include "attribute/resolver/AttributeResolver.h"
 # include "security/PKIXTrustEngine.h"
 # include <saml/SAMLConfig.h>
+# include <saml/version.h>
 # include <saml/binding/ArtifactMap.h>
 # include <saml/binding/SAMLArtifact.h>
 # include <saml/saml1/core/Assertions.h>
 # include <saml/saml2/binding/SAML2ArtifactType0004.h>
-# include <saml/saml2/metadata/ChainingMetadataProvider.h>
-# include <xmltooling/security/ChainingTrustEngine.h>
 # include <xmltooling/util/ReplayCache.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
@@ -70,6 +73,10 @@ 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)
@@ -85,7 +92,7 @@ namespace {
     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
@@ -135,6 +142,10 @@ namespace {
             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;
@@ -156,12 +167,18 @@ namespace {
         }
 
         // Provides filter to exclude special config elements.
-        short acceptNode(const DOMNode* node) const;
-    
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const;
+
     private:
         void cleanup();
         const XMLApplication* m_base;
         string m_hash;
+        std::pair<std::string,std::string> m_attributePrefix;
 #ifndef SHIBSP_LITE
         MetadataProvider* m_metadata;
         TrustEngine* m_trust;
@@ -172,11 +189,7 @@ namespace {
         vector<const XMLCh*> m_audiences;
 
         // RelyingParty properties
-#ifdef HAVE_GOOD_STL
         map<xstring,PropertySet*> m_partyMap;
-#else
-        map<const XMLCh*,PropertySet*> m_partyMap;
-#endif
 #endif
         vector<string> m_remoteUsers,m_frontLogout,m_backLogout;
 
@@ -188,16 +201,12 @@ namespace {
 
         // maps unique indexes to consumer services
         map<unsigned int,const Handler*> m_acsIndexMap;
-        
+
         // pointer to default consumer service
         const Handler* m_acsDefault;
 
         // maps binding strings to supporting consumer service(s)
-#ifdef HAVE_GOOD_STL
         typedef map<xstring,vector<const Handler*> > ACSBindingMap;
-#else
-        typedef map<string,vector<const Handler*> > ACSBindingMap;
-#endif
         ACSBindingMap m_acsBindingMap;
 
         // pointer to default session initiator
@@ -222,16 +231,21 @@ namespace {
     public:
         XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);
         ~XMLConfigImpl();
-        
+
         RequestMapper* m_requestMapper;
         map<string,Application*> m_appmap;
 #ifndef SHIBSP_LITE
         map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
         vector< pair< string, pair<string,string> > > m_transportOptions;
 #endif
-        
+
         // Provides filter to exclude special config elements.
-        short acceptNode(const DOMNode* node) const;
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const;
 
         void setDocument(DOMDocument* doc) {
             m_document = doc;
@@ -258,7 +272,7 @@ namespace {
 #endif
         {
         }
-        
+
         void init() {
             load();
         }
@@ -406,6 +420,7 @@ namespace {
     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);
@@ -427,7 +442,12 @@ namespace {
     class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter
     {
     public:
-        short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+        short
+#else
+        FilterAction
+#endif
+        acceptNode(const DOMNode* node) const {
             return FILTER_REJECT;
         }
     };
@@ -479,6 +499,18 @@ XMLApplication::XMLApplication(
             m_hash += (DIGITS[0x0F & *ch]);
         }
 
+        // Populate prefix pair.
+        m_attributePrefix.second = "HTTP_";
+        pair<bool,const char*> prefix = getString("attributePrefix");
+        if (prefix.first) {
+            m_attributePrefix.first = prefix.second;
+            const char* pch = prefix.second;
+            while (*pch) {
+                m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');
+                pch++;
+            }
+        }
+
         // Load attribute ID lists for REMOTE_USER and header clearing.
         if (conf.isEnabled(SPConfig::InProcess)) {
             pair<bool,const char*> attributes = getString("REMOTE_USER");
@@ -502,9 +534,9 @@ XMLApplication::XMLApplication(
 
             attributes = getString("unsetHeaders");
             if (attributes.first) {
-                string transformedprefix("HTTP_");
+                string transformedprefix(m_attributePrefix.second);
                 const char* pch;
-                pair<bool,const char*> prefix = getString("metadataAttributePrefix");
+                prefix = getString("metadataAttributePrefix");
                 if (prefix.first) {
                     pch = prefix.second;
                     while (*pch) {
@@ -530,13 +562,14 @@ XMLApplication::XMLApplication(
                         transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                         pch++;
                     }
-                    m_unsetHeaders.push_back(pair<string,string>(start,string("HTTP_") + transformed));
+
+                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
                     if (prefix.first)
-                        m_unsetHeaders.push_back(pair<string,string>(string(prefix.second) + start, transformedprefix + transformed));
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
                     start = pos ? pos+1 : NULL;
                 }
                 free(dup);
-                m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
             }
         }
 
@@ -589,13 +622,9 @@ XMLApplication::XMLApplication(
                     }
                     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)
-#ifdef HAVE_GOOD_STL
                     m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
-#else
-                    m_acsBindingMap[handler->getString("Binding").second].push_back(handler);
-#endif
                     m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;
-                    
+
                     if (!hardACS) {
                         pair<bool,bool> defprop=handler->getBool("isDefault");
                         if (defprop.first) {
@@ -649,7 +678,7 @@ XMLApplication::XMLApplication(
                         continue;
                     }
                     handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-                    
+
                     if (!hardArt) {
                         pair<bool,bool> defprop=handler->getBool("isDefault");
                         if (defprop.first) {
@@ -703,7 +732,7 @@ XMLApplication::XMLApplication(
             catch (exception& ex) {
                 log.error("caught exception processing handler element: %s", ex.what());
             }
-            
+
             child = XMLHelper::getNextSiblingElement(child);
         }
 
@@ -724,9 +753,12 @@ XMLApplication::XMLApplication(
 
 #ifndef SHIBSP_LITE
         nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);
-        for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++)
-            if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
-                m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
+        if (nlist && nlist->getLength()) {
+            log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
+            for (XMLSize_t i=0; i<nlist->getLength(); i++)
+                if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
+                    m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
+        }
 
         if (conf.isEnabled(SPConfig::Metadata)) {
             child = XMLHelper::getFirstChildElement(e,_MetadataProvider);
@@ -801,18 +833,20 @@ XMLApplication::XMLApplication(
                     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);
                 }
-                if (unsetHeaders.empty()) {
-                    if (m_base)
-                        m_unsetHeaders.insert(m_unsetHeaders.end(), m_base->m_unsetHeaders.begin(), m_base->m_unsetHeaders.end());
-                    else
-                        m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
+                else if (m_base && m_base->m_attrResolver) {
+                    Locker extlock(m_base->m_attrResolver);
+                    m_base->m_attrResolver->getAttributeIds(unsetHeaders);
                 }
-                else {
-                    string transformedprefix("HTTP_");
+                if (!unsetHeaders.empty()) {
+                    string transformedprefix(m_attributePrefix.second);
                     const char* pch;
                     pair<bool,const char*> prefix = getString("metadataAttributePrefix");
                     if (prefix.first) {
@@ -829,12 +863,12 @@ XMLApplication::XMLApplication(
                             transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                             pch++;
                         }
-                        m_unsetHeaders.push_back(pair<string,string>(*hdr, string("HTTP_") + transformed));
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
                         if (prefix.first)
-                            m_unsetHeaders.push_back(pair<string,string>(string(prefix.second) + *hdr, transformedprefix + transformed));
+                            m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
                     }
-                    m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
                 }
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
             }
         }
 
@@ -896,11 +930,7 @@ void XMLApplication::cleanup()
     for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
     m_handlers.clear();
 #ifndef SHIBSP_LITE
-#ifdef HAVE_GOOD_STL
     for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());
-#else
-    for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<const XMLCh*,PropertySet>());
-#endif
     m_partyMap.clear();
     delete m_credResolver;
     m_credResolver = NULL;
@@ -917,7 +947,12 @@ void XMLApplication::cleanup()
 #endif
 }
 
-short XMLApplication::acceptNode(const DOMNode* node) const
+#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) ||
@@ -948,8 +983,7 @@ const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provi
 {
     if (!provider)
         return this;
-        
-#ifdef HAVE_GOOD_STL
+
     map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());
     if (i!=m_partyMap.end())
         return i->second;
@@ -962,19 +996,6 @@ const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provi
         }
         group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
     }
-#else
-    map<const XMLCh*,PropertySet*>::const_iterator i=m_partyMap.begin();
-    for (; i!=m_partyMap.end(); i++) {
-        if (XMLString::equals(i->first,provider->getEntityID()))
-            return i->second;
-        const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
-        while (group) {
-            if (XMLString::equals(i->first,group->getName()))
-                return i->second;
-            group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
-        }
-    }
-#endif
     return this;
 }
 
@@ -982,18 +1003,10 @@ const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const
 {
     if (!entityID)
         return this;
-        
-#ifdef HAVE_GOOD_STL
+
     map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);
     if (i!=m_partyMap.end())
         return i->second;
-#else
-    map<const XMLCh*,PropertySet*>::const_iterator i=m_partyMap.begin();
-    for (; i!=m_partyMap.end(); i++) {
-        if (XMLString::equals(i->first,entityID))
-            return i->second;
-    }
-#endif
     return this;
 }
 
@@ -1015,7 +1028,7 @@ string XMLApplication::getNotificationURL(const char* resource, bool front, unsi
         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(
@@ -1071,6 +1084,49 @@ string XMLApplication::getNotificationURL(const char* resource, bool front, unsi
     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;
@@ -1099,12 +1155,7 @@ const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short
 
 const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
 {
-#ifdef HAVE_GOOD_STL
     ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
-#else
-    auto_ptr_char temp(binding);
-    ACSBindingMap::const_iterator i=m_acsBindingMap.find(temp.get());
-#endif
     if (i!=m_acsBindingMap.end())
         return i->second;
     return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
@@ -1113,6 +1164,7 @@ const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBind
 const Handler* XMLApplication::getHandler(const char* path) const
 {
     string wrap(path);
+    wrap = wrap.substr(0,wrap.find(';'));
     map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
     if (i!=m_handlerMap.end())
         return i->second;
@@ -1130,7 +1182,12 @@ void XMLApplication::getHandlers(vector<const Handler*>& handlers) const
     }
 }
 
-short XMLConfigImpl::acceptNode(const DOMNode* node) const
+#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;
@@ -1162,7 +1219,8 @@ void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Categor
             auto_ptr_char path(exts->getAttributeNS(NULL,_path));
             try {
                 if (path.get()) {
-                    XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts);
+                    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());
                 }
             }
@@ -1209,15 +1267,29 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
             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());
-                XMLToolingConfig::getConfig().log_config(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);
 
@@ -1229,7 +1301,11 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
             // Set clock skew.
             pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
             if (skew.first)
-                xmlConf.clock_skew_secs=skew.second;
+                xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
+
+            pair<bool,const char*> unsafe = getString("unsafeChars");
+            if (unsafe.first)
+                TemplateEngine::unsafe_chars = unsafe.second;
 
             // Extensions
             doExtensions(e, "global", log);
@@ -1238,7 +1314,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
 
             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);
@@ -1269,8 +1345,10 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
 
 #ifndef SHIBSP_LITE
             if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
-                m_outer->m_listener->regListener("set::RelayState", m_outer->m_listener);
-                m_outer->m_listener->regListener("get::RelayState", m_outer->m_listener);
+                m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));
+                m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));
+                m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));
+                m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));
             }
 #endif
 
@@ -1310,7 +1388,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                     else {
                         log.warn("no ReplayCache built, missing conf:ReplayCache element?");
                     }
-                    
+
                     // ArtifactMap
                     child=XMLHelper::getFirstChildElement(e,_ArtifactMap);
                     if (child) {
@@ -1338,7 +1416,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                 }
             }
         } // 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);
@@ -1352,7 +1430,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                 throw ConfigurationException("Can't build RequestMapper, missing conf:RequestMapper element?");
             }
         }
-        
+
 #ifndef SHIBSP_LITE
         // Load security policies.
         child = XMLHelper::getLastChildElement(e,SecurityPolicies);
@@ -1366,9 +1444,9 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                 auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
                 settings->load(child, NULL, &filter);
                 rules.first = settings.release();
-                
-                // Process Rule elements.
-                const DOMElement* rule = XMLHelper::getFirstChildElement(child,Rule);
+
+                // Process PolicyRule elements.
+                const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);
                 while (rule) {
                     auto_ptr_char type(rule->getAttributeNS(NULL,_type));
                     try {
@@ -1377,9 +1455,29 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
                     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);
+                    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);
             }
         }
@@ -1407,7 +1505,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
         }
         XMLApplication* defapp=new XMLApplication(m_outer,child);
         m_appmap[defapp->getId()]=defapp;
-        
+
         // Load any overrides.
         child = XMLHelper::getFirstChildElement(child,ApplicationOverride);
         while (child) {
@@ -1475,7 +1573,7 @@ void XMLConfig::receive(DDF& in, ostream& out)
         }
 
         // Repack for return to caller.
-        DDF ret=DDF(NULL).string(relayState.c_str());
+        DDF ret=DDF(NULL).unsafe_string(relayState.c_str());
         DDFJanitor jret(ret);
         out << ret;
     }
@@ -1503,6 +1601,60 @@ void XMLConfig::receive(DDF& in, ostream& out)
         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
 
@@ -1510,12 +1662,12 @@ pair<bool,DOMElement*> XMLConfig::load()
 {
     // Load from source using base class.
     pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-    
+
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
 
     XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this,m_log);
-    
+
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
 
index fd3bfba..cb8ffc0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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
@@ -16,8 +16,8 @@
 
 /**
  * CommonDomainCookie.cpp
- * 
- * Helper class for maintaining discovery cookie. 
+ *
+ * Helper class for maintaining discovery cookie.
  */
 
 #include "internal.h"
@@ -55,12 +55,16 @@ CommonDomainCookie::CommonDomainCookie(const char* cookie)
     free(b64);
 
     // Now Base64 decode the list.
-    unsigned int len;
+    xsecsize_t len;
     for (vector<string>::iterator i=templist.begin(); i!=templist.end(); ++i) {
         XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(i->c_str()),&len);
         if (decoded && *decoded) {
             m_list.push_back(reinterpret_cast<char*>(decoded));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
             XMLString::release(&decoded);
+#else
+            XMLString::release((char**)&decoded);
+#endif
         }
     }
 }
@@ -74,27 +78,31 @@ const char* CommonDomainCookie::set(const char* entityID)
             break;
         }
     }
-    
+
     // Append it to the end.
     m_list.push_back(entityID);
-    
+
     // Now rebuild the delimited list.
-    unsigned int len;
+    xsecsize_t len;
     string delimited;
     for (vector<string>::const_iterator j=m_list.begin(); j!=m_list.end(); j++) {
         if (!delimited.empty()) delimited += ' ';
-        
+
         XMLByte* b64=Base64::encode(reinterpret_cast<const XMLByte*>(j->c_str()),j->length(),&len);
         XMLByte *pos, *pos2;
         for (pos=b64, pos2=b64; *pos2; pos2++)
             if (isgraph(*pos2))
                 *pos++=*pos2;
         *pos=0;
-        
+
         delimited += reinterpret_cast<char*>(b64);
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
         XMLString::release(&b64);
+#else
+        XMLString::release((char**)&b64);
+#endif
     }
-    
+
     m_encoded=XMLToolingConfig::getConfig().getURLEncoder()->encode(delimited.c_str());
     return m_encoded.c_str();
 }
index 5c2be15..59f8e8b 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * SAMLConstants.cpp
- * 
- * SAML XML namespace constants 
+ *
+ * SAML XML namespace constants
  */
 
 
@@ -184,6 +184,36 @@ const XMLCh samlconstants::SAML20P_THIRDPARTY_EXT_NS[] = // urn:oasis:names:tc:S
 
 const XMLCh samlconstants::SAML20P_THIRDPARTY_EXT_PREFIX[] = UNICODE_LITERAL_6(t,h,r,p,t,y);
 
+const XMLCh samlconstants::SAML20_ATTRIBUTE_EXT_NS[] = // urn:oasis:names:tc:SAML:attribute:ext
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_o, chLatin_a, chLatin_s, chLatin_i, chLatin_s, chColon,
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chColon, chLatin_t, chLatin_c, chColon,
+  chLatin_S, chLatin_A, chLatin_M, chLatin_L, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chColon,
+  chLatin_e, chLatin_x, chLatin_t, chNull
+};
+
+const XMLCh samlconstants::SAML20_ATTRIBUTE_EXT_PREFIX[] = UNICODE_LITERAL_3(e,x,t);
+
+const XMLCh samlconstants::SAML20MD_ENTITY_ATTRIBUTE_NS[] = // urn:oasis:names:tc:SAML:metadata:attribute
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_o, chLatin_a, chLatin_s, chLatin_i, chLatin_s, chColon,
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chColon, chLatin_t, chLatin_c, chColon,
+  chLatin_S, chLatin_A, chLatin_M, chLatin_L, chColon,
+  chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chNull
+};
+
+const XMLCh samlconstants::SAML20MD_ENTITY_ATTRIBUTE_PREFIX[] = UNICODE_LITERAL_6(m,d,a,t,t,r);
+
+const XMLCh samlconstants::SAML20_DELEGATION_CONDITION_NS[] = // urn:oasis:names:tc:SAML:2.0:conditions:delegation
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_o, chLatin_a, chLatin_s, chLatin_i, chLatin_s, chColon,
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chColon, chLatin_t, chLatin_c, chColon,
+  chLatin_S, chLatin_A, chLatin_M, chLatin_L, chColon, chDigit_2, chPeriod, chDigit_0, chColon,
+  chLatin_c, chLatin_o, chLatin_n, chLatin_d, chLatin_i, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chLatin_s, chColon,
+  chLatin_d, chLatin_e, chLatin_l, chLatin_e, chLatin_g, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull
+};
+
+const XMLCh samlconstants::SAML20_DELEGATION_CONDITION_PREFIX[] = UNICODE_LITERAL_3(d,e,l);
+
 const char samlconstants::SAML1_BINDING_SOAP[] = "urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding";
 
 const char samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT[] = "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01";
index 74e0004..f04b3f3 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * @file shibsp/lite/SAMLConstants.h
- * 
- * SAML XML namespace constants 
+ *
+ * SAML XML namespace constants
  */
 
 #ifndef __shibsp_xmlconstants_h__
  * SAML related constants.
  */
 namespace samlconstants {
-    
+
     /**  Liberty PAOS XML Namespace ("urn:liberty:paos:2003-08") */
     extern SHIBSP_API const XMLCh PAOS_NS[];
-    
+
     /**  Liberty PAOS QName prefix ("paos") */
     extern SHIBSP_API const XMLCh PAOS_PREFIX[];
 
@@ -41,16 +41,16 @@ namespace samlconstants {
 
     /**  SAML 1.X Protocol XML namespace ("urn:oasis:names:tc:SAML:1.0:protocol") */
     extern SHIBSP_API const XMLCh SAML1P_NS[];
-    
+
     /** SAML 1.X Assertion QName prefix ("saml") */
     extern SHIBSP_API const XMLCh SAML1_PREFIX[];
 
     /** SAML 1.X Protocol QName prefix ("samlp") */
     extern SHIBSP_API const XMLCh SAML1P_PREFIX[];
-    
+
     /**  SAML 2.0 Version ("2.0") */
     extern SHIBSP_API const XMLCh SAML20_VERSION[];
-    
+
     /**  SAML 2.0 Assertion XML namespace ("urn:oasis:names:tc:SAML:2.0:assertion") */
     extern SHIBSP_API const XMLCh SAML20_NS[];
 
@@ -62,7 +62,7 @@ namespace samlconstants {
 
     /**  SAML 2.0 AuthnContext XML namespace ("urn:oasis:names:tc:SAML:2.0:ac") */
     extern SHIBSP_API const XMLCh SAML20AC_NS[];
-    
+
     /** SAML 2.0 Assertion QName prefix ("saml") */
     extern SHIBSP_API const XMLCh SAML20_PREFIX[];
 
@@ -77,52 +77,70 @@ namespace samlconstants {
 
     /** SAML 2.0 Enhanced Client/Proxy SSO Profile XML Namespace ("urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp") */
     extern SHIBSP_API const XMLCh SAML20ECP_NS[];
-    
+
     /** SAML 2.0 Enhanced Client/Proxy SSO Profile QName prefix ("ecp") */
     extern SHIBSP_API const XMLCh SAML20ECP_PREFIX[];
 
     /** SAML 2.0 DCE PAC Attribute Profile XML Namespace ("urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE") */
     extern SHIBSP_API const XMLCh SAML20DCE_NS[];
-    
+
     /** SAML 2.0 DCE PAC Attribute Profile QName prefix ("DCE") */
     extern SHIBSP_API const XMLCh SAML20DCE_PREFIX[];
 
     /** SAML 2.0 X.500 Attribute Profile XML Namespace ("urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500") */
     extern SHIBSP_API const XMLCh SAML20X500_NS[];
-    
+
     /** SAML 2.0 X.500 Attribute Profile QName prefix ("x500") */
     extern SHIBSP_API const XMLCh SAML20X500_PREFIX[];
 
     /** SAML 2.0 XACML Attribute Profile XML Namespace ("urn:oasis:names:tc:SAML:2.0:profiles:attribute:XACML") */
     extern SHIBSP_API const XMLCh SAML20XACML_NS[];
-    
+
     /** SAML 2.0 XACML Attribute Profile QName prefix ("xacmlprof") */
     extern SHIBSP_API const XMLCh SAML20XACML_PREFIX[];
 
     /** SAML 1.x Metadata Profile XML Namespace ("urn:oasis:names:tc:SAML:profiles:v1metadata") */
     extern SHIBSP_API const XMLCh SAML1MD_NS[];
-    
+
     /** SAML 1.x Metadata Profile QName prefix ("saml1md") */
     extern SHIBSP_API const XMLCh SAML1MD_PREFIX[];
 
     /** SAML 1.0 Protocol Enumeration constant ("urn:oasis:names:tc:SAML:1.0:protocol") */
     extern SHIBSP_API const XMLCh SAML10_PROTOCOL_ENUM[];
-    
+
     /** SAML 1.1 Protocol Enumeration constant ("urn:oasis:names:tc:SAML:1.1:protocol") */
     extern SHIBSP_API const XMLCh SAML11_PROTOCOL_ENUM[];
 
     /** SAML Query Requester Metadata Extension XML Namespace ("urn:oasis:names:tc:SAML:metadata:ext:query") */
     extern SHIBSP_API const XMLCh SAML20MD_QUERY_EXT_NS[];
-    
+
     /** SAML Query Requester Metadata Extension QName prefix ("query") */
     extern SHIBSP_API const XMLCh SAML20MD_QUERY_EXT_PREFIX[];
 
     /** SAML Third-Party Request Protocol Extension XML Namespace ("urn:oasis:names:tc:SAML:protocol:ext:third-party") */
     extern SHIBSP_API const XMLCh SAML20P_THIRDPARTY_EXT_NS[];
-    
-    /** SAML Third-Party Request Protocol Extension QName prefix ("query") */
+
+    /** SAML Third-Party Request Protocol Extension QName prefix ("thrpty") */
     extern SHIBSP_API const XMLCh SAML20P_THIRDPARTY_EXT_PREFIX[];
 
+    /** SAML Attribute Extension XML Namespace ("urn:oasis:names:tc:SAML:attribute:ext") */
+    extern SHIBSP_API const XMLCh SAML20_ATTRIBUTE_EXT_NS[];
+
+    /** SAML Attribute Extension QName prefix ("ext") */
+    extern SHIBSP_API const XMLCh SAML20_ATTRIBUTE_EXT_PREFIX[];
+
+    /** SAML Metadata Extension for Entity Attributes XML Namespace ("urn:oasis:names:tc:SAML:metadata:attribute") */
+    extern SHIBSP_API const XMLCh SAML20MD_ENTITY_ATTRIBUTE_NS[];
+
+    /** SAML Metadata Extension for Entity Attributes QName prefix ("mdattr") */
+    extern SHIBSP_API const XMLCh SAML20MD_ENTITY_ATTRIBUTE_PREFIX[];
+
+    /** SAML Condition for Delegation Restriction XML Namespace ("urn:oasis:names:tc:SAML:2.0:conditions:delegation") */
+    extern SHIBSP_API const XMLCh SAML20_DELEGATION_CONDITION_NS[];
+
+    /** SAML Condition for Delegation Restriction QName prefix ("del") */
+    extern SHIBSP_API const XMLCh SAML20_DELEGATION_CONDITION_PREFIX[];
+
     /** SAML 1.x SOAP binding ("urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding") */
     extern SHIBSP_API const char SAML1_BINDING_SOAP[];
 
@@ -131,11 +149,11 @@ namespace samlconstants {
 
     /** SAML 1.x Browser POST profile ("urn:oasis:names:tc:SAML:1.0:profiles:browser-post") */
     extern SHIBSP_API const char SAML1_PROFILE_BROWSER_POST[];
-    
+
     /** SAML 2.0 SOAP binding ("urn:oasis:names:tc:SAML:2.0:bindings:SOAP") */
     extern SHIBSP_API const char SAML20_BINDING_SOAP[];
 
-    /** SAML 2.0 SOAP binding ("urn:oasis:names:tc:SAML:2.0:bindings:PAOS") */
+    /** SAML 2.0 PAOS binding ("urn:oasis:names:tc:SAML:2.0:bindings:PAOS") */
     extern SHIBSP_API const char SAML20_BINDING_PAOS[];
 
     /** SAML 2.0 URI binding ("urn:oasis:names:tc:SAML:2.0:bindings:URI") */
@@ -146,13 +164,13 @@ namespace samlconstants {
 
     /** SAML 2.0 HTTP-POST binding ("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST") */
     extern SHIBSP_API const char SAML20_BINDING_HTTP_POST[];
-    
+
     /** SAML 2.0 HTTP-POST-SimpleSign binding ("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign") */
     extern SHIBSP_API const char SAML20_BINDING_HTTP_POST_SIMPLESIGN[];
 
     /** SAML 2.0 HTTP-Redirect binding ("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect") */
     extern SHIBSP_API const char SAML20_BINDING_HTTP_REDIRECT[];
-    
+
     /** SAML 2.0 HTTP-Redirect DEFLATE URL encoding ("urn:oasis:names:tc:SAML:2.0:bindings:URL-Encoding:DEFLATE") */
     extern SHIBSP_API const char SAML20_BINDING_URL_ENCODING_DEFLATE[];
 };
index 42545a3..9e583e4 100644 (file)
@@ -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.
@@ -127,14 +127,16 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
     Category& log=Category::getInstance(SHIBSP_LOGCAT".MetadataProvider.Dynamic");
 
     string name;
-    if (criteria.entityID_ascii)
+    if (criteria.entityID_ascii) {
         name = criteria.entityID_ascii;
+    }
     else if (criteria.entityID_unicode) {
         auto_ptr_char temp(criteria.entityID_unicode);
         name = temp.get();
     }
-    else if (criteria.artifact)
-        name = criteria.artifact->getSource();
+    else if (criteria.artifact) {
+        throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");\r
+    }
 
     // Establish networking properties based on calling application.
     const MetadataProviderCriteria* mpc = dynamic_cast<const MetadataProviderCriteria*>(&criteria);
@@ -239,9 +241,8 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
     }
 
     try {
-        // Use an empty stream to trigger a body-less "GET" operation.
-        istringstream dummy;
-        transport->send(dummy);
+        // Use a NULL stream to trigger a body-less "GET" operation.
+        transport->send();
         istream& msg = transport->receive();
 
         DOMDocument* doc=NULL;
index 6188b46..71fb17a 100644 (file)
@@ -59,7 +59,7 @@ namespace shibsp {
 
     public:
 
-        ScopeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
+        ScopeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
             init();
         }
@@ -99,7 +99,7 @@ namespace shibsp {
             XMLString::release(&m_VerifyDepth);
         }
 
-        KeyAuthorityImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
+        KeyAuthorityImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
             init();
         }
@@ -119,7 +119,7 @@ namespace shibsp {
         IMPL_TYPED_CHILDREN(KeyInfo,m_children.end());
         
     public:
-        void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false) {
+        void setAttribute(const xmltooling::QName& qualifiedName, const XMLCh* value, bool ID=false) {
             if (!qualifiedName.hasNamespaceURI()) {
                 if (XMLString::equals(qualifiedName.getLocalPart(),VERIFYDEPTH_ATTRIB_NAME)) {
                     setVerifyDepth(value);
index d175ba4..f9b4472 100644 (file)
@@ -46,12 +46,12 @@ namespace shibsp {
 };
 
 #define REGISTER_ELEMENT(cname) \
-    q=QName(SHIBMD_NS,cname::LOCAL_NAME); \
+    q=xmltooling::QName(SHIBMD_NS,cname::LOCAL_NAME); \
     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
     
 void shibsp::registerMetadataExtClasses() {
-    QName q;
+    xmltooling::QName q;
     REGISTER_ELEMENT(Scope);
     REGISTER_ELEMENT(KeyAuthority);
 
index 4020005..286a4a0 100644 (file)
@@ -37,6 +37,14 @@ namespace shibsp {
          * Constructor.
          *
          * @param app   application performing the lookup
+         */
+        MetadataProviderCriteria(const Application& app) : application(app) {
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param app   application performing the lookup
          * @param id    entityID to lookup
          * @param q     element/type of role, if any
          * @param prot  protocol support constant, if any
index 4aa5d5e..6eb507d 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2005 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  * \r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
 #ifndef __shibsp_paths_h__\r
 #define __shibsp_paths_h__\r
 \r
-/**\r
- * Default schema catalogs.\r
- */\r
-#define SHIBSP_SCHEMAS "/usr/share/xml/xmltooling/catalog.xml:/usr/share/xml/opensaml/saml20-catalog.xml:/usr/share/xml/opensaml/saml11-catalog.xml:/usr/local/share/xml/shibboleth/catalog.xml"\r
+/** Default schema catalogs. */\r
+#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/usr/share/xml/opensaml/saml20-catalog.xml:/usr/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"\r
 \r
-/**\r
- * Default name of SP configuration file.\r
- */\r
+/** Default name of SP configuration file. */\r
 #define SHIBSP_CONFIG "shibboleth2.xml"\r
 \r
-/**\r
- * Default name of SP console tool logging file.\r
- */\r
+/** Default name of SP console tool logging file. */\r
 #define SHIBSP_LOGGING "console.logger"\r
 \r
-/**\r
- * Default prefix for installation (used to resolve relative paths).\r
- */\r
-#define SHIBSP_PREFIX  "/usr/local"\r
+/** Default prefix for installation (used to resolve relative paths). */\r
+#define SHIBSP_PREFIX  "/opt/shibboleth-sp"\r
+\r
+/** Library directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_LIBDIR  "/opt/shibboleth-sp/lib"\r
+\r
+/** Log directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_LOGDIR  "/opt/shibboleth-sp/var/log"\r
+\r
+/** Configuration directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_CFGDIR  "/opt/shibboleth-sp/etc"\r
+\r
+/** Runtime state directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_RUNDIR  "/opt/shibboleth-sp/var/run"\r
+\r
+/** XML directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_XMLDIR  "/opt/shibboleth-sp/share/xml"\r
 \r
 #endif /* __shibsp_paths_h__ */\r
index 9f5e2b1..f35df0b 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2005 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  * \r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
 #ifndef __shibsp_paths_h__\r
 #define __shibsp_paths_h__\r
 \r
-/**\r
- * Default schema catalogs.\r
- */\r
+/** Default schema catalogs. */\r
 #define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"\r
 \r
-/**\r
- * Default name of SP configuration file.\r
- */\r
+/** Default name of SP configuration file. */\r
 #define SHIBSP_CONFIG "shibboleth2.xml"\r
 \r
-/**\r
- * Default name of SP console tool logging file.\r
- */\r
+/** Default name of SP console tool logging file. */\r
 #define SHIBSP_LOGGING "console.logger"\r
 \r
-/**\r
- * Default prefix for installation (used to resolve relative paths).\r
- */\r
+/** Default prefix for installation (used to resolve relative paths). */\r
 #define SHIBSP_PREFIX  "@-PREFIX-@"\r
 \r
+/** Library directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_LIBDIR  "@-LIBDIR-@"\r
+\r
+/** Log directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_LOGDIR  "@-LOGDIR-@"\r
+\r
+/** Configuration directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_CFGDIR  "@-SYSCONFDIR-@"\r
+\r
+/** Runtime state directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_RUNDIR  "@-RUNDIR-@"\r
+\r
+/** XML directory for installation (used to resolve relative paths). */\r
+#define SHIBSP_XMLDIR  "@-XMLDIR-@"\r
+\r
 #endif /* __shibsp_paths_h__ */\r
index 3e8c6b3..c85af8c 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/remoting/ListenerService.h
- * 
+ *
  * Interprocess remoting engine.
  */
 
@@ -30,7 +30,7 @@ namespace shibsp {
 
     /**
      * Interface to a remoted service
-     * 
+     *
      * Classes that support remoted messages delivered by the Listener runtime
      * support this interface and register themselves with the runtime to receive
      * particular messages.
@@ -45,7 +45,7 @@ namespace shibsp {
 
         /**
          * Remoted classes implement this method to process incoming messages.
-         * 
+         *
          * @param in    incoming DDF message
          * @param out   stream to write outgoing DDF message to
          */
@@ -59,7 +59,7 @@ namespace shibsp {
 
     /**
      * Interface to a remoting engine.
-     * 
+     *
      * A ListenerService supports the remoting of DDF objects, which are dynamic data trees
      * that other class implementations can use to remote themselves by calling an
      * out-of-process peer implementation with arbitrary data to carry out tasks
@@ -77,53 +77,74 @@ namespace shibsp {
 
         /**
          * Send a remoted message and return the response.
-         * 
+         *
          * @param in    input message to send
          * @return      response from remote service
          */
         virtual DDF send(const DDF& in)=0;
-        
+
         void receive(DDF& in, std::ostream& out);
 
         // Remoted classes register and unregister for messages using these methods.
         // Registration returns any existing listeners, allowing message hooking.
-        
+
         /**
          * Register for a message. Returns existing remote service, allowing message hooking.
-         * 
+         *
          * @param address   message address to register
          * @param svc       pointer to remote service
          * @return  previous service registered for message, if any
          */
         virtual Remoted* regListener(const char* address, Remoted* svc);
-        
+
         /**
          * Unregisters service from an address, possibly restoring an original.
-         * 
+         *
          * @param address   message address to modify
          * @param current   pointer to unregistering service
          * @param restore   service to "restore" registration for
          * @return  true iff the current service was still registered
          */
         virtual bool unregListener(const char* address, Remoted* current, Remoted* restore=NULL);
-        
+
         /**
          * Returns current service registered at an address, if any.
-         * 
+         *
          * @param address message address to access
          * @return  registered service, or NULL
          */
         virtual Remoted* lookup(const char* address) const;
 
         /**
+         * OutOfProcess servers can implement server-side initialization that should occur
+         * before daemonization.
+         *
+         * <p>The parameter applies to implementations that can detect and remove
+         * the results of ungraceful shutdowns of previous executions and continue
+         * successfully. File-based sockets are the most common example.
+         *
+         * @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;
+        }
+
+        /**
          * OutOfProcess servers can implement server-side transport handling by
          * calling the run method and supplying a flag to monitor for shutdown.
-         * 
+         *
          * @param shutdown  pointer to flag that caller will set when shutdown is required
-         * @return true iff ListenerService initialization was successful
+         * @return true iff the service execution was successful
          */
         virtual bool run(bool* shutdown)=0;
 
+        /**
+         * OutOfProcess servers can implement server-side termination/cleanup.
+         */
+        virtual void term() {
+        }
+
     private:
         std::map<std::string,Remoted*> m_listenerMap;
     };
index 041f344..b361ec0 100644 (file)
@@ -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.
@@ -44,7 +44,7 @@ namespace shibsp {
         // constructors
         DDF() : m_handle(NULL) {}
         DDF(const char* n);
-        DDF(const char* n, const char* val);
+        DDF(const char* n, const char* val, bool safe=true);
         DDF(const char* n, long val);
         DDF(const char* n, double val);
         DDF(const char* n, void* val);
@@ -80,7 +80,10 @@ namespace shibsp {
         DDF& string(const char* val) {
             return string(const_cast<char*>(val), true);
         }
-        DDF& string(char* val, bool copyit=true);
+        DDF& unsafe_string(const char* val) {
+            return string(const_cast<char*>(val), true, false);
+        }
+        DDF& string(char* val, bool copyit=true, bool safe=true);
         DDF& string(long val);
         DDF& string(double val);
         DDF& integer(long val);
index 600c87f..f33b307 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * ListenerService.cpp
- * 
+ *
  * Interprocess remoting engine.
  */
 
@@ -93,6 +93,6 @@ void ListenerService::receive(DDF &in, ostream& out)
     Remoted* dest=lookup(in.name());
     if (!dest)
         throw ListenerException("No destination registered for incoming message addressed to ($1).",params(1,in.name()));
-    
+
     dest->receive(in, out);
 }
index e211b20..edac04f 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * SocketListener.cpp
- * 
+ *
  * Berkeley Socket-based ListenerService implementation
  */
 
@@ -45,7 +45,7 @@ using namespace std;
 using xercesc::DOMElement;
 
 namespace shibsp {
-  
+
     // Manages the pool of connections
     class SocketPool
     {
@@ -55,16 +55,16 @@ namespace shibsp {
         ~SocketPool();
         SocketListener::ShibSocket get();
         void put(SocketListener::ShibSocket s);
-  
+
     private:
         SocketListener::ShibSocket connect();
-       
-        Category& m_log; 
+
+        Category& m_log;
         const SocketListener* m_listener;
         auto_ptr<Mutex> m_lock;
         stack<SocketListener::ShibSocket> m_pool;
     };
-  
+
     // Worker threads in server
     class ServerThread {
     public:
@@ -104,7 +104,7 @@ SocketListener::ShibSocket SocketPool::connect()
             connected = true;
             break;
         }
-    
+
         m_log.warn("cannot connect socket (%u)...%s", sock, (i > 0 ? "retrying" : ""));
 
         if (i) {
@@ -158,8 +158,9 @@ void SocketPool::put(SocketListener::ShibSocket s)
     m_lock->unlock();
 }
 
-SocketListener::SocketListener(const DOMElement* e) : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
-    m_socketpool(NULL), m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socket((ShibSocket)0)
+SocketListener::SocketListener(const DOMElement* e)
+    : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")), m_socketpool(NULL),
+        m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socket((ShibSocket)0)
 {
     // Are we a client?
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
@@ -179,10 +180,10 @@ SocketListener::~SocketListener()
     delete m_child_lock;
 }
 
-bool SocketListener::run(bool* shutdown)
+bool SocketListener::init(bool force)
 {
 #ifdef _DEBUG
-    NDC ndc("run");
+    NDC ndc("init");
 #endif
     log->info("listener service starting");
 
@@ -194,28 +195,36 @@ bool SocketListener::run(bool* shutdown)
         m_catchAll = flag.first && flag.second;
     }
     sp->unlock();
-    
-    // Save flag to monitor for shutdown request.
-    m_shutdown=shutdown;
-    unsigned long count = 0;
 
     if (!create(m_socket)) {
         log->crit("failed to create socket");
         return false;
     }
-    if (!bind(m_socket,true)) {
+    if (!bind(m_socket, force)) {
         this->close(m_socket);
         log->crit("failed to bind to socket.");
         return false;
     }
 
+    return true;
+}
+
+bool SocketListener::run(bool* shutdown)
+{
+#ifdef _DEBUG
+    NDC ndc("run");
+#endif
+    // Save flag to monitor for shutdown request.
+    m_shutdown=shutdown;
+    unsigned long count = 0;
+
     while (!*m_shutdown) {
         fd_set readfds;
         FD_ZERO(&readfds);
         FD_SET(m_socket, &readfds);
         struct timeval tv = { 0, 0 };
         tv.tv_sec = 5;
-    
+
         switch (select(m_socket + 1, &readfds, 0, 0, &tv)) {
 #ifdef WIN32
             case SOCKET_ERROR:
@@ -225,24 +234,30 @@ bool SocketListener::run(bool* shutdown)
                 if (errno == EINTR) continue;
                 log_error();
                 log->error("select() on main listener socket failed");
-                return false;
-        
+                *m_shutdown = true;
+                break;
+
             case 0:
                 continue;
-        
+
             default:
             {
                 // Accept the connection.
                 SocketListener::ShibSocket newsock;
-                if (!accept(m_socket, newsock))
+                if (!accept(m_socket, newsock)) {
                     log->crit("failed to accept incoming socket connection");
+                    continue;
+                }
 
                 // We throw away the result because the children manage themselves...
                 try {
                     new ServerThread(newsock,this,++count);
                 }
+                catch (exception& ex) {
+                    log->crit("exception starting new server thread to service incoming request: %s", ex.what());
+                }
                 catch (...) {
-                    log->crit("error starting new server thread to service incoming request");
+                    log->crit("unknown error starting new server thread to service incoming request");
                     if (!m_catchAll)
                         *m_shutdown = true;
                 }
@@ -257,9 +272,13 @@ bool SocketListener::run(bool* shutdown)
         m_child_wait->wait(m_child_lock);
     m_child_lock->unlock();
 
+    return true;
+}
+
+void SocketListener::term()
+{
     this->close(m_socket);
     m_socket=(ShibSocket)0;
-    return true;
 }
 
 DDF SocketListener::send(const DDF& in)
@@ -285,7 +304,7 @@ DDF SocketListener::send(const DDF& in)
     SocketListener::ShibSocket sock;
     while (retry >= 0) {
         sock = m_socketpool->get();
-        
+
         int outlen = ostr.length();
         len = htonl(outlen);
         if (send(sock,(char*)&len,sizeof(len)) != sizeof(len) || send(sock,ostr.c_str(),outlen) != outlen) {
@@ -312,7 +331,7 @@ DDF SocketListener::send(const DDF& in)
         throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
     }
     len = ntohl(len);
-    
+
     char buf[16384];
     int size_read;
     stringstream is;
@@ -326,25 +345,25 @@ DDF SocketListener::send(const DDF& in)
                break;
        }
     }
-    
+
     if (len) {
         log->error("error reading output message from socket");
         this->close(sock);
         throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
     }
-    
+
     m_socketpool->put(sock);
 
     // Unmarshall data.
     DDF out;
     is >> out;
-    
+
     // Check for exception to unmarshall and throw, otherwise return.
     if (out.isstring() && out.name() && !strcmp(out.name(),"exception")) {
         // Reconstitute exception object.
         DDFJanitor jout(out);
         XMLToolingException* except=NULL;
-        try { 
+        try {
             except=XMLToolingException::fromString(out.string());
             log->error("remoted message returned an error: %s", except->what());
         }
@@ -418,7 +437,7 @@ ServerThread::~ServerThread()
     m_listener->m_children.erase(m_sock);
     m_listener->m_child_lock->unlock();
     m_listener->m_child_wait->signal();
-  
+
     delete m_child;
 }
 
@@ -432,7 +451,7 @@ void ServerThread::run()
         m_listener->m_child_wait->wait(m_listener->m_child_lock);
     m_listener->m_children[m_sock] = m_child;
     m_listener->m_child_lock->unlock();
-    
+
     int result;
     fd_set readfds;
     struct timeval tv = { 0, 0 };
@@ -494,19 +513,19 @@ int ServerThread::job()
             return -1;
         }
         len = ntohl(len);
-        
+
         int size_read;
         stringstream is;
         while (len && (size_read = m_listener->recv(m_sock, m_buf, sizeof(m_buf))) > 0) {
             is.write(m_buf, size_read);
             len -= size_read;
         }
-        
+
         if (len) {
             log.error("error reading input message from socket");
             return -1;
         }
-        
+
         // Unmarshall the message.
         DDF in;
         DDFJanitor jin(in);
@@ -544,7 +563,7 @@ int ServerThread::job()
         DDFJanitor jout(out);
         sink << out;
     }
-    
+
     // Return whatever's available.
     string response(sink.str());
     int outlen = response.length();
@@ -557,6 +576,6 @@ int ServerThread::job()
         log.error("error sending output message");
         return -1;
     }
-    
+
     return 0;
 }
index 0922cf4..a558650 100644 (file)
@@ -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 @@
 
 /**
  * SocketListener.h
- * 
+ *
  * Berkeley Socket-based ListenerService implementation
  */
 
@@ -41,7 +41,7 @@ namespace shibsp {
 
     class SocketPool;
     class ServerThread;
-    
+
     /**
      * Berkeley Socket-based ListenerService implementation
      */
@@ -53,7 +53,10 @@ namespace shibsp {
         ~SocketListener();
 
         DDF send(const DDF& in);
+
+        bool init(bool force);
         bool run(bool* shutdown);
+        void term();
 
         // Implemented by socket-specific subclasses.
 #ifdef WIN32
@@ -74,7 +77,7 @@ namespace shibsp {
         bool log_error() const; // for OS-level errors
         xmltooling::logging::Category* log;
         /// @endcond
-    
+
     private:
         mutable SocketPool* m_socketpool;
         bool* m_shutdown;
index 44828e6..05f2f90 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * TCPListener.cpp
- * 
+ *
  * TCP-based SocketListener implementation
  */
 
@@ -31,6 +31,7 @@
 # include <sys/un.h>
 # include <unistd.h>
 # include <arpa/inet.h>
+# include <netinet/in.h>
 #endif
 
 #include <sys/types.h>
@@ -60,21 +61,21 @@ namespace shibsp {
         bool connect(ShibSocket& s) const;
         bool close(ShibSocket& s) const;
         bool accept(ShibSocket& listener, ShibSocket& s) const;
-        
+
         int send(ShibSocket& s, const char* buf, int len) const {
             return ::send(s, buf, len, 0);
         }
-        
+
         int recv(ShibSocket& s, char* buf, int buflen) const {
             return ::recv(s, buf, buflen, 0);
         }
-        
+
     private:
         void setup_tcp_sockaddr(struct sockaddr_in* addr) const;
 
         string m_address;
         unsigned short m_port;
-        vector<string> m_acl;
+        set<string> m_acl;
     };
 
     ListenerService* SHIBSP_DLLLOCAL TCPListenerServiceFactory(const DOMElement* const & e)
@@ -91,14 +92,14 @@ TCPListener::TCPListener(const DOMElement* e) : SocketListener(e), m_address("12
         auto_ptr_char a(tag);
         m_address=a.get();
     }
-    
+
     tag=e->getAttributeNS(NULL,port);
     if (tag && *tag) {
         m_port=XMLString::parseInt(tag);
         if (m_port==0)
             m_port=12345;
     }
-    
+
     tag=e->getAttributeNS(NULL,acl);
     if (tag && *tag) {
         auto_ptr_char temp(tag);
@@ -107,15 +108,15 @@ TCPListener::TCPListener(const DOMElement* e) : SocketListener(e), m_address("12
             int j = 0;
             for (unsigned int i=0;  i < sockacl.length();  i++) {
                 if (sockacl.at(i)==' ') {
-                    m_acl.push_back(sockacl.substr(j, i-j));
+                    m_acl.insert(sockacl.substr(j, i-j));
                     j = i+1;
                 }
             }
-            m_acl.push_back(sockacl.substr(j, sockacl.length()-j));
+            m_acl.insert(sockacl.substr(j, sockacl.length()-j));
         }
     }
     else
-        m_acl.push_back("127.0.0.1");
+        m_acl.insert("127.0.0.1");
 }
 
 void TCPListener::setup_tcp_sockaddr(struct sockaddr_in* addr) const
@@ -204,12 +205,11 @@ bool TCPListener::accept(ShibSocket& listener, ShibSocket& s) const
 #endif
         return log_error();
     char* client=inet_ntoa(addr.sin_addr);
-    for (vector<string>::const_iterator i=m_acl.begin(); i!=m_acl.end(); i++) {
-        if (*i==client)
-            return true;
+    if (m_acl.count(client) == 0) {
+        close(s);
+        s=-1;
+        log->error("accept() rejected client at %s", client);
+        return false;
     }
-    close(s);
-    s=-1;
-    log->error("accept() rejected client at %s\n",client);
-    return false;
+    return true;
 }
index 463bb8c..ae44d4f 100644 (file)
@@ -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 @@
 
 /**
  * ddf.cpp
- * 
+ *
  * C++ DDF abstraction for interpretive RPC
  */
 
@@ -32,6 +32,7 @@
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/URLEncoder.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
@@ -61,22 +62,19 @@ char* ddf_strdup(const char* s)
    The name buffer is returned from the function. */
 char* ddf_token(const char** path, char* name)
 {
-    const char* temp=NULL;
-    
-    *name='\0';
-    if (*path==NULL || **path=='\0')
+    *name=0;
+    if (*path==NULL || **path==0)
         return name;
 
-    temp=strchr(*path,'.');
-    if (temp==NULL)
-    {
-        strcpy(name,*path);
+    const char* temp=strchr(*path,'.');
+    if (temp==NULL) {
+        strncpy(name,*path,MAX_NAME_LEN);
+        name[MAX_NAME_LEN]=0;
         *path=NULL;
     }
-    else if (temp>*path)
-    {
+    else if (temp>*path) {
         strncpy(name,*path,temp-*path);
-        name[temp-*path]='\0';
+        name[temp-*path]=0;
         *path=temp+1;
     }
     else
@@ -101,7 +99,8 @@ struct shibsp::ddf_body_t {
         DDF_FLOAT,
            DDF_STRUCT,
         DDF_LIST,
-           DDF_POINTER
+           DDF_POINTER,
+        DDF_STRING_UNSAFE
     } type;                         // data type of node
 
     union {
@@ -126,11 +125,11 @@ DDF::DDF(const char* n)
     name(n);
 }
 
-DDF::DDF(const char* n, const char* val)
+DDF::DDF(const char* n, const char* val, bool safe)
 {
     m_handle=new(nothrow) ddf_body_t;
     name(n);
-    string(val);
+    string(const_cast<char*>(val), true, safe);
 }
 
 DDF::DDF(const char* n, long val)
@@ -171,7 +170,8 @@ DDF DDF::copy() const
         case ddf_body_t::DDF_EMPTY:
             return DDF(m_handle->name);
         case ddf_body_t::DDF_STRING:
-            return DDF(m_handle->name,m_handle->value.string);
+        case ddf_body_t::DDF_STRING_UNSAFE:
+            return DDF(m_handle->name,m_handle->value.string,(m_handle->type==ddf_body_t::DDF_STRING));
         case ddf_body_t::DDF_INT:
             return DDF(m_handle->name,m_handle->value.integer);
         case ddf_body_t::DDF_FLOAT:
@@ -240,7 +240,7 @@ bool DDF::isempty() const
 
 bool DDF::isstring() const
 {
-    return m_handle ? (m_handle->type==ddf_body_t::DDF_STRING) : false;
+    return m_handle ? (m_handle->type==ddf_body_t::DDF_STRING || m_handle->type==ddf_body_t::DDF_STRING_UNSAFE) : false;
 }
 
 bool DDF::isint() const
@@ -282,6 +282,7 @@ long DDF::integer() const
             case ddf_body_t::DDF_FLOAT:
                 return static_cast<long>(m_handle->value.floating);
             case ddf_body_t::DDF_STRING:
+            case ddf_body_t::DDF_STRING_UNSAFE:
                 return m_handle->value.string ? atol(m_handle->value.string) : 0;
             case ddf_body_t::DDF_STRUCT:
             case ddf_body_t::DDF_LIST:
@@ -300,6 +301,7 @@ double DDF::floating() const
             case ddf_body_t::DDF_FLOAT:
                 return m_handle->value.floating;
             case ddf_body_t::DDF_STRING:
+            case ddf_body_t::DDF_STRING_UNSAFE:
                 return m_handle->value.string ? atof(m_handle->value.string) : 0;
             case ddf_body_t::DDF_STRUCT:
             case ddf_body_t::DDF_LIST:
@@ -332,6 +334,7 @@ DDF& DDF::empty()
     if (m_handle) {
         switch (m_handle->type) {
             case ddf_body_t::DDF_STRING:
+            case ddf_body_t::DDF_STRING_UNSAFE:
                 if (m_handle->value.string)
                     free(m_handle->value.string);
                 break;
@@ -351,13 +354,13 @@ DDF& DDF::empty()
     return *this;
 }
 
-DDF& DDF::string(char* val, bool copyit)
+DDF& DDF::string(char* val, bool copyit, bool safe)
 {
     if (empty().m_handle) {
         m_handle->value.string = copyit ? ddf_strdup(val) : val;
         if (!m_handle->value.string && val && *val)
             return destroy();
-        m_handle->type=ddf_body_t::DDF_STRING;
+        m_handle->type=(safe ? ddf_body_t::DDF_STRING : ddf_body_t::DDF_STRING_UNSAFE);
     }
     return *this;
 }
@@ -614,7 +617,7 @@ DDF DDF::addmember(const char* path)
 {
     char name[MAX_NAME_LEN+1];
     const char* path_ptr=path;
-    
+
     if (m_handle && ddf_strlen(ddf_token(&path_ptr,name))>0) {
         if (!isstruct())
             structure();
@@ -642,18 +645,32 @@ DDF DDF::addmember(const char* path)
 
 DDF DDF::getmember(const char* path) const
 {
+    DDF current;
     char name[MAX_NAME_LEN+1];
     const char* path_ptr=path;
-    DDF current;
 
-    if (isstruct() && ddf_strlen(ddf_token(&path_ptr,name))>0) {
-        current.m_handle=m_handle->value.children.first;
-        while (current.m_handle && strcmp(current.m_handle->name,name)!=0)
-            current.m_handle=current.m_handle->next;
-
-        if (current.m_handle && ddf_strlen(path_ptr)>0)
-            current=current.getmember(path_ptr);
+    ddf_token(&path_ptr, name);
+    if (*name == 0)
+        return current;
+    else if (*name == '[') {
+        unsigned long i = strtoul(name+1, NULL, 10);
+        if (islist() && i < m_handle->value.children.count)
+            current=operator[](i);
+        else if (i == 0)
+            current = *this;
+    }
+    else if (isstruct()) {
+        current.m_handle = m_handle->value.children.first;
+        while (current.m_handle && strcmp(current.m_handle->name,name) != 0)
+            current.m_handle = current.m_handle->next;
+    }
+    else if (islist()) {
+        current.m_handle = m_handle->value.children.first;
+        return current.getmember(path);
     }
+
+    if (current.m_handle && path_ptr && *path_ptr)
+        current = current.getmember(path_ptr);
     return current;
 }
 
@@ -672,7 +689,7 @@ void DDF::dump(FILE* f, int indent) const
     ddf_print_indent(f,indent);
     if (m_handle) {
         switch (m_handle->type) {
-            
+
             case ddf_body_t::DDF_EMPTY:
                 fprintf(f,"empty");
                 if (m_handle->name)
@@ -680,6 +697,7 @@ void DDF::dump(FILE* f, int indent) const
                 break;
 
             case ddf_body_t::DDF_STRING:
+            case ddf_body_t::DDF_STRING_UNSAFE:
                 if (m_handle->name)
                     fprintf(f,"char* %s = ",m_handle->name);
                 else
@@ -796,8 +814,9 @@ void serialize(ddf_body_t* p, ostream& os, bool name_attr=true)
 {
     if (p) {
         switch (p->type) {
-            
+
             case ddf_body_t::DDF_STRING:
+            case ddf_body_t::DDF_STRING_UNSAFE:
                 os << "<string";
                 if (name_attr && p->name) {
                     os << " name=\"";
@@ -805,8 +824,14 @@ void serialize(ddf_body_t* p, ostream& os, bool name_attr=true)
                     os << '"';
                 }
                 if (p->value.string) {
-                    os << '>';
-                    xml_encode(os,p->value.string);
+                    if (p->type == ddf_body_t::DDF_STRING) {
+                        os << '>';
+                        xml_encode(os,p->value.string);
+                    }
+                    else {
+                        os << " unsafe=\"1\">";
+                        xml_encode(os,XMLToolingConfig::getConfig().getURLEncoder()->encode(p->value.string).c_str());
+                    }
                     os << "</string>";
                 }
                 else
@@ -941,11 +966,12 @@ static const XMLCh _number[] =  UNICODE_LITERAL_6(n,u,m,b,e,r);
 static const XMLCh _array[] =   UNICODE_LITERAL_5(a,r,r,a,y);
 static const XMLCh _struct[] =  UNICODE_LITERAL_6(s,t,r,u,c,t);
 static const XMLCh _lowercase[] = UNICODE_LITERAL_9(l,o,w,e,r,c,a,s,e);
+static const XMLCh _unsafe[] =  UNICODE_LITERAL_6(u,n,s,a,f,e);
 
 DDF deserialize(DOMElement* root, bool lowercase)
 {
     DDF obj(NULL);
-    auto_ptr_char name_val(root->getAttribute(_name));
+    auto_ptr_char name_val(root->getAttributeNS(NULL, _name));
     if (name_val.get() && *name_val.get()) {
         if (lowercase)
             for (char* pch=const_cast<char*>(name_val.get()); *pch=tolower(*pch); pch++);
@@ -961,9 +987,19 @@ DDF deserialize(DOMElement* root, bool lowercase)
     if (XMLString::equals(tag,_string)) {
         DOMNode* child=root->getFirstChild();
         if (child && child->getNodeType()==DOMNode::TEXT_NODE) {
-            char* val = toUTF8(child->getNodeValue(), true);    // use malloc
-            if (val)
-                obj.string(val, false); // don't re-copy the string
+            const XMLCh* unsafe = root->getAttributeNS(NULL, _unsafe);
+            if (unsafe && *unsafe==chDigit_1) {
+                // If it's unsafe, it's not UTF-8 data, so we have to convert to ASCII and decode it.
+                char* encoded = XMLString::transcode(child->getNodeValue());
+                XMLToolingConfig::getConfig().getURLEncoder()->decode(encoded);
+                obj.string(encoded, true, false); // re-copy into free-able buffer, plus mark unsafe
+                XMLString::release(&encoded);
+            }
+            else {
+                char* val = toUTF8(child->getNodeValue(), true);    // use malloc
+                if (val)
+                    obj.string(val, false); // don't re-copy the string
+            }
         }
     }
     else if (XMLString::equals(tag,_number)) {
index c8ed9bc..d52db86 100644 (file)
@@ -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.
@@ -272,7 +272,6 @@ void MetadataPKIXIterator::populate()
     if (m_caching) {
         m_engine.m_credLock->unlock();
         m_engine.m_credLock->wrlock();
-        PKIXTrustEngine::credmap_t::iterator cached = m_credCache->second.find(m_current);
         if (m_credCache->second.count(m_current)==0) {
             // Transfer objects into cache.
             m_credCache->second[m_current] = m_ownedCreds;
index 6e260d4..8317554 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
 
 /**
  * SecurityPolicy.cpp
- * 
+ *
  * SP-specific SecurityPolicy subclass.
  */
 
 #include "internal.h"
 #include "Application.h"
 #include "ServiceProvider.h"
+#include "metadata/MetadataProviderCriteria.h"
 #include "security/SecurityPolicy.h"
 
 using namespace shibsp;
+using namespace opensaml::saml2;
+using namespace std;
 
-SecurityPolicy::SecurityPolicy(const Application& application, const xmltooling::QName* role, bool validate)
-    : opensaml::SecurityPolicy(application.getMetadataProvider(), role, application.getTrustEngine(), validate), m_application(application) {
-
-    const std::vector<const opensaml::SecurityPolicyRule*>& rules =
-        application.getServiceProvider().getPolicyRules(application.getString("policyId").second);
+SecurityPolicy::SecurityPolicy(const Application& application, const xmltooling::QName* role, bool validate, const char* policyId)
+        : opensaml::SecurityPolicy(application.getMetadataProvider(), role, application.getTrustEngine(), validate), m_application(application) {
+    const vector<const opensaml::SecurityPolicyRule*>& rules =
+        application.getServiceProvider().getPolicyRules(policyId ? policyId : application.getString("policyId").second);
     getRules().assign(rules.begin(), rules.end());
+
+    // Populate audiences.
+    if (application.getAudiences()) {
+        for (vector<const XMLCh*>::const_iterator a = application.getAudiences()->begin(); a != application.getAudiences()->end(); ++a)
+            getAudiences().push_back(*a);
+    }
+}
+
+opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProviderCriteria() const
+{
+    if (!m_metadataCriteria)
+        m_metadataCriteria=new MetadataProviderCriteria(m_application);
+    else
+        m_metadataCriteria->reset();
+    return *m_metadataCriteria;
 }
index 74745ff..29a3bf5 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/security/SecurityPolicy.h
- * 
+ *
  * SP-specific SecurityPolicy subclass.
  */
 
 #define __shibsp_secpol_h__
 
 #include <shibsp/base.h>
-#include <saml/binding/SecurityPolicy.h>
+#include <saml/saml2/profile/SAML2AssertionPolicy.h>
 
 namespace shibsp {
-    
+
     class SHIBSP_API Application;
 
     /**
      * SP-specific SecurityPolicy subclass.
      */
-    class SHIBSP_API SecurityPolicy : public opensaml::SecurityPolicy
+    class SHIBSP_API SecurityPolicy : public opensaml::saml2::SAML2AssertionPolicy
     {
     public:
         /**
          * Constructor for policy.
-         * 
+         *
          * @param application       an Application instance
-         * @param role              identifies the role (generally IdP or SP) of the policy peer 
+         * @param role              identifies the role (generally IdP or SP) of the policy peer
          * @param validate          true iff XML parsing should be done with validation
+         * @param policyId          identifies policy rules to auto-attach, defaults to the application's set
          */
-        SecurityPolicy(const Application& application, const xmltooling::QName* role=NULL, bool validate=true);
+        SecurityPolicy(const Application& application, const xmltooling::QName* role=NULL, bool validate=true, const char* policyId=NULL);
 
         virtual ~SecurityPolicy() {}
 
+        opensaml::saml2md::MetadataProvider::Criteria& getMetadataProviderCriteria() const;
+
         /**
          * Returns the Application associated with the policy.
-         * 
+         *
          * @return the associated Application
          */
         const Application& getApplication() const {
index 48dc6af..e465154 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="shibsp-lite"\r
        ProjectGUID="{81F0F7A6-DC36-46EF-957F-F9E81D4403F7}"\r
        RootNamespace="shibsp-lite"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"\r
                                TargetMachine="1"\r
                        />\r
@@ -93,9 +96,6 @@
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"\r
                                TargetMachine="17"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1.dll"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1.lib"\r
                                TargetMachine="1"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1.dll"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1.lib"\r
                                TargetMachine="17"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                                Name="impl"\r
                                >\r
                                <File\r
+                                       RelativePath=".\impl\ChainingAccessControl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
                                        >\r
                                </File>\r
                                        RelativePath=".\attribute\Attribute.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="handler"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttribute.h"\r
                                        >\r
                                </File>\r
                                        RelativePath=".\attribute\SimpleAttribute.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttribute.h"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="handler"\r
index 5f8cda8..b39d484 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 1,1,0,0\r
- PRODUCTVERSION 2,1,0,0\r
+ FILEVERSION 1,2,1,0\r
+ PRODUCTVERSION 2,2,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -51,38 +51,38 @@ BEGIN
 #else\r
             VALUE "FileDescription", "Shibboleth SP Library\0"\r
 #endif\r
-            VALUE "FileVersion", "1, 1, 0, 0\0"\r
+            VALUE "FileVersion", "1, 2, 1, 0\0"\r
 #ifdef SHIBSP_LITE\r
 #ifdef _DEBUG\r
-            VALUE "InternalName", "shibsp-lite1_1D\0"\r
+            VALUE "InternalName", "shibsp-lite1_2D\0"\r
 #else\r
-            VALUE "InternalName", "shibsp-lite1_1\0"\r
+            VALUE "InternalName", "shibsp-lite1_2\0"\r
 #endif\r
 #else\r
 #ifdef _DEBUG\r
-            VALUE "InternalName", "shibsp1_1D\0"\r
+            VALUE "InternalName", "shibsp1_2D\0"\r
 #else\r
-            VALUE "InternalName", "shibsp1_1\0"\r
+            VALUE "InternalName", "shibsp1_2\0"\r
 #endif\r
 #endif\r
-            VALUE "LegalCopyright", "Copyright Â© 2008 Internet2\0"\r
+            VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
 #ifdef SHIBSP_LITE\r
 #ifdef _DEBUG\r
-            VALUE "OriginalFilename", "shibsp-lite1_1D.dll\0"\r
+            VALUE "OriginalFilename", "shibsp-lite1_2D.dll\0"\r
 #else\r
-            VALUE "OriginalFilename", "shibsp-lite1_1.dll\0"\r
+            VALUE "OriginalFilename", "shibsp-lite1_2.dll\0"\r
 #endif\r
 #else\r
 #ifdef _DEBUG\r
-            VALUE "OriginalFilename", "shibsp1_1D.dll\0"\r
+            VALUE "OriginalFilename", "shibsp1_2D.dll\0"\r
 #else\r
-            VALUE "OriginalFilename", "shibsp1_1.dll\0"\r
+            VALUE "OriginalFilename", "shibsp1_2.dll\0"\r
 #endif\r
 #endif\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.1\0"\r
-            VALUE "ProductVersion", "2, 1, 0, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
+            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index bb58f7e..cbd630d 100644 (file)
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="shibsp"\r
        ProjectGUID="{81F0F7A6-DC36-46EF-957F-F9E81D4403F6}"\r
        RootNamespace="shibsp"\r
        Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"\r
                                TargetMachine="1"\r
                        />\r
@@ -93,9 +96,6 @@
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"\r
+                               AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"\r
                                TargetMachine="17"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1.dll"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1.lib"\r
                                TargetMachine="1"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib xerces-c_2.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_1.dll"\r
+                               AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                ImportLibrary="$(TargetDir)$(ProjectName)1.lib"\r
                                TargetMachine="17"\r
                        />\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                                Name="impl"\r
                                >\r
                                <File\r
+                                       RelativePath=".\impl\ChainingAccessControl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\impl\StorageServiceSessionCache.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\DOMAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\KeyInfoAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                        RelativePath=".\attribute\StringAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
                                <Filter\r
                                        Name="resolver"\r
                                        >\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\attribute\resolver\impl\DelegationAttributeExtractor.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
+                                                       RelativePath=".\attribute\resolver\impl\KeyDescriptorAttributeExtractor.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\attribute\resolver\impl\QueryAttributeResolver.cpp"\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\attribute\resolver\impl\SimpleAggregationAttributeResolver.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\attribute\resolver\impl\XMLAttributeExtractor.cpp"\r
                                                        >\r
                                                </File>\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\ApplicationAwarePlugin.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
                                RelativePath=".\base.h"\r
                                >\r
                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttribute.h"\r
                                        >\r
                                </File>\r
                                        RelativePath=".\attribute\SimpleAttribute.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttribute.h"\r
+                                       >\r
+                               </File>\r
                                <Filter\r
                                        Name="resolver"\r
                                        >\r
index 1011351..d1cba90 100644 (file)
@@ -61,7 +61,9 @@ CGIParser::~CGIParser()
 
 pair<CGIParser::walker,CGIParser::walker> CGIParser::getParameters(const char* name) const
 {
-    return kvp_map.equal_range(name);
+    if (name)
+        return kvp_map.equal_range(name);
+    return make_pair(kvp_map.begin(), kvp_map.end());
 }
 
 /* Parsing routines modified from NCSA source. */
index b76953d..c0e3371 100644 (file)
@@ -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.
@@ -55,7 +55,7 @@ namespace shibsp {
         /**
          * Returns a pair of bounded iterators around the values of a parameter.
          * 
-         * @param name  name of parameter
+         * @param name  name of parameter, or NULL to return all parameters
          * @return  a pair of multimap iterators surrounding the matching value(s)
          */
         std::pair<walker,walker> getParameters(const char* name) const;
index 8836d4a..b08f76d 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  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.
  * You may obtain a copy of the License at
@@ -16,8 +16,8 @@
 
 /**
  * version.h
- * 
- * Library version macros and constants 
+ *
+ * Library version macros and constants
  */
 
 #ifndef __shibsp_version_h__
 // V E R S I O N   S P E C I F I C A T I O N
 
 /**
- * MODIFY THESE NUMERIC VALUES TO COINCIDE WITH OPENSAML VERSION
+ * MODIFY THESE NUMERIC VALUES TO COINCIDE WITH SHIBSP LIBRARY VERSION
  * AND DO NOT MODIFY ANYTHING ELSE IN THIS VERSION HEADER FILE
  */
 
 #define SHIBSP_VERSION_MAJOR 1
-#define SHIBSP_VERSION_MINOR 0
+#define SHIBSP_VERSION_MINOR 2
 #define SHIBSP_VERSION_REVISION 1
 
 /** DO NOT MODIFY BELOW THIS LINE */
index 33435cc..89cc34e 100644 (file)
@@ -94,48 +94,25 @@ int main(int argc,char* argv[])
 \r
     if (!entityID) {\r
         usage();\r
-        exit(-10);\r
+        return -10;\r
     }\r
 \r
-    char* path=getenv("SHIBSP_SCHEMAS");\r
-    if (!path)\r
-        path=SHIBSP_SCHEMAS;\r
-    char* config=getenv("SHIBSP_CONFIG");\r
-    if (!config)\r
-        config=SHIBSP_CONFIG;\r
-\r
-    XMLToolingConfig::getConfig().log_config(getenv("SHIBSP_LOGGING") ? getenv("SHIBSP_LOGGING") : SHIBSP_LOGGING);\r
-\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);\r
-    if (!conf.init(path))\r
-        return -1;\r
-\r
     if (rname) {\r
         if (!protocol) {\r
             if (prot)\r
                 protocol = XMLString::transcode(prot);\r
         }\r
         if (!protocol) {\r
-            conf.term();\r
             usage();\r
-            exit(-10);\r
+            return -10;\r
         }\r
     }\r
 \r
-    try {\r
-        static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);\r
-        static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-        xercesc::DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();\r
-        XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);\r
-        xercesc::DOMElement* dummy = dummydoc->createElementNS(NULL,_path);\r
-        auto_ptr_XMLCh src(config);\r
-        dummy->setAttributeNS(NULL,_path,src.get());\r
-        dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);\r
-        conf.setServiceProvider(conf.ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));\r
-        conf.getServiceProvider()->init();\r
-    }\r
-    catch (exception&) {\r
+    SPConfig& conf=SPConfig::getConfig();\r
+    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);\r
+    if (!conf.init())\r
+        return -1;\r
+    if (!conf.instantiate()) {\r
         conf.term();\r
         return -2;\r
     }\r
index 5240966..6335253 100644 (file)
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="mdquery"\r
        ProjectGUID="{F13141B6-6C87-40BB-8D4E-5CC56EBB4C5A}"\r
        RootNamespace="mdquery"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"\r
+                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        UseOfMFC="0"\r
                        ATLMinimizesCRunTimeLibraryUsage="false"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               EnableFunctionLevelLinking="true"\r
                                RuntimeTypeInfo="true"\r
-                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
-                               DebugInformationFormat="4"\r
                                CompileAs="0"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"\r
-                               LinkIncremental="2"\r
+                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"\r
+                               LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        UseOfMFC="0"\r
                        ATLMinimizesCRunTimeLibraryUsage="false"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
+                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                RuntimeTypeInfo="true"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
                                CompileAs="0"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"\r
-                               LinkIncremental="1"\r
+                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"\r
+                               LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               TargetMachine="17"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
index 43a0e49..6fe35e2 100644 (file)
@@ -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.
@@ -115,8 +115,6 @@ int main(int argc,char* argv[])
     char* i_param=NULL;
     char* prot = NULL;
     const XMLCh* protocol = NULL;
-    char* path=NULL;
-    char* config=NULL;
 
     for (int i=1; i<argc; i++) {
         if (!strcmp(argv[i],"-n") && i+1<argc)
@@ -139,57 +137,34 @@ int main(int argc,char* argv[])
 
     if (n_param && !i_param) {
         usage();
-        exit(-10);
+        return -10;
     }
 
-    path=getenv("SHIBSP_SCHEMAS");
-    if (!path)
-        path=SHIBSP_SCHEMAS;
-    config=getenv("SHIBSP_CONFIG");
-    if (!config)
-        config=SHIBSP_CONFIG;
     if (!a_param)
         a_param="default";
 
-    XMLToolingConfig::getConfig().log_config(getenv("SHIBSP_LOGGING") ? getenv("SHIBSP_LOGGING") : SHIBSP_LOGGING);
-
-    SPConfig& conf=SPConfig::getConfig();
-    conf.setFeatures(
-        SPConfig::Metadata |
-        SPConfig::Trust |
-        SPConfig::AttributeResolution |
-        SPConfig::Credentials |
-        SPConfig::OutOfProcess
-        );
-    if (!conf.init(path))
-        return -1;
-
     if (n_param) {
         if (!protocol) {
             if (prot)
                 protocol = XMLString::transcode(prot);
         }
         if (!protocol) {
-            conf.term();
             usage();
-            exit(-10);
+            return -10;
         }
     }
-   
-    try {
-        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);
-        xercesc::DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();
-        XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);
-        xercesc::DOMElement* dummy = dummydoc->createElementNS(NULL,path);
-        auto_ptr_XMLCh src(config);
-        dummy->setAttributeNS(NULL,path,src.get());
-        dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);
 
-        conf.setServiceProvider(conf.ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));
-        conf.getServiceProvider()->init();
-    }
-    catch (exception&) {
+    SPConfig& conf=SPConfig::getConfig();
+    conf.setFeatures(
+        SPConfig::Metadata |
+        SPConfig::Trust |
+        SPConfig::AttributeResolution |
+        SPConfig::Credentials |
+        SPConfig::OutOfProcess
+        );
+    if (!conf.init())
+        return -1;
+    if (!conf.instantiate()) {
         conf.term();
         return -2;
     }
@@ -270,21 +245,25 @@ int main(int argc,char* argv[])
                     protocol = samlconstants::SAML11_PROTOCOL_ENUM;
                 v1name = a1->getAuthenticationStatements().size() ?
                     a1->getAuthenticationStatements().front()->getSubject()->getNameIdentifier() : NULL;
-                // Normalize the SAML 1.x NameIdentifier...
-                v2name = saml2::NameIDBuilder::buildNameID();
-                v2name->setName(v1name->getName());
-                v2name->setFormat(v1name->getFormat());
-                v2name->setNameQualifier(v1name->getNameQualifier());
+                if (!v1name)
+                    v1name = a1->getAttributeStatements().size() ?
+                    a1->getAttributeStatements().front()->getSubject()->getNameIdentifier() : NULL;
+                if (v1name) {
+                    // Normalize the SAML 1.x NameIdentifier...
+                    v2name = saml2::NameIDBuilder::buildNameID();
+                    v2name->setName(v1name->getName());
+                    v2name->setFormat(v1name->getFormat());
+                    v2name->setNameQualifier(v1name->getNameQualifier());
+                }
             }
             else {
                 throw FatalProfileException("Unknown assertion type.");
             }
 
-            if (!issuer) {
-                if (v1name)
-                    delete v2name;
+            auto_ptr<saml2::NameID> nameidwrapper(v1name ? v2name : NULL);
+
+            if (!issuer)
                 throw FatalProfileException("Unable to determine issuer.");
-            }
 
             MetadataProvider* m=app->getMetadataProvider();
             xmltooling::Locker mlocker(m);
@@ -297,23 +276,20 @@ int main(int argc,char* argv[])
             
             vector<const Assertion*> tokens(1, dynamic_cast<Assertion*>(token.get()));
             ResolverTest rt(NULL, a_param);
-            try {
-                ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name, NULL, NULL, &tokens);
-            }
-            catch (...) {
-                if (v1name)
-                    delete v2name;
-                throw;
-            }
+            ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name, NULL, NULL, &tokens);
         }
 
         auto_ptr<ResolutionContext> wrapper(ctx);
         for (vector<Attribute*>::const_iterator a = ctx->getResolvedAttributes().begin(); a != ctx->getResolvedAttributes().end(); ++a) {
-            cout << endl;
-            for (vector<string>::const_iterator s = (*a)->getAliases().begin(); s != (*a)->getAliases().end(); ++s)
-                cout << "ID: " << *s << endl;
-            for (vector<string>::const_iterator s = (*a)->getSerializedValues().begin(); s != (*a)->getSerializedValues().end(); ++s)
-                cout << "Value: " << *s << endl;
+            for (vector<string>::const_iterator s = (*a)->getAliases().begin(); s != (*a)->getAliases().end(); ++s) {
+                cout << *s << ": ";
+                for (vector<string>::const_iterator v = (*a)->getSerializedValues().begin(); v != (*a)->getSerializedValues().end(); ++v) {
+                    if (v != (*a)->getSerializedValues().begin())
+                        cout << ';';
+                    cout << *v;
+                }
+                cout << endl;
+            }
         }
         cout << endl;
     }
index 4ced967..26a719b 100644 (file)
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="8.00"\r
+       Version="9.00"\r
        Name="resolvertest"\r
        ProjectGUID="{F13141B6-6C87-40BB-8D4E-5CC56EBB4C59}"\r
        RootNamespace="resolvertest"\r
+       TargetFrameworkVersion="131072"\r
        >\r
        <Platforms>\r
                <Platform\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"\r
+                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="0"\r
                        ATLMinimizesCRunTimeLibraryUsage="false"\r
                        CharacterSet="2"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               EnableFunctionLevelLinking="true"\r
                                RuntimeTypeInfo="true"\r
-                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
-                               DebugInformationFormat="4"\r
                                CompileAs="0"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
+                               PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"\r
-                               LinkIncremental="2"\r
+                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"\r
+                               LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
-                               GenerateDebugInformation="true"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="0"\r
                        ATLMinimizesCRunTimeLibraryUsage="false"\r
                        CharacterSet="2"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                                HeaderFileName=""\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories=".;..;&quot;..\..\cpp-opensaml2&quot;;&quot;..\..\cpp-xmltooling&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
+                               PreprocessorDefinitions="_CONSOLE;WIN32;_DEBUG"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                RuntimeTypeInfo="true"\r
+                               BrowseInformation="1"\r
                                WarningLevel="3"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
                                CompileAs="0"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
+                               PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
                        />\r
                        <Tool\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"\r
-                               LinkIncremental="1"\r
+                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"\r
+                               LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
+                               AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               TargetMachine="17"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"\r
+                               AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
                                TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCAppVerifierTool"\r
                        />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
                                Name="VCPostBuildEventTool"\r
                        />\r
                </Configuration>\r