[cpp-sp] 03/40: Imported Upstream version 2.2.1+dfsg
Scott Cantor
cantor.2 at osu.edu
Thu Dec 20 19:42:24 EST 2018
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to annotated tag debian/2.2.1+dfsg-1
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=a5b1914f888d2ac8992cc4985d65e9d727aa8df4
commit a5b1914f888d2ac8992cc4985d65e9d727aa8df4
Author: Russ Allbery <rra at debian.org>
AuthorDate: Fri Aug 21 10:32:58 2009 -0700
Imported Upstream version 2.2.1+dfsg
---
Makefile.am | 30 +-
Makefile.in | 66 +-
Portfile | 69 +
Portfile.in | 69 +
Shibboleth.sln | 106 +-
adfs/adfs-lite.vcproj | 85 +-
adfs/adfs.cpp | 125 +-
adfs/adfs.rc | 12 +-
adfs/adfs.vcproj | 83 +-
apache/mod_apache.cpp | 95 +-
apache/mod_shib13.vcproj | 103 +-
apache/mod_shib20.vcproj | 103 +-
apache/mod_shib22.vcproj | 103 +-
apache/mod_shib_13.cpp | 3 +-
apache/mod_shib_13.rc | 12 +-
apache/mod_shib_20.cpp | 3 +-
apache/mod_shib_20.rc | 12 +-
apache/mod_shib_22.cpp | 3 +-
apache/mod_shib_22.rc | 12 +-
config.h.in | 6 +
config_win32.h | 13 +-
configs/Makefile.am | 15 +-
configs/Makefile.in | 13 +-
configs/attribute-map.xml | 10 +-
configs/keygen.bat | 2 +-
configs/metagen.sh | 211 +++
configs/postTemplate.html | 41 +
configs/shibboleth2.xml | 52 +-
configs/shibd-debian.in | 6 +-
configs/shibd-osx.plist.in | 1 +
configs/shibd-redhat.in | 10 +-
configs/shibd-suse.in | 112 ++
configure | 487 +++--
configure.ac | 95 +-
depend | 4 +-
doc/FASTCGI.LICENSE | 56 +-
doc/LOG4CPP.LICENSE | 1008 +++++-----
doc/Makefile.am | 6 +-
doc/Makefile.in | 23 +-
doc/OPENSSL.LICENSE | 254 +--
doc/README.txt | 3 +-
doc/RELEASE.txt | 21 +-
doc/main.css | 76 +-
doxygen.m4 | 7 +-
fastcgi/shibauthorizer.cpp | 22 +-
fastcgi/shibauthorizer.rc | 12 +-
fastcgi/shibauthorizer.vcproj | 104 +-
fastcgi/shibresponder.cpp | 3 +
fastcgi/shibresponder.rc | 12 +-
fastcgi/shibresponder.vcproj | 105 +-
isapi_shib/isapi_shib.cpp | 199 +-
isapi_shib/{isapi_shib.cpp => isapi_shib.cpp.mine} | 1929 ++++++++++----------
.../{isapi_shib.cpp => isapi_shib.cpp.r3059} | 36 +-
.../{isapi_shib.cpp => isapi_shib.cpp.r3097} | 174 +-
isapi_shib/isapi_shib.rc | 12 +-
isapi_shib/isapi_shib.vcproj | 97 +-
memcache-store/memcache-store.cpp | 154 +-
memcache-store/memcache-store.rc | 12 +-
memcache-store/memcache-store.vcproj | 93 +-
nsapi_shib/nsapi_shib.cpp | 157 +-
nsapi_shib/nsapi_shib.rc | 12 +-
nsapi_shib/nsapi_shib.vcproj | 99 +-
odbc-store/odbc-store.rc | 12 +-
odbc-store/odbc-store.vcproj | 83 +-
pkginfo | 2 +-
pkginfo.in | 2 +-
schemas/shibboleth-2.0-attribute-map.xsd | 35 +-
schemas/shibboleth-2.0-native-sp-config.xsd | 22 +-
shibboleth.spec | 240 ++-
shibboleth.spec.in | 242 ++-
shibd/shibd.cpp | 135 +-
shibd/shibd.rc | 12 +-
shibd/shibd.vcproj | 85 +-
shibsp/AbstractSPRequest.cpp | 46 +-
shibsp/AbstractSPRequest.h | 2 +
shibsp/AccessControl.h | 19 +-
shibsp/Application.cpp | 15 +
shibsp/Application.h | 86 +-
shibsp/Makefile.am | 30 +-
shibsp/Makefile.in | 148 +-
shibsp/SPConfig.cpp | 40 +-
shibsp/SPConfig.h | 8 +-
shibsp/SPRequest.h | 56 +-
shibsp/ServiceProvider.cpp | 63 +-
shibsp/attribute/Attribute.cpp | 116 +-
shibsp/attribute/Attribute.h | 116 +-
shibsp/attribute/AttributeDecoder.h | 26 +-
shibsp/attribute/DOMAttributeDecoder.cpp | 226 +++
shibsp/attribute/ExtensibleAttribute.cpp | 79 +
shibsp/attribute/ExtensibleAttribute.h | 118 ++
shibsp/attribute/KeyInfoAttributeDecoder.cpp | 157 ++
shibsp/attribute/NameIDAttribute.h | 17 +-
shibsp/attribute/NameIDAttributeDecoder.cpp | 26 +-
.../attribute/NameIDFromScopedAttributeDecoder.cpp | 28 +-
shibsp/attribute/ScopedAttribute.h | 13 +-
shibsp/attribute/ScopedAttributeDecoder.cpp | 9 +-
shibsp/attribute/StringAttributeDecoder.cpp | 7 +-
shibsp/attribute/XMLAttribute.h | 111 ++
shibsp/attribute/XMLAttributeDecoder.cpp | 138 ++
.../attribute/filtering/impl/AndMatchFunctor.cpp | 2 +-
shibsp/attribute/filtering/impl/MatchFunctor.cpp | 8 +-
.../attribute/filtering/impl/NotMatchFunctor.cpp | 2 +-
shibsp/attribute/filtering/impl/OrMatchFunctor.cpp | 2 +-
.../filtering/impl/XMLAttributeFilter.cpp | 32 +-
shibsp/attribute/resolver/AttributeExtractor.h | 16 +-
shibsp/attribute/resolver/AttributeResolver.h | 21 +-
.../resolver/impl/ChainingAttributeExtractor.cpp | 6 +-
.../resolver/impl/ChainingAttributeResolver.cpp | 7 +-
.../resolver/impl/DelegationAttributeExtractor.cpp | 205 +++
.../impl/KeyDescriptorAttributeExtractor.cpp | 177 ++
.../resolver/impl/QueryAttributeResolver.cpp | 65 +-
.../impl/SimpleAggregationAttributeResolver.cpp | 603 ++++++
.../resolver/impl/XMLAttributeExtractor.cpp | 486 ++++-
shibsp/base.h | 41 +-
shibsp/binding/SOAPClient.h | 5 +-
shibsp/binding/impl/ArtifactResolver.cpp | 2 +-
shibsp/binding/impl/SOAPClient.cpp | 11 +-
shibsp/handler/AbstractHandler.h | 57 +-
shibsp/handler/AssertionConsumerService.h | 19 +-
shibsp/handler/impl/AbstractHandler.cpp | 262 ++-
shibsp/handler/impl/AssertionConsumerService.cpp | 91 +-
shibsp/handler/impl/AssertionLookup.cpp | 21 +-
shibsp/handler/impl/ChainingLogoutInitiator.cpp | 7 +-
shibsp/handler/impl/ChainingSessionInitiator.cpp | 7 +-
shibsp/handler/impl/LogoutHandler.cpp | 20 +-
shibsp/handler/impl/MetadataGenerator.cpp | 45 +-
shibsp/handler/impl/RemotedHandler.cpp | 10 +-
shibsp/handler/impl/SAML1Consumer.cpp | 63 +-
shibsp/handler/impl/SAML2ArtifactResolution.cpp | 4 +-
shibsp/handler/impl/SAML2Consumer.cpp | 110 +-
shibsp/handler/impl/SAML2Logout.cpp | 43 +-
shibsp/handler/impl/SAML2LogoutInitiator.cpp | 10 +-
shibsp/handler/impl/SAML2NameIDMgmt.cpp | 35 +-
shibsp/handler/impl/SAML2SessionInitiator.cpp | 134 +-
shibsp/handler/impl/SAMLDSSessionInitiator.cpp | 20 +-
shibsp/handler/impl/SessionHandler.cpp | 15 +-
shibsp/handler/impl/Shib1SessionInitiator.cpp | 75 +-
shibsp/handler/impl/StatusHandler.cpp | 38 +-
shibsp/handler/impl/TransformSessionInitiator.cpp | 7 +-
shibsp/handler/impl/WAYFSessionInitiator.cpp | 20 +-
shibsp/impl/ChainingAccessControl.cpp | 136 ++
shibsp/impl/StorageServiceSessionCache.cpp | 2 +-
shibsp/impl/XMLAccessControl.cpp | 57 +-
shibsp/impl/XMLRequestMapper.cpp | 81 +-
shibsp/impl/XMLServiceProvider.cpp | 356 ++--
shibsp/lite/CommonDomainCookie.cpp | 28 +-
shibsp/lite/SAMLConstants.cpp | 38 +-
shibsp/lite/SAMLConstants.h | 64 +-
shibsp/metadata/DynamicMetadataProvider.cpp | 15 +-
shibsp/metadata/MetadataExtImpl.cpp | 6 +-
shibsp/metadata/MetadataExtSchemaValidators.cpp | 4 +-
shibsp/metadata/MetadataProviderCriteria.h | 8 +
shibsp/paths.h | 37 +-
shibsp/paths.h.in | 33 +-
shibsp/remoting/ListenerService.h | 53 +-
shibsp/remoting/ddf.h | 9 +-
shibsp/remoting/impl/ListenerService.cpp | 8 +-
shibsp/remoting/impl/SocketListener.cpp | 95 +-
shibsp/remoting/impl/SocketListener.h | 11 +-
shibsp/remoting/impl/TCPListener.cpp | 38 +-
shibsp/remoting/impl/ddf.cpp | 110 +-
shibsp/security/PKIXTrustEngine.cpp | 3 +-
shibsp/security/SecurityPolicy.cpp | 33 +-
shibsp/security/SecurityPolicy.h | 23 +-
shibsp/shibsp-lite.vcproj | 55 +-
shibsp/shibsp.rc | 28 +-
shibsp/shibsp.vcproj | 83 +-
shibsp/util/CGIParser.cpp | 4 +-
shibsp/util/CGIParser.h | 4 +-
shibsp/version.h | 12 +-
util/mdquery.cpp | 37 +-
util/mdquery.vcproj | 87 +-
util/resolvertest.cpp | 98 +-
util/resolvertest.vcproj | 89 +-
174 files changed, 9443 insertions(+), 4534 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 28448cf..96b8823 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
diff --git a/Makefile.in b/Makefile.in
index 7f86166..b296c95 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
- at 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 at doxygen-ps: @DX_DOCDIR@/@PACKAGE at .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)
- at DX_COND_doc_TRUE@all-local: shibboleth.spec pkginfo doxygen-doc
- at 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@
+ at DX_COND_doc_TRUE@all-local: doxygen-doc
+ at 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
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
index 0000000..2408f92
--- /dev/null
+++ b/Portfile.in
@@ -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+)?)"
diff --git a/Shibboleth.sln b/Shibboleth.sln
index 8988b06..1fd1708 100644
--- a/Shibboleth.sln
+++ b/Shibboleth.sln
@@ -1,160 +1,80 @@
-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}
diff --git a/adfs/adfs-lite.vcproj b/adfs/adfs-lite.vcproj
index cbc2a53..5017792 100644
--- a/adfs/adfs-lite.vcproj
+++ b/adfs/adfs-lite.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="adfs-lite"
ProjectGUID="{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83B}"
RootNamespace="adfs-lite"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -66,12 +67,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -93,19 +96,15 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
- WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -121,13 +120,18 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE"
- RuntimeLibrary="2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
UsePrecompiledHeader="0"
+ BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -137,21 +141,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="SHIBSP_LITE"
+ PreprocessorDefinitions="SHIBSP_LITE;_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
+ GenerateDebugInformation="true"
SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -172,18 +177,16 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Debug|x64"
- OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ProjectName)-$(ConfigurationName)"
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)-$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -199,18 +202,13 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE"
+ RuntimeLibrary="2"
UsePrecompiledHeader="0"
- BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -220,20 +218,23 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="SHIBSP_LITE;_DEBUG"
+ PreprocessorDefinitions="SHIBSP_LITE"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="2"
- TargetMachine="17"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -254,9 +255,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -306,7 +304,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
@@ -314,6 +312,8 @@
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -335,9 +335,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp
index 0dd273b..bc84c2f 100644
--- a/adfs/adfs.cpp
+++ b/adfs/adfs.cpp
@@ -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());
diff --git a/adfs/adfs.rc b/adfs/adfs.rc
index 7cd4e1b..7db3d05 100644
--- a/adfs/adfs.rc
+++ b/adfs/adfs.rc
@@ -54,8 +54,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 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -73,13 +73,13 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Internet2\0"
VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"
- VALUE "FileVersion", "2, 1, 0, 0\0"
+ VALUE "FileVersion", "2, 2, 1, 0\0"
#ifdef SHIBSP_LITE
VALUE "InternalName", "adfs-lite\0"
#else
VALUE "InternalName", "adfs\0"
#endif
- VALUE "LegalCopyright", "Copyright � 2008 Internet2\0"
+ VALUE "LegalCopyright", "Copyright � 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
#ifdef SHIBSP_LITE
VALUE "OriginalFilename", "adfs-lite.so\0"
@@ -87,8 +87,8 @@ BEGIN
VALUE "OriginalFilename", "adfs.so\0"
#endif
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
diff --git a/adfs/adfs.vcproj b/adfs/adfs.vcproj
index efb995f..4a4613b 100644
--- a/adfs/adfs.vcproj
+++ b/adfs/adfs.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="adfs"
ProjectGUID="{26D4FABF-ACDE-4947-9C4A-7AE1B50CD83A}"
RootNamespace="adfs"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -66,12 +67,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib saml2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib saml2D.lib xmltooling1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -93,19 +96,15 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
- WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -121,13 +120,18 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
UsePrecompiledHeader="0"
+ BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -137,20 +141,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib saml2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib saml2D.lib xmltooling1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
+ GenerateDebugInformation="true"
SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -171,18 +177,16 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Debug|x64"
- OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -198,18 +202,13 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="2"
UsePrecompiledHeader="0"
- BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -219,20 +218,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib saml2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib saml2.lib xmltooling1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="2"
- TargetMachine="17"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -253,9 +254,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -304,7 +302,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib saml2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib saml2.lib xmltooling1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
@@ -312,6 +310,8 @@
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -333,9 +333,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/apache/mod_apache.cpp b/apache/mod_apache.cpp
index 4fd81e8..661b448 100644
--- a/apache/mod_apache.cpp
+++ b/apache/mod_apache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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"),
diff --git a/apache/mod_shib13.vcproj b/apache/mod_shib13.vcproj
index 5f207f4..e83f9ad 100644
--- a/apache/mod_shib13.vcproj
+++ b/apache/mod_shib13.vcproj
@@ -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
@@ -74,11 +75,13 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache\libexec"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -100,16 +103,13 @@
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"
@@ -130,25 +130,25 @@
/>
<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;"..\..\cpp-xmltooling""
- 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
@@ -156,7 +156,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -164,13 +164,15 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache\libexec"
- GenerateDebugInformation="true"
- TargetMachine="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache\libexec"
+ ProgramDatabaseFile=".\Release/mod_shib_13.pdb"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -191,16 +193,13 @@
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"
@@ -221,25 +220,25 @@
/>
<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;"..\..\cpp-xmltooling""
- 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
@@ -247,7 +246,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -255,13 +254,15 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache\libexec"
- ProgramDatabaseFile=".\Release/mod_shib_13.pdb"
- TargetMachine="17"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache\libexec"
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -282,9 +283,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -346,12 +344,14 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache\libexec"
GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -373,9 +373,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -395,7 +392,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Debug|Win32"
+ Name="Release|x64"
ExcludedFromBuild="true"
>
<Tool
@@ -403,7 +400,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Release|x64"
+ Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
diff --git a/apache/mod_shib20.vcproj b/apache/mod_shib20.vcproj
index 237bd70..91d85c5 100644
--- a/apache/mod_shib20.vcproj
+++ b/apache/mod_shib20.vcproj
@@ -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
@@ -75,11 +76,13 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2\lib"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -101,16 +104,13 @@
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"
@@ -131,26 +131,26 @@
/>
<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;"..\..\cpp-xmltooling""
- 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
@@ -158,7 +158,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -166,13 +166,15 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2\lib"
- GenerateDebugInformation="true"
- TargetMachine="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2\lib"
+ ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -193,16 +195,13 @@
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"
@@ -223,26 +222,26 @@
/>
<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;"..\..\cpp-xmltooling""
- 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
@@ -250,7 +249,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -258,13 +257,15 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2\lib"
- ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
- TargetMachine="17"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2\lib"
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -285,9 +286,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -350,12 +348,14 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";\Apache2\lib"
GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -377,9 +377,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -399,7 +396,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Debug|Win32"
+ Name="Release|x64"
ExcludedFromBuild="true"
>
<Tool
@@ -407,7 +404,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Release|x64"
+ Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
diff --git a/apache/mod_shib22.vcproj b/apache/mod_shib22.vcproj
index 81ed0da..c6e2fd6 100644
--- a/apache/mod_shib22.vcproj
+++ b/apache/mod_shib22.vcproj
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="mod_shib22"
ProjectGUID="{B44C0852-83B8-4FB2-A86E-097C9C8256D0}"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -74,11 +75,13 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
+ AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
OutputFile="$(OutDir)\mod_shib_22.so"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2\lib"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -101,16 +104,13 @@
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\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -131,34 +131,33 @@
/>
<Tool
Name="VCMIDLTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
- TargetEnvironment="1"
- TypeLibraryName=".\mod_shib22___Win32_Debug/mod_shib22.tlb"
+ TargetEnvironment="3"
+ TypeLibraryName=".\mod_shib22___Win32_Release/mod_shib22.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
RuntimeTypeInfo="true"
- BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -166,13 +165,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
+ AdditionalDependencies="xerces-c_3.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
OutputFile="$(OutDir)\mod_shib_22.so"
- LinkIncremental="2"
+ LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2\lib"
- GenerateDebugInformation="true"
- TargetMachine="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"C:\httpd-2.2-x64\lib""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -194,16 +194,13 @@
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\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -224,33 +221,34 @@
/>
<Tool
Name="VCMIDLTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
- TargetEnvironment="3"
- TypeLibraryName=".\mod_shib22___Win32_Release/mod_shib22.tlb"
+ TargetEnvironment="1"
+ TypeLibraryName=".\mod_shib22___Win32_Debug/mod_shib22.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories="..;\Apache2.2\include;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
RuntimeTypeInfo="true"
+ BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -258,12 +256,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling-lite1.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
OutputFile="$(OutDir)\mod_shib_22.so"
- LinkIncremental="1"
+ LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"C:\httpd-2.2-x64\lib""
- TargetMachine="17"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";\Apache2.2\lib"
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -285,9 +286,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -350,12 +348,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling-lite1D.lib libapr-1.lib libaprutil-1.lib libhttpd.lib"
OutputFile="$(OutDir)\mod_shib_22.so"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"C:\httpd-2.2-x64\lib""
GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -378,9 +378,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -400,7 +397,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Debug|Win32"
+ Name="Release|x64"
ExcludedFromBuild="true"
>
<Tool
@@ -408,7 +405,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Release|x64"
+ Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
diff --git a/apache/mod_shib_13.cpp b/apache/mod_shib_13.cpp
index d3c7a00..0497568 100644
--- a/apache/mod_shib_13.cpp
+++ b/apache/mod_shib_13.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
#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
diff --git a/apache/mod_shib_13.rc b/apache/mod_shib_13.rc
index e6939bb..503cf30 100644
--- a/apache/mod_shib_13.rc
+++ b/apache/mod_shib_13.rc
@@ -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
diff --git a/apache/mod_shib_20.cpp b/apache/mod_shib_20.cpp
index 065b24e..c4260c1 100644
--- a/apache/mod_shib_20.cpp
+++ b/apache/mod_shib_20.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
diff --git a/apache/mod_shib_20.rc b/apache/mod_shib_20.rc
index 108338c..d3e619e 100644
--- a/apache/mod_shib_20.rc
+++ b/apache/mod_shib_20.rc
@@ -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
diff --git a/apache/mod_shib_22.cpp b/apache/mod_shib_22.cpp
index 5cab9e4..fbaf17d 100644
--- a/apache/mod_shib_22.cpp
+++ b/apache/mod_shib_22.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
diff --git a/apache/mod_shib_22.rc b/apache/mod_shib_22.rc
index ede13f4..5f92326 100644
--- a/apache/mod_shib_22.rc
+++ b/apache/mod_shib_22.rc
@@ -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
diff --git a/config.h.in b/config.h.in
index 0d29263..e74571c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -107,6 +107,12 @@
/* 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
diff --git a/config_win32.h b/config_win32.h
index 57a9ec7..04b4dd2 100644
--- a/config_win32.h
+++ b/config_win32.h
@@ -40,6 +40,13 @@
/* 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
@@ -110,13 +117,13 @@
#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. */
@@ -129,7 +136,7 @@
/* #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 */
diff --git a/configs/Makefile.am b/configs/Makefile.am
index d745b5d..cd01d03 100644
--- a/configs/Makefile.am
+++ b/configs/Makefile.am
@@ -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 at -@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)
diff --git a/configs/Makefile.in b/configs/Makefile.in
index 6a9a049..40939a8 100644
--- a/configs/Makefile.in
+++ b/configs/Makefile.in
@@ -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 at -@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 ; \
diff --git a/configs/attribute-map.xml b/configs/attribute-map.xml
index 4f7477c..431db53 100644
--- a/configs/attribute-map.xml
+++ b/configs/attribute-map.xml
@@ -25,30 +25,32 @@
<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... -->
diff --git a/configs/keygen.bat b/configs/keygen.bat
index 1af0518..401269c 100644
--- a/configs/keygen.bat
+++ b/configs/keygen.bat
@@ -74,7 +74,7 @@ shift
goto opt_start
:opt_years
-set DAYS=%2
+set YEARS=%2
shift
shift
goto opt_start
diff --git a/configs/metagen.sh b/configs/metagen.sh
new file mode 100755
index 0000000..faf89af
--- /dev/null
+++ b/configs/metagen.sh
@@ -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
index 0000000..4883feb
--- /dev/null
+++ b/configs/postTemplate.html
@@ -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>
diff --git a/configs/shibboleth2.xml b/configs/shibboleth2.xml
index afe286d..d02da4c 100644
--- a/configs/shibboleth2.xml
+++ b/configs/shibboleth2.xml
@@ -16,19 +16,25 @@
<!-- 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"/> -->
@@ -76,10 +82,8 @@
-->
<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.
@@ -104,22 +108,22 @@
<!-- 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>
<!--
@@ -210,7 +214,8 @@
<!--
<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>
-->
@@ -245,14 +250,21 @@
<!-- 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
diff --git a/configs/shibd-debian.in b/configs/shibd-debian.in
index 99ff4d1..13e8240 100644
--- a/configs/shibd-debian.in
+++ b/configs/shibd-debian.in
@@ -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: S 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."
;;
diff --git a/configs/shibd-osx.plist.in b/configs/shibd-osx.plist.in
index 26c90b1..a05cc9d 100644
--- a/configs/shibd-osx.plist.in
+++ b/configs/shibd-osx.plist.in
@@ -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>
diff --git a/configs/shibd-redhat.in b/configs/shibd-redhat.in
index 496f631..02e3426 100644
--- a/configs/shibd-redhat.in
+++ b/configs/shibd-redhat.in
@@ -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
index 0000000..1dceeda
--- /dev/null
+++ b/configs/shibd-suse.in
@@ -0,0 +1,112 @@
+#! /bin/sh
+# Author: Peter Schober <peter.schober at 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
diff --git a/configure b/configure
index e3cf3b9..cd4b0c2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for shibboleth 2.1.
+# Generated by GNU Autoconf 2.59 for shibboleth 2.2.1.
#
# Report bugs to <shibboleth-users at 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 at 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 INS [...]
+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 INS [...]
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
@@ -23754,6 +23757,126 @@ fi
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, at DX_ENV@,$DX_ENV,;t t
s, at DX_FLAG_doc@,$DX_FLAG_doc,;t t
s, at DX_DOXYGEN@,$DX_DOXYGEN,;t t
s, at ac_pt_DX_DOXYGEN@,$ac_pt_DX_DOXYGEN,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_PERL@,$DX_PERL,;t t
s, at ac_pt_DX_PERL@,$ac_pt_DX_PERL,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_doc_TRUE@,$DX_COND_doc_TRUE,;t t
s, at DX_COND_doc_FALSE@,$DX_COND_doc_FALSE,;t t
s, at DX_FLAG_dot@,$DX_FLAG_dot,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_DOT@,$DX_DOT,;t t
s, at ac_pt_DX_DOT@,$ac_pt_DX_DOT,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_dot_TRUE@,$DX_COND_dot_TRUE,;t t
s, at DX_COND_dot_FALSE@,$DX_COND_dot_FALSE,;t t
s, at DX_FLAG_man@,$DX_FLAG_man,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_man_TRUE@,$DX_COND_man_TRUE,;t t
s, at DX_COND_man_FALSE@,$DX_COND_man_FALSE,;t t
s, at DX_FLAG_rtf@,$DX_FLAG_rtf,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_rtf_TRUE@,$DX_COND_rtf_TRUE,;t t
s, at DX_COND_rtf_FALSE@,$DX_COND_rtf_FALSE,;t t
s, at DX_FLAG_xml@,$DX_FLAG_xml,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_xml_TRUE@,$DX_COND_xml_TRUE,;t t
s, at DX_COND_xml_FALSE@,$DX_COND_xml_FALSE,;t t
s, at DX_FLAG_chm@,$DX_FLAG_chm,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_HHC@,$DX_HHC,;t t
s, at ac_pt_DX_HHC@,$ac_pt_DX_HHC,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_chm_TRUE@,$DX_COND_chm_TRUE,;t t
s, at DX_COND_chm_FALSE@,$DX_COND_chm_FALSE,;t t
s, at DX_FLAG_chi@,$DX_FLAG_chi,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_chi_TRUE@,$DX_COND_chi_TRUE,;t t
s, at DX_COND_chi_FALSE@,$DX_COND_chi_FALSE,;t t
s, at DX_FLAG_html@,$DX_FLAG_html,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_html_TRUE@,$DX_COND_html_TRUE,;t t
s, at DX_COND_html_FALSE@,$DX_COND_html_FALSE,;t t
s, at DX_FLAG_ps@,$DX_FLAG_ps,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_LATEX@,$DX_LATEX,;t t
s, at ac_pt_DX_LATEX@,$ac_pt_DX_LATEX,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_MAKEINDEX@,$DX_MAKEINDEX,;t t
s, at ac_pt_DX_MAKEINDEX@,$ac_pt_DX_MAKEINDEX,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_DVIPS@,$DX_DVIPS,;t t
s, at ac_pt_DX_DVIPS@,$ac_pt_DX_DVIPS,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_EGREP@,$DX_EGREP,;t t
s, at ac_pt_DX_EGREP@,$ac_pt_DX_EGREP,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_ps_TRUE@,$DX_COND_ps_TRUE,;t t
s, at DX_COND_ps_FALSE@,$DX_COND_ps_FALSE,;t t
s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_PDFLATEX@,$DX_PDFLATEX,;t t
s, at ac_pt_DX_PDFLATEX@,$ac_pt_DX_PDFLATEX,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
-s, at DX_FLAG_pdf@,$DX_FLAG_pdf,;t t
s, at DX_COND_pdf_TRUE@,$DX_COND_pdf_TRUE,;t t
s, at DX_COND_pdf_FALSE@,$DX_COND_pdf_FALSE,;t t
s, at 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
-
diff --git a/configure.ac b/configure.ac
index effa6af..fd07125 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
AC_PREREQ([2.50])
-AC_INIT([shibboleth], [2.1], [shibboleth-users at internet2.edu], [shibboleth])
+AC_INIT([shibboleth], [2.2.1], [shibboleth-users at 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
--- 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
diff --git a/doc/FASTCGI.LICENSE b/doc/FASTCGI.LICENSE
index 55dde7c..7e6bdfd 100644
--- a/doc/FASTCGI.LICENSE
+++ b/doc/FASTCGI.LICENSE
@@ -1,28 +1,28 @@
-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.
+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.
diff --git a/doc/LOG4CPP.LICENSE b/doc/LOG4CPP.LICENSE
index cbee875..b1e3f5a 100644
--- a/doc/LOG4CPP.LICENSE
+++ b/doc/LOG4CPP.LICENSE
@@ -1,504 +1,504 @@
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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
-
- 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!
-
-
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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
+
+ 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!
+
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 3b312ee..03f93ee 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,6 +1,10 @@
AUTOMAKE_OPTIONS = foreign
-pkgdocdir = $(datadir)/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE at -@PACKAGE_VERSION@
+
+install-data-hook:
+ cp -r api $(DESTDIR)$(pkgdocdir)
+ rm -rf `find $(DESTDIR)$(pkgdocdir)/api -name .svn`
docfiles = \
CREDITS.txt \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 7e4107e..ab75e34 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -257,7 +257,7 @@ sysconfdir = @sysconfdir@
target_alias = @target_alias@
xs = @xs@
AUTOMAKE_OPTIONS = foreign
-pkgdocdir = $(datadir)/doc/@PACKAGE@
+pkgdocdir = $(datadir)/doc/@PACKAGE at -@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:
diff --git a/doc/OPENSSL.LICENSE b/doc/OPENSSL.LICENSE
index cdc9ade..4027788 100644
--- a/doc/OPENSSL.LICENSE
+++ b/doc/OPENSSL.LICENSE
@@ -1,127 +1,127 @@
-
- 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 at 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 at 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 at cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh at cryptsoft.com).
- *
- */
-
- Original SSLeay License
- -----------------------
-
-/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay at 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 at 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 at 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 at 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.]
- */
-
+
+ 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 at 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 at 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 at cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at 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 at 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 at 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 at 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.]
+ */
+
diff --git a/doc/README.txt b/doc/README.txt
index 7b15351..6443108 100644
--- a/doc/README.txt
+++ b/doc/README.txt
@@ -1,5 +1,4 @@
-August 8, 2008
-Version 2.1
+Version 2.2.1
Welcome to Internet2's Shibboleth
diff --git a/doc/RELEASE.txt b/doc/RELEASE.txt
index 3efe64b..66ee2a7 100644
--- a/doc/RELEASE.txt
+++ b/doc/RELEASE.txt
@@ -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 at 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
diff --git a/doc/main.css b/doc/main.css
index a3eb681..a11cebe 100644
--- a/doc/main.css
+++ b/doc/main.css
@@ -1,39 +1,39 @@
-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;
+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
diff --git a/doxygen.m4 b/doxygen.m4
index e4688de..9bda4f6 100644
--- a/doxygen.m4
+++ b/doxygen.m4
@@ -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,
diff --git a/fastcgi/shibauthorizer.cpp b/fastcgi/shibauthorizer.cpp
index 282dad9..59f4417 100644
--- a/fastcgi/shibauthorizer.cpp
+++ b/fastcgi/shibauthorizer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,6 +115,9 @@ public:
return s ? atol(s) : 0;
}
string getRemoteAddr() const {
+ string ret = AbstractSPRequest::getRemoteAddr();
+ if (!ret.empty())
+ return ret;
const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
return s ? s : "";
}
@@ -172,6 +175,23 @@ public:
}
return "";
}
+ void setAuthType(const char* authtype) {
+ if (authtype)
+ m_request_headers["AUTH_TYPE"] = authtype;
+ else
+ m_request_headers.erase("AUTH_TYPE");
+ }
+ string getAuthType() const {
+ map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");
+ if (i != m_request_headers.end())
+ return i->second;
+ else {
+ char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);
+ if (auth_type)
+ return auth_type;
+ }
+ return "";
+ }
void setResponseHeader(const char* name, const char* value) {
// Set for later.
if (value)
diff --git a/fastcgi/shibauthorizer.rc b/fastcgi/shibauthorizer.rc
index 4a2069a..c9b4c1d 100644
--- a/fastcgi/shibauthorizer.rc
+++ b/fastcgi/shibauthorizer.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,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 FastCGI Authorizer\0"
- VALUE "FileVersion", "2, 1, 0, 0\0"
+ VALUE "FileVersion", "2, 2, 1, 0\0"
VALUE "InternalName", "shibauthorizer\0"
- VALUE "LegalCopyright", "Copyright � 2008 Internet2\0"
+ VALUE "LegalCopyright", "Copyright � 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "shibauthorizer.exe\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
diff --git a/fastcgi/shibauthorizer.vcproj b/fastcgi/shibauthorizer.vcproj
index e8f395a..56e1896 100644
--- a/fastcgi/shibauthorizer.vcproj
+++ b/fastcgi/shibauthorizer.vcproj
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="shibauthorizer"
ProjectGUID="{8CF7DDFA-EAA0-416E-853E-3DCB210C4AE0}"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -68,11 +69,13 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"
+ AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)""
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -94,16 +97,13 @@
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="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -124,28 +124,28 @@
/>
<Tool
Name="VCMIDLTool"
- TypeLibraryName=".\shibauthorizer___Win32_Debug/shibauthorizer.tlb"
+ TargetEnvironment="3"
+ TypeLibraryName=".\shibauthorizer___Win32_Release/shibauthorizer.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- BrowseInformation="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
WarningLevel="3"
SuppressStartupBanner="true"
- DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -153,13 +153,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"
- LinkIncremental="2"
+ AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"
+ LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)""
+ ProgramDatabaseFile=".\shibauthorizer___Win32_Release/shibauthorizer.pdb"
SubSystem="1"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -180,16 +182,13 @@
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="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -210,28 +209,28 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
- TypeLibraryName=".\shibauthorizer___Win32_Release/shibauthorizer.tlb"
+ TypeLibraryName=".\shibauthorizer___Win32_Debug/shibauthorizer.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
+ DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -239,13 +238,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"
- LinkIncremental="1"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"
+ LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
- ProgramDatabaseFile=".\shibauthorizer___Win32_Release/shibauthorizer.pdb"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)""
+ GenerateDebugInformation="true"
SubSystem="1"
- TargetMachine="17"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -266,9 +267,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -326,13 +324,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)""
GenerateDebugInformation="true"
- ProgramDatabaseFile=".\shibauthorizer___Win32_Debug/shibauthorizer.pdb"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -354,9 +353,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -381,7 +377,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Debug|Win32"
+ Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
@@ -390,7 +386,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Release|x64"
+ Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
diff --git a/fastcgi/shibresponder.cpp b/fastcgi/shibresponder.cpp
index 3582833..1537e33 100644
--- a/fastcgi/shibresponder.cpp
+++ b/fastcgi/shibresponder.cpp
@@ -120,6 +120,9 @@ public:
return s ? s : "";
}
string getRemoteAddr() const {
+ string ret = AbstractSPRequest::getRemoteAddr();
+ if (!ret.empty())
+ return ret;
const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
return s ? s : "";
}
diff --git a/fastcgi/shibresponder.rc b/fastcgi/shibresponder.rc
index c8bded3..4bccb0f 100644
--- a/fastcgi/shibresponder.rc
+++ b/fastcgi/shibresponder.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,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 FastCGI Responder\0"
- VALUE "FileVersion", "2, 1, 0, 0\0"
+ VALUE "FileVersion", "2, 2, 1, 0\0"
VALUE "InternalName", "shibresponder\0"
- VALUE "LegalCopyright", "Copyright � 2008 Internet2\0"
+ VALUE "LegalCopyright", "Copyright � 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "shibresponder.exe\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
diff --git a/fastcgi/shibresponder.vcproj b/fastcgi/shibresponder.vcproj
index 0d6518f..164fa25 100644
--- a/fastcgi/shibresponder.vcproj
+++ b/fastcgi/shibresponder.vcproj
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="shibresponder"
ProjectGUID="{B2423DCE-048D-4BAA-9AB9-F5D1FCDD3D25}"
+ RootNamespace="shibresponder"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -68,11 +70,13 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"
+ AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)""
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -94,16 +98,13 @@
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="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -124,28 +125,28 @@
/>
<Tool
Name="VCMIDLTool"
- TypeLibraryName=".\shibresponder___Win32_Debug/shibresponder.tlb"
+ TargetEnvironment="3"
+ TypeLibraryName=".\shibresponder___Win32_Release/shibresponder.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- BrowseInformation="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
WarningLevel="3"
SuppressStartupBanner="true"
- DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -153,13 +154,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"
- LinkIncremental="2"
+ AdditionalDependencies="xerces-c_3.lib xmltooling1.lib libfcgi.lib"
+ LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)""
+ ProgramDatabaseFile=".\shibresponder___Win32_Release/shibresponder.pdb"
SubSystem="1"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -180,16 +183,13 @@
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="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
@@ -210,28 +210,28 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
- TypeLibraryName=".\shibresponder___Win32_Release/shibresponder.tlb"
+ TypeLibraryName=".\shibresponder___Win32_Debug/shibresponder.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- StringPooling="true"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
+ DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -239,13 +239,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2.lib xmltooling1.lib libfcgi.lib"
- LinkIncremental="1"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"
+ LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
- ProgramDatabaseFile=".\shibresponder___Win32_Release/shibresponder.pdb"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(ConfigurationName)""
+ GenerateDebugInformation="true"
SubSystem="1"
- TargetMachine="17"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -266,9 +268,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -326,13 +325,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="xerces-c_2D.lib xmltooling1D.lib libfcgi.lib"
+ AdditionalDependencies="xerces-c_3D.lib xmltooling1D.lib libfcgi.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)",\fcgi-2.4.0-VC8\libfcgi\$(ConfigurationName)"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)";"\fcgi-2.4.0-VC9\Win32\$(PlatformName)\$(ConfigurationName)""
GenerateDebugInformation="true"
- ProgramDatabaseFile=".\shibresponder___Win32_Debug/shibresponder.pdb"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -354,9 +354,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -381,7 +378,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Debug|Win32"
+ Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
@@ -390,7 +387,7 @@
/>
</FileConfiguration>
<FileConfiguration
- Name="Release|x64"
+ Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
diff --git a/isapi_shib/isapi_shib.cpp b/isapi_shib/isapi_shib.cpp
index 38ea0c2..148a079 100644
--- a/isapi_shib/isapi_shib.cpp
+++ b/isapi_shib/isapi_shib.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#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 b/isapi_shib/isapi_shib.cpp.mine
similarity index 84%
copy from isapi_shib/isapi_shib.cpp
copy to isapi_shib/isapi_shib.cpp.mine
index 38ea0c2..9d2278e 100644
--- a/isapi_shib/isapi_shib.cpp
+++ b/isapi_shib/isapi_shib.cpp.mine
@@ -1,936 +1,993 @@
-/*
- * Copyright 2001-2007 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 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* getMethod() const {
- if (m_method.empty()) {
- dynabuf var(5);
- GetServerVariable(m_pfc,"REQUEST_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,"CONTENT_TYPE",var,32,false);
- if (!var.empty())
- m_content_type = var;
- }
- return m_content_type;
- }
- long getContentLength() const {
- return 0;
- }
- string getRemoteAddr() const {
- 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.
- const char* getQueryString() const { throw IOException("getQueryString not implemented"); }
- const char* getRequestBody() const { throw IOException("getRequestBody not implemented"); }
-};
-
-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 {
- 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;
- char buf[8192];
- DWORD datalen=m_lpECB->cbTotalBytes;
- while (datalen) {
- DWORD buflen=8192;
- BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
- if (!ret || !buflen)
- throw IOException("Error 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) {
- unsigned int outlen;
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
- m_certs.push_back(reinterpret_cast<char*>(serialized));
- XMLString::release(&serialized);
- }
- }
- }
- return m_certs;
- }
-
- // Not used in the extension.
- void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }
- void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
- void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
-};
-
-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;
-}
+/*
+ * 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);
+}
+
+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 {
+ unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
+ if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
+ ostringstream keystr;
+ keystr << randkey << randkey2 << randkey3 << randkey4;
+ g_spoofKey = keystr.str();
+ }
+ else {
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+ "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
+ g_Config->term();
+ g_Config=NULL;
+ return FALSE;
+ }
+ }
+ }
+
+ props = props->getPropertySet("ISAPI");
+ if (props) {
+ flag = props->getBool("normalizeRequest");
+ g_bNormalizeRequest = !flag.first || flag.second;
+ flag = props->getBool("safeHeaderNames");
+ g_bSafeHeaderNames = flag.first && flag.second;
+ const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
+ while (child) {
+ auto_ptr_char id(child->getAttributeNS(NULL,id));
+ if (id.get())
+ g_Sites.insert(pair<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;
+}
diff --git a/isapi_shib/isapi_shib.cpp b/isapi_shib/isapi_shib.cpp.r3059
similarity index 96%
copy from isapi_shib/isapi_shib.cpp
copy to isapi_shib/isapi_shib.cpp.r3059
index 38ea0c2..73fb7a0 100644
--- a/isapi_shib/isapi_shib.cpp
+++ b/isapi_shib/isapi_shib.cpp.r3059
@@ -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.
@@ -401,10 +401,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 +418,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);
@@ -527,8 +530,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)
@@ -754,6 +757,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);
@@ -796,13 +800,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 +882,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 b/isapi_shib/isapi_shib.cpp.r3097
similarity index 85%
copy from isapi_shib/isapi_shib.cpp
copy to isapi_shib/isapi_shib.cpp.r3097
index 38ea0c2..2a1130d 100644
--- a/isapi_shib/isapi_shib.cpp
+++ b/isapi_shib/isapi_shib.cpp.r3097
@@ -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,45 @@ 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;
+ 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));
@@ -348,10 +383,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 +418,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 +438,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 +455,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 +473,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));
- }
- 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()));
+ 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(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 +588,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 +613,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 +638,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 +815,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 +826,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 +858,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 +940,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.rc b/isapi_shib/isapi_shib.rc
index 26733a8..4a6f709 100644
--- a/isapi_shib/isapi_shib.rc
+++ b/isapi_shib/isapi_shib.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,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
diff --git a/isapi_shib/isapi_shib.vcproj b/isapi_shib/isapi_shib.vcproj
index 3f1bad4..f82279a 100644
--- a/isapi_shib/isapi_shib.vcproj
+++ b/isapi_shib/isapi_shib.vcproj
@@ -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
@@ -76,10 +77,12 @@
<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=""..\..\cpp-xmltooling\$(ConfigurationName)""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -101,16 +104,13 @@
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"
@@ -131,25 +131,26 @@
/>
<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=".;..;"..\..\cpp-xmltooling""
- 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
@@ -157,7 +158,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -166,12 +167,14 @@
<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=""..\..\cpp-xmltooling\$(ConfigurationName)""
- GenerateDebugInformation="true"
- TargetMachine="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
+ ProgramDatabaseFile=".\Release/isapi_shib.pdb"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -192,16 +195,13 @@
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"
@@ -222,26 +222,25 @@
/>
<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=".;..;"..\..\cpp-xmltooling""
- 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
@@ -249,7 +248,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -258,12 +257,14 @@
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
- ProgramDatabaseFile=".\Release/isapi_shib.pdb"
- TargetMachine="17"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)""
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -284,9 +285,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -349,11 +347,13 @@
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -375,9 +375,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/memcache-store/memcache-store.cpp b/memcache-store/memcache-store.cpp
index d1fb373..c208108 100644
--- a/memcache-store/memcache-store.cpp
+++ b/memcache-store/memcache-store.cpp
@@ -26,17 +26,26 @@
# include "config.h"
#endif
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+# define MCEXT_EXPORTS __declspec(dllexport)
+#else
+# define MCEXT_EXPORTS
+#endif
+
+#include <xmltooling/base.h>
+
+#include <iostream>
+#include <libmemcached/memcached.h>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/logging.h>
-
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/StorageService.h>
#include <xmltooling/util/XMLHelper.h>
-#include <libmemcached/memcached.h>
-
using namespace xmltooling::logging;
using namespace xmltooling;
using namespace xercesc;
@@ -100,7 +109,7 @@ namespace xmltooling {
memcached_st *memc;
string m_memcacheHosts;
string m_prefix;
-
+ Mutex* m_lock;
};
class MemcacheStorageService : public StorageService, public MemcacheBase {
@@ -151,15 +160,19 @@ bool MemcacheBase::addLock(string what, bool use_prefix) {
string set_val = "1";
unsigned tries = 5;
while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {
- if (tries-- < 0) {
+ if (tries-- == 0) {
log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
return false;
}
log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());
// sleep 100ms
+#ifdef WIN32
+ Sleep(100);
+#else
struct timeval tv = { 0, 100000 };
- select(0, 0, 0, 0, &tv);
+ select(0, 0, 0, 0, &tv);
+#endif
}
return true;
}
@@ -264,7 +277,6 @@ bool MemcacheBase::deleteMemcache(const char *key,
bool use_prefix) {
memcached_return rv;
string final_key;
- memcached_st clone;
bool success;
if (use_prefix) {
@@ -273,23 +285,25 @@ bool MemcacheBase::deleteMemcache(const char *key,
final_key = key;
}
- if (memcached_clone(&clone, memc) == NULL) {
- throw IOException("MemcacheBase::deleteMemcache(): memcached_clone() failed");
- }
+ m_lock->lock();
+ rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);
+ m_lock->unlock();
- rv = memcached_delete(&clone, (char *)final_key.c_str(), final_key.length(), timeout);
if (rv == MEMCACHED_SUCCESS) {
success = true;
} else if (rv == MEMCACHED_NOTFOUND) {
// Key wasn't there... No biggie.
success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));
+ success = false;
} else {
- log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(&clone, rv));
+ log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv));
// shouldn't be here
success = false;
}
- memcached_free(&clone);
return success;
}
@@ -301,7 +315,6 @@ bool MemcacheBase::getMemcache(const char *key,
size_t len;
char *result;
string final_key;
- memcached_st clone;
bool success;
if (use_prefix) {
@@ -310,11 +323,10 @@ bool MemcacheBase::getMemcache(const char *key,
final_key = key;
}
- if (memcached_clone(&clone, memc) == NULL) {
- throw IOException("MemcacheBase::getMemcache(): memcached_clone() failed");
- }
+ m_lock->lock();
+ result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);
+ m_lock->unlock();
- result = memcached_get(&clone, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);
if (rv == MEMCACHED_SUCCESS) {
dest = result;
free(result);
@@ -322,12 +334,15 @@ bool MemcacheBase::getMemcache(const char *key,
} else if (rv == MEMCACHED_NOTFOUND) {
log.debug("Key %s not found in memcache...", key);
success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));
+ success = false;
} else {
- log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(&clone, rv));
+ log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv));
success = false;
}
- memcached_free(&clone);
return success;
}
@@ -339,7 +354,6 @@ bool MemcacheBase::addMemcache(const char *key,
memcached_return rv;
string final_key;
- memcached_st clone;
bool success;
if (use_prefix) {
@@ -348,23 +362,25 @@ bool MemcacheBase::addMemcache(const char *key,
final_key = key;
}
- if (memcached_clone(&clone, memc) == NULL) {
- throw IOException("MemcacheBase::addMemcache(): memcached_clone() failed");
- }
+ m_lock->lock();
+ rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
- rv = memcached_add(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
if (rv == MEMCACHED_SUCCESS) {
success = true;
} else if (rv == MEMCACHED_NOTSTORED) {
// already there
success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));
+ success = false;
} else {
// shouldn't be here
- log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(&clone, rv));
+ log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv));
success = false;
}
- memcached_free(&clone);
return success;
}
@@ -376,7 +392,6 @@ bool MemcacheBase::setMemcache(const char *key,
memcached_return rv;
string final_key;
- memcached_st clone;
bool success;
if (use_prefix) {
@@ -385,20 +400,22 @@ bool MemcacheBase::setMemcache(const char *key,
final_key = key;
}
- if (memcached_clone(&clone, memc) == NULL) {
- throw IOException("MemcacheBase::setMemcache(): memcached_clone() failed");
- }
+ m_lock->lock();
+ rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
- rv = memcached_set(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
if (rv == MEMCACHED_SUCCESS) {
success = true;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));
+ success = false;
} else {
// shouldn't be here
- log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(&clone, rv));
+ log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv));
success = false;
}
- memcached_free(&clone);
return success;
}
@@ -410,7 +427,6 @@ bool MemcacheBase::replaceMemcache(const char *key,
memcached_return rv;
string final_key;
- memcached_st clone;
bool success;
if (use_prefix) {
@@ -419,23 +435,25 @@ bool MemcacheBase::replaceMemcache(const char *key,
final_key = key;
}
- if (memcached_clone(&clone, memc) == NULL) {
- throw IOException("MemcacheBase::replaceMemcache(): memcached_clone() failed");
- }
+ m_lock->lock();
+ rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+ m_lock->unlock();
- rv = memcached_replace(&clone, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
if (rv == MEMCACHED_SUCCESS) {
success = true;
} else if (rv == MEMCACHED_NOTSTORED) {
// not there
success = false;
+ } else if (rv == MEMCACHED_ERRNO) {
+ // System error
+ log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));
+ success = false;
} else {
// shouldn't be here
- log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(&clone, rv));
+ log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv));
success = false;
}
- memcached_free(&clone);
return success;
}
@@ -456,6 +474,9 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
log.debug("INIT: GOT Hosts: %s", h.get());
m_memcacheHosts = h.get();
+ m_lock = Mutex::create();
+ log.debug("Lock created");
+
memc = memcached_create(NULL);
if (memc == NULL) {
throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
@@ -463,10 +484,23 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
log.debug("Memcache created");
- unsigned int set = MEMCACHED_HASH_CRC;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, set);
+ unsigned int hash = MEMCACHED_HASH_CRC;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);
log.debug("CRC hash set");
+ int32_t timeout = 1000000;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout);
+
+ int32_t poll_timeout = 1000;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);
+
+ int32_t fail_limit = 5;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);
+
+ int32_t retry_timeout = 30;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);
+
memcached_server_st *servers;
servers = memcached_servers_parse((char *)m_memcacheHosts.c_str());
log.debug("Got %u hosts.", memcached_server_list_count(servers));
@@ -480,6 +514,7 @@ MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getIn
MemcacheBase::~MemcacheBase() {
memcached_free(memc);
+ delete m_lock;
log.debug("Base object destroyed");
}
@@ -564,6 +599,19 @@ int MemcacheStorageService::readString(const char* context, const char* key, str
uint32_t rec_version;
string value;
+ if (m_buildMap) {
+ log.debug("Checking context");
+
+ string map_name = context;
+ string ser_arr;
+ uint32_t flags;
+ bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+ if (!ctx_found) {
+ return 0;
+ }
+ }
+
bool found = getMemcache(final_key.c_str(), value, &rec_version);
if (!found) {
return 0;
@@ -645,12 +693,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
}
string map_name = context;
-
- if (! addLock(map_name)) {
- log.error("Unable to get lock for context %s!", context);
- return;
- }
-
string ser_arr;
uint32_t flags;
bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
@@ -681,8 +723,6 @@ void MemcacheStorageService::updateContext(const char* context, time_t expiratio
replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);
}
- deleteLock(map_name);
-
}
void MemcacheStorageService::deleteContext(const char* context) {
@@ -695,12 +735,6 @@ void MemcacheStorageService::deleteContext(const char* context) {
}
string map_name = context;
-
- if (! addLock(map_name)) {
- log.error("Unable to get lock for context %s!", context);
- return;
- }
-
string ser_arr;
uint32_t flags;
bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
@@ -723,16 +757,14 @@ void MemcacheStorageService::deleteContext(const char* context) {
deleteMemcache(map_name.c_str(), 0);
}
- deleteLock(map_name);
-
}
-extern "C" int xmltooling_extension_init(void*) {
+extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {
// Register this SS type
XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);
return 0;
}
-extern "C" void xmltooling_extension_term() {
+extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {
XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");
}
diff --git a/memcache-store/memcache-store.rc b/memcache-store/memcache-store.rc
index ee39660..ffd78ff 100644
--- a/memcache-store/memcache-store.rc
+++ b/memcache-store/memcache-store.rc
@@ -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"
diff --git a/memcache-store/memcache-store.vcproj b/memcache-store/memcache-store.vcproj
index 854aad3..245333c 100644
--- a/memcache-store/memcache-store.vcproj
+++ b/memcache-store/memcache-store.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="memcache-store"
ProjectGUID="{666A63A7-983F-4C19-8411-207F24305198}"
RootNamespace="memcachestore"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -43,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling";..\..\..\libmemcached"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -65,12 +66,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib memcached.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"..\..\..\libmemcached\visualc\$(ConfigurationName)""
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -92,19 +95,15 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
- WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -120,12 +119,17 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="2"
+ Optimization="0"
+ AdditionalIncludeDirectories=""..\..\cpp-xmltooling";..\..\..\libmemcached\visualc\toolset"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -135,20 +139,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
+ GenerateDebugInformation="true"
SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -169,18 +175,16 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Debug|x64"
- OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -196,17 +200,12 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- BrowseInformation="1"
+ AdditionalIncludeDirectories=".;..;"..\..\cpp-xmltooling";..\..\..\libmemcached"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -216,20 +215,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib memcached.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)";"..\..\..\libmemcached\visualc\$(ConfigurationName)""
SubSystem="2"
- TargetMachine="17"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -250,9 +251,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -282,7 +280,7 @@
/>
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
+ AdditionalIncludeDirectories=""..\..\cpp-xmltooling";..\..\..\libmemcached\visualc\toolset"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
WarningLevel="3"
@@ -300,7 +298,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
@@ -308,6 +306,8 @@
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -329,9 +329,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp
index ea38feb..960409d 100644
--- a/nsapi_shib/nsapi_shib.cpp
+++ b/nsapi_shib/nsapi_shib.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/nsapi_shib/nsapi_shib.rc b/nsapi_shib/nsapi_shib.rc
index 6af4d84..ba31800 100644
--- a/nsapi_shib/nsapi_shib.rc
+++ b/nsapi_shib/nsapi_shib.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,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
diff --git a/nsapi_shib/nsapi_shib.vcproj b/nsapi_shib/nsapi_shib.vcproj
index a1c457b..ad271b0 100644
--- a/nsapi_shib/nsapi_shib.vcproj
+++ b/nsapi_shib/nsapi_shib.vcproj
@@ -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
@@ -74,10 +75,12 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -99,16 +102,13 @@
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"
@@ -129,25 +129,25 @@
/>
<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=".;..;"..\..\cpp-xmltooling""
- 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
@@ -155,7 +155,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -163,12 +163,14 @@
/>
<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=""..\..\cpp-xmltooling\$(ConfigurationName)""
- GenerateDebugInformation="true"
- TargetMachine="1"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
+ ProgramDatabaseFile=".\Release/nsapi_shib.pdb"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -189,16 +191,13 @@
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"
@@ -219,25 +218,25 @@
/>
<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=".;..;"..\..\cpp-xmltooling""
- 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
@@ -245,7 +244,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -253,12 +252,14 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
- ProgramDatabaseFile=".\Release/nsapi_shib.pdb"
- TargetMachine="17"
+ AdditionalLibraryDirectories=""..\..\cpp-xmltooling\$(ConfigurationName)""
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -279,9 +280,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -343,11 +341,13 @@
/>
<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=""..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)""
GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -369,9 +369,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/odbc-store/odbc-store.rc b/odbc-store/odbc-store.rc
index ef40f0e..1a9eb39 100644
--- a/odbc-store/odbc-store.rc
+++ b/odbc-store/odbc-store.rc
@@ -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"
diff --git a/odbc-store/odbc-store.vcproj b/odbc-store/odbc-store.vcproj
index 1b6a307..b15cf98 100644
--- a/odbc-store/odbc-store.vcproj
+++ b/odbc-store/odbc-store.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="odbc-store"
ProjectGUID="{666A63A7-983F-4C19-8411-207F24305197}"
RootNamespace="odbcstore"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -65,12 +66,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -92,19 +95,15 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
- WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -120,12 +119,17 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
+ Optimization="0"
AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
- RuntimeLibrary="2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BrowseInformation="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -135,20 +139,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling1D.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
+ GenerateDebugInformation="true"
SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -169,18 +175,16 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
- Name="Debug|x64"
- OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -196,17 +200,12 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories=""..\..\cpp-xmltooling""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- BrowseInformation="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
@@ -216,20 +215,22 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling1D.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
- LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
- GenerateDebugInformation="true"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="2"
- TargetMachine="17"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -250,9 +251,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -300,7 +298,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling1.lib"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling1.lib"
OutputFile="$(OutDir)\$(ProjectName).so"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
@@ -308,6 +306,8 @@
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -329,9 +329,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/pkginfo b/pkginfo
index 67f161a..cd040c3 100644
--- a/pkginfo
+++ b/pkginfo
@@ -1,5 +1,5 @@
PKG=SHIBsp
-VERSION=2.1
+VERSION=2.2.1
BASEDIR=/
NAME=shibboleth-sp
CATEGORY=application,security
diff --git a/pkginfo.in b/pkginfo.in
index 53f2469..9df027f 100644
--- a/pkginfo.in
+++ b/pkginfo.in
@@ -1,5 +1,5 @@
PKG=SHIBsp
-VERSION=@-VERSION-@
+VERSION=@PACKAGE_VERSION@
BASEDIR=/
NAME=shibboleth-sp
CATEGORY=application,security
diff --git a/schemas/shibboleth-2.0-attribute-map.xsd b/schemas/shibboleth-2.0-attribute-map.xsd
index 3a72cda..caf5e1e 100644
--- a/schemas/shibboleth-2.0-attribute-map.xsd
+++ b/schemas/shibboleth-2.0-attribute-map.xsd
@@ -3,7 +3,7 @@
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:am="urn:mace:shibboleth:2.0:attribute-map"
elementFormDefault="qualified"
- version="2.1">
+ version="2.2">
<annotation>
<documentation>
@@ -26,6 +26,14 @@
<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>
@@ -33,8 +41,12 @@
</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>
@@ -73,13 +85,18 @@
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">
@@ -127,6 +144,13 @@
</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>
@@ -147,6 +171,13 @@
</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>
diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd
index f9950db..88befab 100644
--- a/schemas/shibboleth-2.0-native-sp-config.xsd
+++ b/schemas/shibboleth-2.0-native-sp-config.xsd
@@ -8,7 +8,7 @@
elementFormDefault="qualified"
attributeFormDefault="unqualified"
blockDefault="substitution"
- version="2.1">
+ version="2.2">
<import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>
<import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>
@@ -87,6 +87,7 @@
</sequence>
<attribute name="logger" type="anyURI"/>
<attribute name="clockSkew" type="unsignedInt"/>
+ <attribute name="unsafeChars" type="conf:string"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
</element>
@@ -199,9 +200,10 @@
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="logger" type="anyURI"/>
- <attribute name="unsetHeaderValue" type="string"/>
+ <attribute name="unsetHeaderValue" type="conf:string"/>
<attribute name="checkSpoofing" type="boolean"/>
- <attribute name="catchAll" type="boolean"/>
+ <attribute name="spoofKey" type="conf:string"/>
+ <attribute name="catchAll" type="boolean"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
</element>
@@ -224,6 +226,7 @@
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="normalizeRequest" type="boolean"/>
+ <attribute name="safeHeaderNames" type="boolean"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
</element>
@@ -293,6 +296,7 @@
<attribute name="metadataError" type="anyURI"/>
<attribute name="accessError" type="anyURI"/>
<attribute name="sslError" type="anyURI"/>
+ <attribute name="REMOTE_ADDR" type="conf:string"/>
<anyAttribute namespace="##other" processContents="lax"/>
</attributeGroup>
<element name="AccessControlProvider" type="conf:PluggableType"/>
@@ -536,7 +540,7 @@
</complexType>
</element>
</choice>
- <attribute name="handlerURL" type="anyURI"/>
+ <attribute name="handlerURL" type="anyURI" use="required"/>
<attribute name="handlerSSL" type="boolean"/>
<attribute name="exportLocation" type="conf:string"/>
<attribute name="exportACL" type="conf:listOfStrings"/>
@@ -550,6 +554,10 @@
<attribute name="maxTimeSinceAuthn" type="unsignedInt"/>
<attribute name="checkAddress" type="boolean"/>
<attribute name="consistentAddress" type="boolean"/>
+ <attribute name="postData" type="conf:string"/>
+ <attribute name="postLimit" type="positiveInteger"/>
+ <attribute name="postTemplate" type="conf:string"/>
+ <attribute name="postExpire" type="boolean"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
</element>
@@ -586,6 +594,7 @@
<attribute name="forceAuthn" type="boolean"/>
<attribute name="authnContextClassRef" type="anyURI"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
+ <attribute name="requestDelegation" type="boolean"/>
<anyAttribute namespace="##any" processContents="lax"/>
</restriction>
</complexContent>
@@ -678,9 +687,10 @@
<documentation>Specifies a set of SecurityPolicyRule plugins</documentation>
</annotation>
<complexType>
- <sequence>
+ <choice>
<element name="Rule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>
- </sequence>
+ <element name="PolicyRule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>
+ </choice>
<attribute name="id" type="conf:string" use="required"/>
<attribute name="validate" type="boolean"/>
<anyAttribute namespace="##any" processContents="lax"/>
diff --git a/shibboleth.spec b/shibboleth.spec
index 89a86a1..393507a 100644
--- a/shibboleth.spec
+++ b/shibboleth.spec
@@ -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 at osu.edu> - 2.2.1-1
+- Doc handling changes
+- SuSE init script
+
+* Tue Aug 4 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2.1-1
+- Initial version for 2.2.1, with shibd/httpd restart on upgrade
+
+* Thu Jun 25 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-3
+- Add additional cleanup to posttrans fix
+
+* Tue Jun 23 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-2
+- Reverse without_builtinapache macro test
+- Fix init script handling on Red Hat to handle upgrades
+
+* Wed Dec 3 2008 Scott Cantor <cantor.2 at osu.edu> - 2.2-1
+- Bump minor version.
+- Make keygen.sh executable.
+- Fixing SUSE Xerces dependency name.
+- Optionally package shib.conf.
+
* Tue Jun 10 2008 Scott Cantor <cantor.2 at osu.edu> - 2.1-1
- Change shib.conf handling to treat as config file.
diff --git a/shibboleth.spec.in b/shibboleth.spec.in
index 2a9f809..b6f89d8 100644
--- a/shibboleth.spec.in
+++ b/shibboleth.spec.in
@@ -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}- at -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 at osu.edu> - 2.2.1-1
+- Doc handling changes
+- SuSE init script
+
+* Tue Aug 4 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2.1-1
+- Initial version for 2.2.1, with shibd/httpd restart on upgrade
+
+* Thu Jun 25 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-3
+- Add additional cleanup to posttrans fix
+
+* Tue Jun 23 2009 Scott Cantor <cantor.2 at osu.edu> - 2.2-2
+- Reverse without_builtinapache macro test
+- Fix init script handling on Red Hat to handle upgrades
+
+* Wed Dec 3 2008 Scott Cantor <cantor.2 at osu.edu> - 2.2-1
+- Bump minor version.
+- Make keygen.sh executable.
+- Fixing SUSE Xerces dependency name.
+- Optionally package shib.conf.
+
* Tue Jun 10 2008 Scott Cantor <cantor.2 at osu.edu> - 2.1-1
- Change shib.conf handling to treat as config file.
diff --git a/shibd/shibd.cpp b/shibd/shibd.cpp
index b7a6956..4c86dae 100644
--- a/shibd/shibd.cpp
+++ b/shibd/shibd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ const char* shar_schemadir = NULL;
const char* shar_prefix = NULL;
bool shar_checkonly = false;
bool shar_version = false;
-static int unlink_socket = 0;
+static bool unlink_socket = false;
const char* pidfile = NULL;
#ifdef WIN32
@@ -141,14 +141,21 @@ int real_main(int preinit)
//_CrtSetAllocHook(MyAllocHook);
- // Run the listener
if (!shar_checkonly) {
-
// Run the listener.
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {
- fprintf(stderr, "listener failed to enter listen loop\n");
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
+ else if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, "listener failed during service\n");
+ listener->term();
+ conf.term();
return -3;
}
+ listener->term();
}
conf.term();
@@ -158,11 +165,25 @@ int real_main(int preinit)
#else
+int daemon_wait = 3;
+bool shibd_running = false;
+bool daemonize = true;
+
static void term_handler(int arg)
{
shibd_shutdown = true;
}
+static void run_handler(int arg)
+{
+ shibd_running = true;
+}
+
+static void child_handler(int arg)
+{
+ // Terminate the parent's wait/sleep if the newly born daemon dies early.
+}
+
static int setup_signals(void)
{
struct sigaction sa;
@@ -190,6 +211,23 @@ static int setup_signals(void)
if (sigaction(SIGTERM, &sa, NULL) < 0) {
return -1;
}
+
+ if (daemonize) {
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = run_handler;
+
+ if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+ return -1;
+ }
+
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = child_handler;
+
+ if (sigaction(SIGCHLD, &sa, NULL) < 0) {
+ return -1;
+ }
+ }
+
return 0;
}
@@ -199,9 +237,11 @@ static void usage(char* whoami)
fprintf(stderr, " -d\tinstallation prefix to use.\n");
fprintf(stderr, " -c\tconfig file to use.\n");
fprintf(stderr, " -x\tXML schema catalogs to use.\n");
- fprintf(stderr, " -t\tcheck configuration file for problems.\n");
+ fprintf(stderr, " -t\ttest configuration file for problems.\n");
fprintf(stderr, " -f\tforce removal of listener socket.\n");
+ fprintf(stderr, " -F\tstay in the foreground.\n");
fprintf(stderr, " -p\tpid file to use.\n");
+ fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");
fprintf(stderr, " -v\tprint software version.\n");
fprintf(stderr, " -h\tprint this help message.\n");
exit(1);
@@ -211,7 +251,7 @@ static int parse_args(int argc, char* argv[])
{
int opt;
- while ((opt = getopt(argc, argv, "d:c:x:p:ftvh")) > 0) {
+ while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {
switch (opt) {
case 'd':
shar_prefix=optarg;
@@ -223,10 +263,14 @@ static int parse_args(int argc, char* argv[])
shar_schemadir=optarg;
break;
case 'f':
- unlink_socket = 1;
+ unlink_socket = true;
+ break;
+ case 'F':
+ daemonize = false;
break;
case 't':
shar_checkonly=true;
+ daemonize=false;
break;
case 'v':
shar_version=true;
@@ -234,6 +278,12 @@ static int parse_args(int argc, char* argv[])
case 'p':
pidfile=optarg;
break;
+ case 'w':
+ if (optarg)
+ daemon_wait = atoi(optarg);
+ if (daemon_wait <= 0)
+ daemon_wait = 3;
+ break;
default:
return -1;
}
@@ -271,6 +321,21 @@ int main(int argc, char *argv[])
return -1;
}
+ if (daemonize) {
+ // We must fork() early, while we're single threaded.
+ // StorageService cleanup thread is about to start.
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ perror("forking");
+ exit(EXIT_FAILURE);
+ default:
+ sleep(daemon_wait);
+ exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+ }
+
if (!conf.instantiate(shar_config)) {
fprintf(stderr, "configuration is invalid, check console for specific problems\n");
conf.term();
@@ -280,23 +345,53 @@ int main(int argc, char *argv[])
if (shar_checkonly)
fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
else {
+ // Init the listener.
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
- // Write the pid file
- if (pidfile) {
- FILE* pidf = fopen(pidfile, "w");
- if (pidf) {
- fprintf(pidf, "%d\n", getpid());
- fclose(pidf);
- } else {
- perror(pidfile); // keep running though
+ if (daemonize) {
+ if (setsid() == -1) {
+ perror("setsid");
+ exit(EXIT_FAILURE);
}
+ if (chdir("/") == -1) {
+ perror("chdir to root");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pidfile) {
+ FILE* pidf = fopen(pidfile, "w");
+ if (pidf) {
+ fprintf(pidf, "%d\n", getpid());
+ fclose(pidf);
+ }
+ else {
+ perror(pidfile);
+ }
+ }
+
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+
+ // Signal our parent that we are A-OK.
+ kill(getppid(), SIGUSR1);
}
- // Run the listener
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {
- fprintf(stderr, "listener failed to enter listen loop\n");
+ // Run the listener.
+ if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, "listener failure during service\n");
+ listener->term();
+ conf.term();
+ if (pidfile)
+ unlink(pidfile);
return -3;
}
+ listener->term();
}
conf.term();
diff --git a/shibd/shibd.rc b/shibd/shibd.rc
index 6f21f45..4f11667 100644
--- a/shibd/shibd.rc
+++ b/shibd/shibd.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,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 Daemon Service\0"
- VALUE "FileVersion", "2, 1, 0, 0\0"
+ VALUE "FileVersion", "2, 2, 1, 0\0"
VALUE "InternalName", "shibd\0"
- VALUE "LegalCopyright", "Copyright � 2008 Internet2\0"
+ VALUE "LegalCopyright", "Copyright � 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "shibd.exe\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
diff --git a/shibd/shibd.vcproj b/shibd/shibd.vcproj
index f86cfad..c921764 100644
--- a/shibd/shibd.vcproj
+++ b/shibd/shibd.vcproj
@@ -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
@@ -70,11 +71,13 @@
/>
<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
@@ -96,16 +99,13 @@
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"
@@ -125,21 +125,22 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -147,7 +148,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -155,13 +156,14 @@
/>
<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"
@@ -182,16 +184,13 @@
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"
@@ -211,22 +210,21 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -234,7 +232,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -242,12 +240,15 @@
/>
<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"
@@ -268,9 +269,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -334,6 +332,8 @@
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -355,9 +355,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp
index ff5c98c..c18d826 100644
--- a/shibsp/AbstractSPRequest.cpp
+++ b/shibsp/AbstractSPRequest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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())
);
diff --git a/shibsp/AbstractSPRequest.h b/shibsp/AbstractSPRequest.h
index 6faf9ee..1253256 100644
--- a/shibsp/AbstractSPRequest.h
+++ b/shibsp/AbstractSPRequest.h
@@ -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;
diff --git a/shibsp/AccessControl.h b/shibsp/AccessControl.h
index 77774b6..59178aa 100644
--- a/shibsp/AccessControl.h
+++ b/shibsp/AccessControl.h
@@ -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__ */
diff --git a/shibsp/Application.cpp b/shibsp/Application.cpp
index 8e41cab..6ee7919 100644
--- a/shibsp/Application.cpp
+++ b/shibsp/Application.cpp
@@ -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)) {
diff --git a/shibsp/Application.h b/shibsp/Application.h
index c7352a2..cfd38e7 100644
--- a/shibsp/Application.h
+++ b/shibsp/Application.h
@@ -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;
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index 703da9d..811d4ed 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -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' \
diff --git a/shibsp/Makefile.in b/shibsp/Makefile.in
index 7a04a6c..43015a5 100644
--- a/shibsp/Makefile.in
+++ b/shibsp/Makefile.in
@@ -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 at ./$(DEPDIR)/AuthenticationMethodRegexFunctor.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/AuthenticationMethodStringFunctor.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/CGIParser.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingAccessControl.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingAttributeExtractor.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingAttributeFilter.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingAttributeResolver.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingLogoutInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ChainingSessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/CookieSessionInitiator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DOMAttributeDecoder.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DOMPropertySet.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DelegationAttributeExtractor.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DynamicMetadataProvider.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ExtensibleAttribute.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/FormSessionInitiator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/KeyDescriptorAttributeExtractor.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/KeyInfoAttributeDecoder.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ListenerService.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/LocalLogoutInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/LogoutHandler.Plo at am__quote@
@@ -712,6 +737,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SessionHandler.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Shib1SessionInitiator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SimpleAggregationAttributeResolver.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SocketListener.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/StatusHandler.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/StorageServiceSessionCache.Plo at am__quote@
@@ -722,6 +748,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/UnixListener.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/WAYFSessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/XMLAccessControl.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/XMLAttributeDecoder.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/XMLAttributeExtractor.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/XMLAttributeFilter.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/XMLRequestMapper.Plo at am__quote@
@@ -734,11 +761,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-AssertionLookup.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-Attribute.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-CGIParser.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-ChainingAccessControl.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-ChainingLogoutInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-ChainingSessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-CommonDomainCookie.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-CookieSessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-DOMPropertySet.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-ExtensibleAttribute.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-FormSessionInitiator.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-ListenerService.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libshibsp_lite_la-LocalLogoutInitiator.Plo at 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
+ at 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; \
+ at 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
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/ExtensibleAttribute.cpp' object='libshibsp_lite_la-ExtensibleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at 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
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='impl/ChainingAccessControl.cpp' object='libshibsp_lite_la-ChainingAccessControl.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/ExtensibleAttribute.Tpo" "$(DEPDIR)/ExtensibleAttribute.Plo"; else rm -f "$(DEPDIR)/ExtensibleAttribute.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/ExtensibleAttribute.cpp' object='ExtensibleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/ChainingAccessControl.Tpo" "$(DEPDIR)/ChainingAccessControl.Plo"; else rm -f "$(DEPDIR)/ChainingAccessControl.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='impl/ChainingAccessControl.cpp' object='ChainingAccessControl.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/DOMAttributeDecoder.Tpo" "$(DEPDIR)/DOMAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/DOMAttributeDecoder.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/DOMAttributeDecoder.cpp' object='DOMAttributeDecoder.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/KeyInfoAttributeDecoder.Tpo" "$(DEPDIR)/KeyInfoAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/KeyInfoAttributeDecoder.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/KeyInfoAttributeDecoder.cpp' object='KeyInfoAttributeDecoder.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/XMLAttributeDecoder.Tpo" "$(DEPDIR)/XMLAttributeDecoder.Plo"; else rm -f "$(DEPDIR)/XMLAttributeDecoder.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/XMLAttributeDecoder.cpp' object='XMLAttributeDecoder.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/SimpleAggregationAttributeResolver.Tpo" "$(DEPDIR)/SimpleAggregationAttributeResolver.Plo"; else rm -f "$(DEPDIR)/SimpleAggregationAttributeResolver.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp' object='SimpleAggregationAttributeResolver.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/DelegationAttributeExtractor.Tpo" "$(DEPDIR)/DelegationAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/DelegationAttributeExtractor.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/resolver/impl/DelegationAttributeExtractor.cpp' object='DelegationAttributeExtractor.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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
+ at 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; \
+ at am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/KeyDescriptorAttributeExtractor.Tpo" "$(DEPDIR)/KeyDescriptorAttributeExtractor.Plo"; else rm -f "$(DEPDIR)/KeyDescriptorAttributeExtractor.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp' object='KeyDescriptorAttributeExtractor.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at 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' \
diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp
index 7aaaf98..cbc9f8c 100644
--- a/shibsp/SPConfig.cpp
+++ b/shibsp/SPConfig.cpp
@@ -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();
diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h
index d58c3a4..99f1a22 100644
--- a/shibsp/SPConfig.h
+++ b/shibsp/SPConfig.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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)
diff --git a/shibsp/SPRequest.h b/shibsp/SPRequest.h
index cf2b7ed..255e8b5 100644
--- a/shibsp/SPRequest.h
+++ b/shibsp/SPRequest.h
@@ -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__
@@ -28,18 +28,18 @@
#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;
};
};
diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp
index 91a8ab9..0006dbc 100644
--- a/shibsp/ServiceProvider.cpp
+++ b/shibsp/ServiceProvider.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/shibsp/attribute/Attribute.cpp b/shibsp/attribute/Attribute.cpp
index d4301e4..36c32bc 100644
--- a/shibsp/attribute/Attribute.cpp
+++ b/shibsp/attribute/Attribute.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,8 +28,11 @@
#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;
+ if (m_serialized.empty()) {
+ for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+ XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
+ if (enc) {
+ for (pos=enc, pos2=enc; *pos2; pos2++)
+ if (isgraph(*pos2))
+ *pos++=*pos2;
+ *pos=0;
+ m_serialized.push_back(reinterpret_cast<char*>(enc));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&enc);
+#else
+ XMLString::release((char**)&enc);
+#endif
+ }
+ }
+ }
+ return Attribute::getSerializedValues();
+}
diff --git a/shibsp/attribute/Attribute.h b/shibsp/attribute/Attribute.h
index 1219681..37e1d39 100644
--- a/shibsp/attribute/Attribute.h
+++ b/shibsp/attribute/Attribute.h
@@ -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__ */
diff --git a/shibsp/attribute/AttributeDecoder.h b/shibsp/attribute/AttributeDecoder.h
index 7063ceb..5b0ad48 100644
--- a/shibsp/attribute/AttributeDecoder.h
+++ b/shibsp/attribute/AttributeDecoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
index 0000000..98cb87c
--- /dev/null
+++ b/shibsp/attribute/DOMAttributeDecoder.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * DOMAttributeDecoder.cpp
+ *
+ * Decodes a DOM into an ExtensibleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/ExtensibleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ DOMAttributeDecoder(const DOMElement* e);
+ ~DOMAttributeDecoder() {}
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ DDF convert(DOMElement* e, bool nameit=true) const;
+ auto_ptr_char m_formatter;
+ map<pair<xstring,xstring>,string> m_tagMap;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new DOMAttributeDecoder(e);
+ }
+
+ static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+ static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m);
+ static const XMLCh _to[] = UNICODE_LITERAL_2(t,o);
+ static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)
+ : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+ e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;
+ while (e) {
+ if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {
+ auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));
+ auto_ptr_char t(e->getAttributeNS(NULL, _to));
+ if (f.get() && t.get() && *t.get()) {
+ if (log.isDebugEnabled())
+ log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());
+ m_tagMap.insert(
+ pair< const pair<xstring,xstring>,string>(
+ pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),
+ t.get()
+ )
+ );
+ }
+ }
+ e = XMLHelper::getNextSiblingElement(e, Mapping);
+ }
+}
+
+Attribute* DOMAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+ return NULL;
+ }
+
+ auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));
+ DDF dest = attr->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ DOMElement* e = (*v)->getDOM();
+ if (e) {
+ DDF converted = convert(e, false);
+ if (!converted.isnull())
+ dest.add(converted);
+ }
+ else
+ log.warn("skipping AttributeValue without a backing DOM");
+ }
+
+ return dest.integer() ? _decode(attr.release()) : NULL;
+}
+
+DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const
+{
+ const XMLCh* nsURI;
+ const XMLCh* local;
+ map<pair<xstring,xstring>,string>::const_iterator mapping;
+ DDF obj = DDF(NULL).structure();
+
+ if (nameit) {
+ // Name this structure.
+ nsURI = e->getNamespaceURI();
+ local = e->getLocalName();
+ mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));
+ if (mapping == m_tagMap.end()) {
+ auto_ptr_char temp(local);
+ obj.name(temp.get());
+ }
+ else {
+ obj.name(mapping->second.c_str());
+ }
+ }
+
+ // Process non-xmlns attributes.
+ DOMNamedNodeMap* attrs = e->getAttributes();
+ for (XMLSize_t a = attrs->getLength(); a > 0; --a) {
+ DOMNode* attr = attrs->item(a-1);
+ nsURI = attr->getNamespaceURI();
+ if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))
+ continue;
+ local = attr->getLocalName();
+ mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));
+ if (mapping == m_tagMap.end()) {
+ auto_ptr_char temp(local);
+ obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);
+ }
+ else {
+ obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);
+ }
+ }
+
+ DOMElement* child = XMLHelper::getFirstChildElement(e);
+ if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {
+ // Attach a _text member if a text node is present.
+ obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);
+ }
+ else {
+ while (child) {
+ // Convert the child element.
+ DDF converted = convert(child);
+ if (!converted.isnull()) {
+ // Now identify it and attach it.
+ if (obj[converted.name()].isnull()) {
+ // We're a new child, so just attach as a structure member.
+ obj.add(converted);
+ }
+ else if (obj[converted.name()].islist()) {
+ // We're already a repeating child, so add it to the list.
+ obj[converted.name()].add(converted);
+ }
+ else if (obj[converted.name()].isstruct()) {
+ // This is the complex case where we see a child for the second
+ // time and have to convert a structure member into a named list.
+ DDF newlist = DDF(converted.name()).list();
+ newlist.add(obj[converted.name()].remove());
+ newlist.add(converted);
+ obj.add(newlist);
+ }
+ }
+ child = XMLHelper::getNextSiblingElement(child);
+ }
+ }
+
+ // If we're empty, just delete.
+ if (obj.integer() == 0)
+ obj.destroy();
+ return obj;
+}
diff --git a/shibsp/attribute/ExtensibleAttribute.cpp b/shibsp/attribute/ExtensibleAttribute.cpp
new file mode 100644
index 0000000..5602c55
--- /dev/null
+++ b/shibsp/attribute/ExtensibleAttribute.cpp
@@ -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
index 0000000..8a12836
--- /dev/null
+++ b/shibsp/attribute/ExtensibleAttribute.h
@@ -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
index 0000000..3ab80f2
--- /dev/null
+++ b/shibsp/attribute/KeyInfoAttributeDecoder.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * KeyInfoAttributeDecoder.cpp
+ *
+ * Decodes KeyInfo information into a SimpleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/signature/KeyInfo.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ KeyInfoAttributeDecoder(const DOMElement* e);
+ ~KeyInfoAttributeDecoder() {
+ delete m_keyInfoResolver;
+ }
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ void extract(const KeyInfo* k, vector<string>& dest) const {
+ auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+ if (cred.get()) {
+ dest.push_back(string());
+ dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash);
+ if (dest.back().empty())
+ dest.pop_back();
+ }
+ }
+
+ const KeyInfoResolver* getKeyInfoResolver() const {
+ return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+ }
+
+ bool m_hash;
+ KeyInfoResolver* m_keyInfoResolver;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new KeyInfoAttributeDecoder(e);
+ }
+
+ static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);
+ static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+};
+
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {
+ const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;
+ m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+ e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;
+ if (e) {
+ auto_ptr_char t(e->getAttributeNS(NULL, _type));
+ if (t.get() && *t.get())
+ m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);
+ else
+ throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
+ }
+}
+
+Attribute* KeyInfoAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");
+
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+ return NULL;
+ }
+
+ auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));
+ vector<string>& dest = attr->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);
+ if (k)
+ extract(k, dest);
+ else if ((*v)->hasChildren()) {
+ const list<XMLObject*>& children = (*v)->getOrderedChildren();
+ for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+ if (k=dynamic_cast<const KeyInfo*>(*vv))
+ extract(k, dest);
+ else
+ log.warn("skipping AttributeValue without a recognizable KeyInfo");
+ }
+ }
+ }
+
+ return dest.empty() ? NULL : _decode(attr.release());
+}
diff --git a/shibsp/attribute/NameIDAttribute.h b/shibsp/attribute/NameIDAttribute.h
index bd292ce..1b8d247 100644
--- a/shibsp/attribute/NameIDAttribute.h
+++ b/shibsp/attribute/NameIDAttribute.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
/**
* @file shibsp/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();
}
diff --git a/shibsp/attribute/NameIDAttributeDecoder.cpp b/shibsp/attribute/NameIDAttributeDecoder.cpp
index 440fa57..903bc33 100644
--- a/shibsp/attribute/NameIDAttributeDecoder.cpp
+++ b/shibsp/attribute/NameIDAttributeDecoder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,12 +34,18 @@ using namespace xmltooling;
using namespace std;
namespace shibsp {
- static XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+ static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+ static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);
class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder
{
public:
- NameIDAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {}
+ NameIDAttributeDecoder(const DOMElement* e)
+ : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {
+ const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;
+ if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+ m_defaultQualifiers = true;
+ }
~NameIDAttributeDecoder() {}
shibsp::Attribute* decode(
@@ -54,6 +60,7 @@ namespace shibsp {
const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
) const;
auto_ptr_char m_formatter;
+ bool m_defaultQualifiers;
};
AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)
@@ -69,7 +76,6 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
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;
@@ -131,7 +137,7 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
}
}
- return dest.empty() ? NULL : nameid.release();
+ return dest.empty() ? NULL : _decode(nameid.release());
}
const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);
@@ -160,7 +166,7 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
}
}
- return dest.empty() ? NULL : nameid.release();
+ return dest.empty() ? NULL : _decode(nameid.release());
}
void NameIDAttributeDecoder::extract(
@@ -181,14 +187,14 @@ void NameIDAttributeDecoder::extract(
str = toUTF8(n->getNameQualifier());
if (str && *str)
val.m_NameQualifier = str;
- else if (assertingParty)
+ else if (m_defaultQualifiers && assertingParty)
val.m_NameQualifier = assertingParty;
delete[] str;
str = toUTF8(n->getSPNameQualifier());
if (str && *str)
val.m_SPNameQualifier = str;
- else if (relyingParty)
+ else if (m_defaultQualifiers && relyingParty)
val.m_SPNameQualifier = relyingParty;
delete[] str;
@@ -218,11 +224,11 @@ void NameIDAttributeDecoder::extract(
str = toUTF8(n->getNameQualifier());
if (str && *str)
val.m_NameQualifier = str;
- else if (assertingParty)
+ else if (m_defaultQualifiers && assertingParty)
val.m_NameQualifier = assertingParty;
delete[] str;
- if (relyingParty)
+ if (m_defaultQualifiers && relyingParty)
val.m_SPNameQualifier = relyingParty;
}
}
diff --git a/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp b/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp
index 7e807b9..ab72dfb 100644
--- a/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp
+++ b/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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");
diff --git a/shibsp/attribute/ScopedAttribute.h b/shibsp/attribute/ScopedAttribute.h
index d72cd0c..a8acac5 100644
--- a/shibsp/attribute/ScopedAttribute.h
+++ b/shibsp/attribute/ScopedAttribute.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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();
}
diff --git a/shibsp/attribute/ScopedAttributeDecoder.cpp b/shibsp/attribute/ScopedAttributeDecoder.cpp
index 2044d6b..c3054c8 100644
--- a/shibsp/attribute/ScopedAttributeDecoder.cpp
+++ b/shibsp/attribute/ScopedAttributeDecoder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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());
}
diff --git a/shibsp/attribute/StringAttributeDecoder.cpp b/shibsp/attribute/StringAttributeDecoder.cpp
index ca86390..f2a9d6f 100644
--- a/shibsp/attribute/StringAttributeDecoder.cpp
+++ b/shibsp/attribute/StringAttributeDecoder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,7 +57,6 @@ shibsp::Attribute* StringAttributeDecoder::decode(
{
char* val;
auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
- simple->setCaseSensitive(m_caseSensitive);
vector<string>& dest = simple->getValues();
vector<XMLObject*>::const_iterator v,stop;
@@ -111,7 +110,7 @@ shibsp::Attribute* StringAttributeDecoder::decode(
}
}
- return dest.empty() ? NULL : simple.release();
+ return dest.empty() ? NULL : _decode(simple.release());
}
const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
@@ -145,5 +144,5 @@ shibsp::Attribute* StringAttributeDecoder::decode(
else
log.warn("ignoring empty NameID");
delete[] val;
- return dest.empty() ? NULL : simple.release();
+ return dest.empty() ? NULL : _decode(simple.release());
}
diff --git a/shibsp/attribute/XMLAttribute.h b/shibsp/attribute/XMLAttribute.h
new file mode 100644
index 0000000..3c9a4f6
--- /dev/null
+++ b/shibsp/attribute/XMLAttribute.h
@@ -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
index 0000000..2d59528
--- /dev/null
+++ b/shibsp/attribute/XMLAttributeDecoder.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * XMLAttributeDecoder.cpp
+ *
+ * Decodes arbitrary XML into an XMLAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/XMLAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+ ~XMLAttributeDecoder() {}
+
+ Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+ ) const;
+
+ private:
+ DDF convert(DOMElement* e, bool nameit=true) const;
+ auto_ptr_char m_formatter;
+ map<pair<xstring,xstring>,string> m_tagMap;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new XMLAttributeDecoder(e);
+ }
+};
+
+
+Attribute* XMLAttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ if (!xmlObject)
+ return NULL;
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");
+
+ auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));
+ vector<string>& dest = attr->getValues();
+
+ // Handle any non-Attribute object directly.
+ if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+ DOMElement* e = xmlObject->getDOM();
+ if (e) {
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "decoding XMLAttribute (%s) from XMLObject (%s)",
+ ids.front().c_str(),
+ (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()
+ );
+ }
+ dest.push_back(string());
+ XMLHelper::serialize(e, dest.back());
+ }
+ else {
+ log.warn("skipping XMLObject without a backing DOM");
+ }
+ return dest.empty() ? NULL : _decode(attr.release());
+ }
+
+ vector<XMLObject*>::const_iterator v,stop;
+
+ const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");
+ return NULL;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ DOMElement* e = (*v)->getDOM();
+ if (e) {
+ dest.push_back(string());
+ XMLHelper::serialize(e, dest.back());
+ }
+ else
+ log.warn("skipping AttributeValue without a backing DOM");
+ }
+
+ return dest.empty() ? NULL : _decode(attr.release());
+}
diff --git a/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
index 857050d..35cea2c 100644
--- a/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
+++ b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
@@ -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.");
diff --git a/shibsp/attribute/filtering/impl/MatchFunctor.cpp b/shibsp/attribute/filtering/impl/MatchFunctor.cpp
index 06fd7b2..1ba0ec6 100644
--- a/shibsp/attribute/filtering/impl/MatchFunctor.cpp
+++ b/shibsp/attribute/filtering/impl/MatchFunctor.cpp
@@ -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);
diff --git a/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
index 0f79a84..9a22474 100644
--- a/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
+++ b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
@@ -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.");
diff --git a/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
index cd29548..2649f42 100644
--- a/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
+++ b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
@@ -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.");
diff --git a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
index b01cf1f..32fab83 100644
--- a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
+++ b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
@@ -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;
}
}
diff --git a/shibsp/attribute/resolver/AttributeExtractor.h b/shibsp/attribute/resolver/AttributeExtractor.h
index a0b0a14..63644ca 100644
--- a/shibsp/attribute/resolver/AttributeExtractor.h
+++ b/shibsp/attribute/resolver/AttributeExtractor.h
@@ -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"
};
diff --git a/shibsp/attribute/resolver/AttributeResolver.h b/shibsp/attribute/resolver/AttributeResolver.h
index 73adab1..524dde8 100644
--- a/shibsp/attribute/resolver/AttributeResolver.h
+++ b/shibsp/attribute/resolver/AttributeResolver.h
@@ -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"
};
diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
index de77496..523cdc3 100644
--- a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
+++ b/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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);
}
diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
index 90e3776..d0b63f1 100644
--- a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
+++ b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
index 0000000..d44311e
--- /dev/null
+++ b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
@@ -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()));
+ if (name.get() && *name.get()) {
+ val.addmember("Name").string(name.get());
+ char* str = toUTF8(n->getFormat());
+ if (str && *str)
+ val.addmember("Format").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getNameQualifier());
+ if (str && *str)
+ val.addmember("NameQualifier").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getSPNameQualifier());
+ if (str && *str)
+ val.addmember("SPNameQualifier").string(str);
+ delete[] str;
+
+ str = toUTF8(n->getSPProvidedID());
+ if (str && *str)
+ val.addmember("SPProvidedID").string(str);
+ delete[] str;
+ }
+
+ if (n != (*d)->getNameID())
+ delete n;
+
+ 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
index 0000000..d730b35
--- /dev/null
+++ b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
@@ -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());
+ }
+ }
+}
diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
index e6e231e..ceff508 100644
--- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
+++ b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,12 +39,10 @@
#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
index 0000000..abd1cad
--- /dev/null
+++ b/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
@@ -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());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
index eeead9f..c27df80 100644
--- a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
+++ b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,12 +24,17 @@
#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.");
diff --git a/shibsp/base.h b/shibsp/base.h
index 9eb4cf3..7e7def0 100644
--- a/shibsp/base.h
+++ b/shibsp/base.h
@@ -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
*/
@@ -68,14 +68,10 @@
#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"
/**
@@ -84,23 +80,32 @@
*/
#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__ */
diff --git a/shibsp/binding/SOAPClient.h b/shibsp/binding/SOAPClient.h
index 573f3f1..eedebc0 100644
--- a/shibsp/binding/SOAPClient.h
+++ b/shibsp/binding/SOAPClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/shibsp/binding/impl/ArtifactResolver.cpp b/shibsp/binding/impl/ArtifactResolver.cpp
index 332549f..52e68fc 100644
--- a/shibsp/binding/impl/ArtifactResolver.cpp
+++ b/shibsp/binding/impl/ArtifactResolver.cpp
@@ -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).");
diff --git a/shibsp/binding/impl/SOAPClient.cpp b/shibsp/binding/impl/SOAPClient.cpp
index ad3d3cb..cc5c6dc 100644
--- a/shibsp/binding/impl/SOAPClient.cpp
+++ b/shibsp/binding/impl/SOAPClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,12 +38,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);
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index 140fa11..20a480b 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
#define __shibsp_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)
diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h
index a7289fe..752e86c 100644
--- a/shibsp/handler/AssertionConsumerService.h
+++ b/shibsp/handler/AssertionConsumerService.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index cd9039c..e42ef5b 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,16 @@
#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();
}
diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp
index 8f3b008..52f747b 100644
--- a/shibsp/handler/impl/AssertionConsumerService.cpp
+++ b/shibsp/handler/impl/AssertionConsumerService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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());
diff --git a/shibsp/handler/impl/AssertionLookup.cpp b/shibsp/handler/impl/AssertionLookup.cpp
index 990d7d7..adeb711 100644
--- a/shibsp/handler/impl/AssertionLookup.cpp
+++ b/shibsp/handler/impl/AssertionLookup.cpp
@@ -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.
diff --git a/shibsp/handler/impl/ChainingLogoutInitiator.cpp b/shibsp/handler/impl/ChainingLogoutInitiator.cpp
index e8de4d6..4fc6776 100644
--- a/shibsp/handler/impl/ChainingLogoutInitiator.cpp
+++ b/shibsp/handler/impl/ChainingLogoutInitiator.cpp
@@ -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;
diff --git a/shibsp/handler/impl/ChainingSessionInitiator.cpp b/shibsp/handler/impl/ChainingSessionInitiator.cpp
index dcd29d6..1cbc45b 100644
--- a/shibsp/handler/impl/ChainingSessionInitiator.cpp
+++ b/shibsp/handler/impl/ChainingSessionInitiator.cpp
@@ -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;
diff --git a/shibsp/handler/impl/LogoutHandler.cpp b/shibsp/handler/impl/LogoutHandler.cpp
index 161dcc3..dfa43ed 100644
--- a/shibsp/handler/impl/LogoutHandler.cpp
+++ b/shibsp/handler/impl/LogoutHandler.cpp
@@ -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);
diff --git a/shibsp/handler/impl/MetadataGenerator.cpp b/shibsp/handler/impl/MetadataGenerator.cpp
index 08e73e0..2a847cb 100644
--- a/shibsp/handler/impl/MetadataGenerator.cpp
+++ b/shibsp/handler/impl/MetadataGenerator.cpp
@@ -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)
diff --git a/shibsp/handler/impl/RemotedHandler.cpp b/shibsp/handler/impl/RemotedHandler.cpp
index b8580e2..2ee35a1 100644
--- a/shibsp/handler/impl/RemotedHandler.cpp
+++ b/shibsp/handler/impl/RemotedHandler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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) {
diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp
index d1c46b8..239d7d2 100644
--- a/shibsp/handler/impl/SAML1Consumer.cpp
+++ b/shibsp/handler/impl/SAML1Consumer.cpp
@@ -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);
diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
index ef85778..6b98392 100644
--- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp
+++ b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
@@ -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;
diff --git a/shibsp/handler/impl/SAML2Consumer.cpp b/shibsp/handler/impl/SAML2Consumer.cpp
index 0a2ebd8..532c0ac 100644
--- a/shibsp/handler/impl/SAML2Consumer.cpp
+++ b/shibsp/handler/impl/SAML2Consumer.cpp
@@ -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"
@@ -29,10 +29,11 @@
# 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;
diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp
index d917407..9a2e71a 100644
--- a/shibsp/handler/impl/SAML2Logout.cpp
+++ b/shibsp/handler/impl/SAML2Logout.cpp
@@ -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());
}
}
diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
index e5a6bbb..249eb8f 100644
--- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp
+++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
@@ -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());
diff --git a/shibsp/handler/impl/SAML2NameIDMgmt.cpp b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
index 4aba9a6..3af13a5 100644
--- a/shibsp/handler/impl/SAML2NameIDMgmt.cpp
+++ b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
@@ -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);
+ }
}
};
};
diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp
index 7121176..ae14e44 100644
--- a/shibsp/handler/impl/SAML2SessionInitiator.cpp
+++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp
@@ -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
);
diff --git a/shibsp/handler/impl/SAMLDSSessionInitiator.cpp b/shibsp/handler/impl/SAMLDSSessionInitiator.cpp
index 90d189c..5ff0878 100644
--- a/shibsp/handler/impl/SAMLDSSessionInitiator.cpp
+++ b/shibsp/handler/impl/SAMLDSSessionInitiator.cpp
@@ -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) {
diff --git a/shibsp/handler/impl/SessionHandler.cpp b/shibsp/handler/impl/SessionHandler.cpp
index 789793c..813aad9 100644
--- a/shibsp/handler/impl/SessionHandler.cpp
+++ b/shibsp/handler/impl/SessionHandler.cpp
@@ -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");
diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp
index aeda3c7..c9de163 100644
--- a/shibsp/handler/impl/Shib1SessionInitiator.cpp
+++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp
@@ -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);
diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp
index 41e9f1f..b9e066d 100644
--- a/shibsp/handler/impl/StatusHandler.cpp
+++ b/shibsp/handler/impl/StatusHandler.cpp
@@ -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.
diff --git a/shibsp/handler/impl/TransformSessionInitiator.cpp b/shibsp/handler/impl/TransformSessionInitiator.cpp
index 36759f3..390d3d8 100644
--- a/shibsp/handler/impl/TransformSessionInitiator.cpp
+++ b/shibsp/handler/impl/TransformSessionInitiator.cpp
@@ -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;
}
};
diff --git a/shibsp/handler/impl/WAYFSessionInitiator.cpp b/shibsp/handler/impl/WAYFSessionInitiator.cpp
index 19510ec..f0e075d 100644
--- a/shibsp/handler/impl/WAYFSessionInitiator.cpp
+++ b/shibsp/handler/impl/WAYFSessionInitiator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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
index 0000000..8b73906
--- /dev/null
+++ b/shibsp/impl/ChainingAccessControl.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2009 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ChainingAccessControl.cpp
+ *
+ * Access control plugin that combines other plugins.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+ class ChainingAccessControl : public AccessControl
+ {
+ public:
+ ChainingAccessControl(const DOMElement* e);
+
+ ~ChainingAccessControl() {
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+ }
+
+ Lockable* lock() {
+ for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+ return this;
+ }
+ void unlock() {
+ for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+ }
+
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+ private:
+ enum operator_t { OP_AND, OP_OR } m_op;
+ vector<AccessControl*> m_ac;
+ };
+
+ AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
+ {
+ return new ChainingAccessControl(e);
+ }
+
+ static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+ static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+ static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);
+ static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);
+
+ extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);
+}
+
+void SHIBSP_API shibsp::registerAccessControls()
+{
+ SPConfig& conf=SPConfig::getConfig();
+ conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);
+ conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
+ conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);
+}
+
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)
+{
+ const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;
+ if (XMLString::equals(op, AND))
+ m_op=OP_AND;
+ else if (XMLString::equals(op, OR))
+ m_op=OP_OR;
+ else
+ throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
+
+ try {
+ e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;
+ while (e) {
+ auto_ptr_char type(e->getAttributeNS(NULL, _type));
+ if (type.get() && *type.get()) {
+ Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());
+ m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));
+ }
+ e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+ }
+ }
+ catch (exception&) {
+ for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+ throw;
+ }
+ if (m_ac.empty())
+ throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
+}
+
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+ switch (m_op) {
+ case OP_AND:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+ if ((*i)->authorized(request, session) != shib_acl_true)
+ return shib_acl_false;
+ }
+ return shib_acl_true;
+ }
+
+ case OP_OR:
+ {
+ for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+ if ((*i)->authorized(request,session) == shib_acl_true)
+ return shib_acl_true;
+ }
+ return shib_acl_false;
+ }
+ }
+ request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");
+ return shib_acl_false;
+}
diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp
index cb51042..27f7610 100644
--- a/shibsp/impl/StorageServiceSessionCache.cpp
+++ b/shibsp/impl/StorageServiceSessionCache.cpp
@@ -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)
diff --git a/shibsp/impl/XMLAccessControl.cpp b/shibsp/impl/XMLAccessControl.cpp
index 939ea68..5d9d352 100644
--- a/shibsp/impl/XMLAccessControl.cpp
+++ b/shibsp/impl/XMLAccessControl.cpp
@@ -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
@@ -40,8 +40,8 @@ using namespace shibsp;
using namespace xmltooling;
using namespace std;
-namespace {
-
+namespace shibsp {
+
class Rule : public AccessControl
{
public:
@@ -52,12 +52,12 @@ namespace {
void unlock() {}
aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
+
private:
string m_alias;
vector <string> m_vals;
};
-
+
class RuleRegex : public AccessControl
{
public:
@@ -65,18 +65,18 @@ namespace {
~RuleRegex() {
delete m_re;
}
-
+
Lockable* lock() {return this;}
void unlock() {}
aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
+
private:
string m_alias;
auto_arrayptr<char> m_exp;
RegularExpression* m_re;
};
-
+
class Operator : public AccessControl
{
public:
@@ -87,7 +87,7 @@ namespace {
void unlock() {}
aclresult_t authorized(const SPRequest& request, const Session* session) const;
-
+
private:
enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
vector<AccessControl*> m_operands;
@@ -102,10 +102,10 @@ namespace {
{
public:
XMLAccessControl(const DOMElement* e)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl")), m_rootAuthz(NULL) {
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {
load(); // guarantees an exception or the policy is loaded
}
-
+
~XMLAccessControl() {
delete m_rootAuthz;
}
@@ -140,13 +140,6 @@ namespace {
static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);
}
-void SHIBSP_API shibsp::registerAccessControls()
-{
- SPConfig& conf=SPConfig::getConfig();
- conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
- conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);
-}
-
Rule::Rule(const DOMElement* e)
{
auto_ptr_char req(e->getAttributeNS(NULL,require));
@@ -157,14 +150,14 @@ Rule::Rule(const DOMElement* e)
auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));
if (!vals.get())
return;
-
+
const XMLCh* flag = e->getAttributeNS(NULL,_list);
if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {
if (*vals.get())
m_vals.push_back(vals.get());
return;
}
-
+
#ifdef HAVE_STRTOK_R
char* pos=NULL;
const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
@@ -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?");
return shib_acl_false;
}
-
+
if (m_alias == "valid-user") {
if (session) {
request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
@@ -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())
throw ConfigurationException("Access control rule missing require attribute or element content.");
m_alias=req.get();
-
+
const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);
bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));
try {
- m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+ m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
@@ -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?");
return shib_acl_false;
}
-
+
if (m_alias == "valid-user") {
if (session) {
request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
@@ -335,7 +328,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
auto_ptr_char tmp(ex.getMessage());
request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());
}
-
+
return shib_acl_false;
}
@@ -349,7 +342,7 @@ Operator::Operator(const DOMElement* e)
m_op=OP_OR;
else
throw ConfigurationException("Unrecognized operator in access control rule");
-
+
try {
e=XMLHelper::getFirstChildElement(e);
if (XMLString::equals(e->getLocalName(),_Rule))
@@ -358,10 +351,10 @@ Operator::Operator(const DOMElement* e)
m_operands.push_back(new RuleRegex(e));
else
m_operands.push_back(new Operator(e));
-
+
if (m_op==OP_NOT)
return;
-
+
e=XMLHelper::getNextSiblingElement(e);
while (e) {
if (XMLString::equals(e->getLocalName(),_Rule))
@@ -396,7 +389,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
default:
return shib_acl_indeterminate;
}
-
+
case OP_AND:
{
for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
@@ -405,7 +398,7 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
}
return shib_acl_true;
}
-
+
case OP_OR:
{
for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
@@ -423,14 +416,14 @@ pair<bool,DOMElement*> XMLAccessControl::load()
{
// Load from source using base class.
pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-
+
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
// Check for AccessControl wrapper and drop a level.
if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
raw.second = XMLHelper::getFirstChildElement(raw.second);
-
+
AccessControl* authz;
if (XMLString::equals(raw.second->getLocalName(),_Rule))
authz=new Rule(raw.second);
diff --git a/shibsp/impl/XMLRequestMapper.cpp b/shibsp/impl/XMLRequestMapper.cpp
index 9c5f294..78e6edf 100644
--- a/shibsp/impl/XMLRequestMapper.cpp
+++ b/shibsp/impl/XMLRequestMapper.cpp
@@ -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());
}
diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp
index fb16a21..5b9de5f 100644
--- a/shibsp/impl/XMLServiceProvider.cpp
+++ b/shibsp/impl/XMLServiceProvider.cpp
@@ -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
@@ -22,12 +22,14 @@
#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"
@@ -42,8 +44,10 @@
#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
@@ -53,12 +57,11 @@
# 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());
diff --git a/shibsp/lite/CommonDomainCookie.cpp b/shibsp/lite/CommonDomainCookie.cpp
index fd3bfba..cb8ffc0 100644
--- a/shibsp/lite/CommonDomainCookie.cpp
+++ b/shibsp/lite/CommonDomainCookie.cpp
@@ -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();
}
diff --git a/shibsp/lite/SAMLConstants.cpp b/shibsp/lite/SAMLConstants.cpp
index 5c2be15..59f8e8b 100644
--- a/shibsp/lite/SAMLConstants.cpp
+++ b/shibsp/lite/SAMLConstants.cpp
@@ -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";
diff --git a/shibsp/lite/SAMLConstants.h b/shibsp/lite/SAMLConstants.h
index 74e0004..f04b3f3 100644
--- a/shibsp/lite/SAMLConstants.h
+++ b/shibsp/lite/SAMLConstants.h
@@ -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__
@@ -29,10 +29,10 @@
* 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[];
};
diff --git a/shibsp/metadata/DynamicMetadataProvider.cpp b/shibsp/metadata/DynamicMetadataProvider.cpp
index 42545a3..9e583e4 100644
--- a/shibsp/metadata/DynamicMetadataProvider.cpp
+++ b/shibsp/metadata/DynamicMetadataProvider.cpp
@@ -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.");
+ }
// 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;
diff --git a/shibsp/metadata/MetadataExtImpl.cpp b/shibsp/metadata/MetadataExtImpl.cpp
index 6188b46..71fb17a 100644
--- a/shibsp/metadata/MetadataExtImpl.cpp
+++ b/shibsp/metadata/MetadataExtImpl.cpp
@@ -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);
diff --git a/shibsp/metadata/MetadataExtSchemaValidators.cpp b/shibsp/metadata/MetadataExtSchemaValidators.cpp
index d175ba4..f9b4472 100644
--- a/shibsp/metadata/MetadataExtSchemaValidators.cpp
+++ b/shibsp/metadata/MetadataExtSchemaValidators.cpp
@@ -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);
diff --git a/shibsp/metadata/MetadataProviderCriteria.h b/shibsp/metadata/MetadataProviderCriteria.h
index 4020005..286a4a0 100644
--- a/shibsp/metadata/MetadataProviderCriteria.h
+++ b/shibsp/metadata/MetadataProviderCriteria.h
@@ -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
diff --git a/shibsp/paths.h b/shibsp/paths.h
index 4aa5d5e..6eb507d 100644
--- a/shibsp/paths.h
+++ b/shibsp/paths.h
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -23,24 +23,31 @@
#ifndef __shibsp_paths_h__
#define __shibsp_paths_h__
-/**
- * Default schema catalogs.
- */
-#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"
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/usr/share/xml/opensaml/saml20-catalog.xml:/usr/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"
-/**
- * Default name of SP configuration file.
- */
+/** Default name of SP configuration file. */
#define SHIBSP_CONFIG "shibboleth2.xml"
-/**
- * Default name of SP console tool logging file.
- */
+/** Default name of SP console tool logging file. */
#define SHIBSP_LOGGING "console.logger"
-/**
- * Default prefix for installation (used to resolve relative paths).
- */
-#define SHIBSP_PREFIX "/usr/local"
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX "/opt/shibboleth-sp"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR "/opt/shibboleth-sp/lib"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR "/opt/shibboleth-sp/var/log"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR "/opt/shibboleth-sp/etc"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR "/opt/shibboleth-sp/var/run"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR "/opt/shibboleth-sp/share/xml"
#endif /* __shibsp_paths_h__ */
diff --git a/shibsp/paths.h.in b/shibsp/paths.h.in
index 9f5e2b1..f35df0b 100644
--- a/shibsp/paths.h.in
+++ b/shibsp/paths.h.in
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -23,24 +23,31 @@
#ifndef __shibsp_paths_h__
#define __shibsp_paths_h__
-/**
- * Default schema catalogs.
- */
+/** Default schema catalogs. */
#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"
-/**
- * Default name of SP configuration file.
- */
+/** Default name of SP configuration file. */
#define SHIBSP_CONFIG "shibboleth2.xml"
-/**
- * Default name of SP console tool logging file.
- */
+/** Default name of SP console tool logging file. */
#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 "@-PREFIX-@"
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR "@-LIBDIR-@"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR "@-LOGDIR-@"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR "@-SYSCONFDIR-@"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR "@-RUNDIR-@"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR "@-XMLDIR-@"
+
#endif /* __shibsp_paths_h__ */
diff --git a/shibsp/remoting/ListenerService.h b/shibsp/remoting/ListenerService.h
index 3e8c6b3..c85af8c 100644
--- a/shibsp/remoting/ListenerService.h
+++ b/shibsp/remoting/ListenerService.h
@@ -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;
};
diff --git a/shibsp/remoting/ddf.h b/shibsp/remoting/ddf.h
index 041f344..b361ec0 100644
--- a/shibsp/remoting/ddf.h
+++ b/shibsp/remoting/ddf.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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);
diff --git a/shibsp/remoting/impl/ListenerService.cpp b/shibsp/remoting/impl/ListenerService.cpp
index 600c87f..f33b307 100644
--- a/shibsp/remoting/impl/ListenerService.cpp
+++ b/shibsp/remoting/impl/ListenerService.cpp
@@ -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);
}
diff --git a/shibsp/remoting/impl/SocketListener.cpp b/shibsp/remoting/impl/SocketListener.cpp
index e211b20..edac04f 100644
--- a/shibsp/remoting/impl/SocketListener.cpp
+++ b/shibsp/remoting/impl/SocketListener.cpp
@@ -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;
}
diff --git a/shibsp/remoting/impl/SocketListener.h b/shibsp/remoting/impl/SocketListener.h
index 0922cf4..a558650 100644
--- a/shibsp/remoting/impl/SocketListener.h
+++ b/shibsp/remoting/impl/SocketListener.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/shibsp/remoting/impl/TCPListener.cpp b/shibsp/remoting/impl/TCPListener.cpp
index 44828e6..05f2f90 100644
--- a/shibsp/remoting/impl/TCPListener.cpp
+++ b/shibsp/remoting/impl/TCPListener.cpp
@@ -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;
}
diff --git a/shibsp/remoting/impl/ddf.cpp b/shibsp/remoting/impl/ddf.cpp
index 463bb8c..ae44d4f 100644
--- a/shibsp/remoting/impl/ddf.cpp
+++ b/shibsp/remoting/impl/ddf.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
/**
* 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)) {
diff --git a/shibsp/security/PKIXTrustEngine.cpp b/shibsp/security/PKIXTrustEngine.cpp
index c8ed9bc..d52db86 100644
--- a/shibsp/security/PKIXTrustEngine.cpp
+++ b/shibsp/security/PKIXTrustEngine.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/shibsp/security/SecurityPolicy.cpp b/shibsp/security/SecurityPolicy.cpp
index 6e260d4..8317554 100644
--- a/shibsp/security/SecurityPolicy.cpp
+++ b/shibsp/security/SecurityPolicy.cpp
@@ -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,21 +16,38 @@
/**
* 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;
}
diff --git a/shibsp/security/SecurityPolicy.h b/shibsp/security/SecurityPolicy.h
index 74745ff..29a3bf5 100644
--- a/shibsp/security/SecurityPolicy.h
+++ b/shibsp/security/SecurityPolicy.h
@@ -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.
*/
@@ -24,32 +24,35 @@
#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 {
diff --git a/shibsp/shibsp-lite.vcproj b/shibsp/shibsp-lite.vcproj
index 48dc6af..e465154 100644
--- a/shibsp/shibsp-lite.vcproj
+++ b/shibsp/shibsp-lite.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="shibsp-lite"
ProjectGUID="{81F0F7A6-DC36-46EF-957F-F9E81D4403F7}"
RootNamespace="shibsp-lite"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -65,12 +66,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"
TargetMachine="1"
/>
@@ -93,9 +96,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -147,12 +147,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xmltooling-lite1D.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"
TargetMachine="17"
/>
@@ -175,9 +177,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -225,13 +224,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1.dll"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1.lib"
TargetMachine="1"
/>
@@ -254,9 +255,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -305,14 +303,16 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xmltooling-lite1.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1.dll"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1.lib"
TargetMachine="17"
/>
@@ -335,9 +335,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -418,6 +415,10 @@
Name="impl"
>
<File
+ RelativePath=".\impl\ChainingAccessControl.cpp"
+ >
+ </File>
+ <File
RelativePath=".\impl\StorageServiceSessionCache.cpp"
>
</File>
@@ -441,6 +442,10 @@
RelativePath=".\attribute\Attribute.cpp"
>
</File>
+ <File
+ RelativePath=".\attribute\ExtensibleAttribute.cpp"
+ >
+ </File>
</Filter>
<Filter
Name="handler"
@@ -672,6 +677,10 @@
>
</File>
<File
+ RelativePath=".\attribute\ExtensibleAttribute.h"
+ >
+ </File>
+ <File
RelativePath=".\attribute\NameIDAttribute.h"
>
</File>
@@ -683,6 +692,10 @@
RelativePath=".\attribute\SimpleAttribute.h"
>
</File>
+ <File
+ RelativePath=".\attribute\XMLAttribute.h"
+ >
+ </File>
</Filter>
<Filter
Name="handler"
diff --git a/shibsp/shibsp.rc b/shibsp/shibsp.rc
index 5f8cda8..b39d484 100644
--- a/shibsp/shibsp.rc
+++ b/shibsp/shibsp.rc
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 1,2,1,0
+ PRODUCTVERSION 2,2,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -51,38 +51,38 @@ BEGIN
#else
VALUE "FileDescription", "Shibboleth SP Library\0"
#endif
- VALUE "FileVersion", "1, 1, 0, 0\0"
+ VALUE "FileVersion", "1, 2, 1, 0\0"
#ifdef SHIBSP_LITE
#ifdef _DEBUG
- VALUE "InternalName", "shibsp-lite1_1D\0"
+ VALUE "InternalName", "shibsp-lite1_2D\0"
#else
- VALUE "InternalName", "shibsp-lite1_1\0"
+ VALUE "InternalName", "shibsp-lite1_2\0"
#endif
#else
#ifdef _DEBUG
- VALUE "InternalName", "shibsp1_1D\0"
+ VALUE "InternalName", "shibsp1_2D\0"
#else
- VALUE "InternalName", "shibsp1_1\0"
+ VALUE "InternalName", "shibsp1_2\0"
#endif
#endif
- VALUE "LegalCopyright", "Copyright � 2008 Internet2\0"
+ VALUE "LegalCopyright", "Copyright � 2009 Internet2\0"
VALUE "LegalTrademarks", "\0"
#ifdef SHIBSP_LITE
#ifdef _DEBUG
- VALUE "OriginalFilename", "shibsp-lite1_1D.dll\0"
+ VALUE "OriginalFilename", "shibsp-lite1_2D.dll\0"
#else
- VALUE "OriginalFilename", "shibsp-lite1_1.dll\0"
+ VALUE "OriginalFilename", "shibsp-lite1_2.dll\0"
#endif
#else
#ifdef _DEBUG
- VALUE "OriginalFilename", "shibsp1_1D.dll\0"
+ VALUE "OriginalFilename", "shibsp1_2D.dll\0"
#else
- VALUE "OriginalFilename", "shibsp1_1.dll\0"
+ VALUE "OriginalFilename", "shibsp1_2.dll\0"
#endif
#endif
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
diff --git a/shibsp/shibsp.vcproj b/shibsp/shibsp.vcproj
index bb58f7e..cbd630d 100644
--- a/shibsp/shibsp.vcproj
+++ b/shibsp/shibsp.vcproj
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="shibsp"
ProjectGUID="{81F0F7A6-DC36-46EF-957F-F9E81D4403F6}"
RootNamespace="shibsp"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -65,12 +66,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"
TargetMachine="1"
/>
@@ -93,9 +96,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -147,12 +147,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib xerces-c_2D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1D.dll"
+ AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1D.lib"
TargetMachine="17"
/>
@@ -175,9 +177,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -224,13 +223,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1.dll"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1.lib"
TargetMachine="1"
/>
@@ -253,9 +254,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -303,14 +301,16 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib xerces-c_2.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"
- OutputFile="$(OutDir)\$(ProjectName)1_1.dll"
+ AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)1_2.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
ImportLibrary="$(TargetDir)$(ProjectName)1.lib"
TargetMachine="17"
/>
@@ -333,9 +333,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -444,6 +441,10 @@
Name="impl"
>
<File
+ RelativePath=".\impl\ChainingAccessControl.cpp"
+ >
+ </File>
+ <File
RelativePath=".\impl\StorageServiceSessionCache.cpp"
>
</File>
@@ -468,6 +469,18 @@
>
</File>
<File
+ RelativePath=".\attribute\DOMAttributeDecoder.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\attribute\ExtensibleAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\attribute\KeyInfoAttributeDecoder.cpp"
+ >
+ </File>
+ <File
RelativePath=".\attribute\NameIDAttributeDecoder.cpp"
>
</File>
@@ -483,6 +496,10 @@
RelativePath=".\attribute\StringAttributeDecoder.cpp"
>
</File>
+ <File
+ RelativePath=".\attribute\XMLAttributeDecoder.cpp"
+ >
+ </File>
<Filter
Name="resolver"
>
@@ -498,10 +515,22 @@
>
</File>
<File
+ RelativePath=".\attribute\resolver\impl\DelegationAttributeExtractor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\attribute\resolver\impl\KeyDescriptorAttributeExtractor.cpp"
+ >
+ </File>
+ <File
RelativePath=".\attribute\resolver\impl\QueryAttributeResolver.cpp"
>
</File>
<File
+ RelativePath=".\attribute\resolver\impl\SimpleAggregationAttributeResolver.cpp"
+ >
+ </File>
+ <File
RelativePath=".\attribute\resolver\impl\XMLAttributeExtractor.cpp"
>
</File>
@@ -747,10 +776,6 @@
>
</File>
<File
- RelativePath=".\ApplicationAwarePlugin.h"
- >
- </File>
- <File
RelativePath=".\base.h"
>
</File>
@@ -858,6 +883,10 @@
>
</File>
<File
+ RelativePath=".\attribute\ExtensibleAttribute.h"
+ >
+ </File>
+ <File
RelativePath=".\attribute\NameIDAttribute.h"
>
</File>
@@ -869,6 +898,10 @@
RelativePath=".\attribute\SimpleAttribute.h"
>
</File>
+ <File
+ RelativePath=".\attribute\XMLAttribute.h"
+ >
+ </File>
<Filter
Name="resolver"
>
diff --git a/shibsp/util/CGIParser.cpp b/shibsp/util/CGIParser.cpp
index 1011351..d1cba90 100644
--- a/shibsp/util/CGIParser.cpp
+++ b/shibsp/util/CGIParser.cpp
@@ -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. */
diff --git a/shibsp/util/CGIParser.h b/shibsp/util/CGIParser.h
index b76953d..c0e3371 100644
--- a/shibsp/util/CGIParser.h
+++ b/shibsp/util/CGIParser.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
diff --git a/shibsp/version.h b/shibsp/version.h
index 8836d4a..b08f76d 100644
--- a/shibsp/version.h
+++ b/shibsp/version.h
@@ -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__
@@ -33,12 +33,12 @@
// 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 */
diff --git a/util/mdquery.cpp b/util/mdquery.cpp
index 33435cc..89cc34e 100644
--- a/util/mdquery.cpp
+++ b/util/mdquery.cpp
@@ -94,48 +94,25 @@ int main(int argc,char* argv[])
if (!entityID) {
usage();
- exit(-10);
+ return -10;
}
- char* path=getenv("SHIBSP_SCHEMAS");
- if (!path)
- path=SHIBSP_SCHEMAS;
- char* config=getenv("SHIBSP_CONFIG");
- if (!config)
- config=SHIBSP_CONFIG;
-
- XMLToolingConfig::getConfig().log_config(getenv("SHIBSP_LOGGING") ? getenv("SHIBSP_LOGGING") : SHIBSP_LOGGING);
-
- SPConfig& conf=SPConfig::getConfig();
- conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);
- if (!conf.init(path))
- return -1;
-
if (rname) {
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::OutOfProcess | SPConfig::Credentials);
+ if (!conf.init())
+ return -1;
+ if (!conf.instantiate()) {
conf.term();
return -2;
}
diff --git a/util/mdquery.vcproj b/util/mdquery.vcproj
index 5240966..6335253 100644
--- a/util/mdquery.vcproj
+++ b/util/mdquery.vcproj
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="mdquery"
ProjectGUID="{F13141B6-6C87-40BB-8D4E-5CC56EBB4C5A}"
RootNamespace="mdquery"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -70,11 +71,13 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"
+ AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -96,16 +99,13 @@
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"
@@ -125,21 +125,22 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -147,7 +148,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -155,13 +156,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"
- LinkIncremental="2"
+ AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.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"
@@ -182,16 +184,13 @@
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"
@@ -211,22 +210,21 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -234,7 +232,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -242,12 +240,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"
- LinkIncremental="1"
+ AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.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"
@@ -268,9 +269,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -328,12 +326,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"
+ AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -355,9 +355,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
diff --git a/util/resolvertest.cpp b/util/resolvertest.cpp
index 43a0e49..6fe35e2 100644
--- a/util/resolvertest.cpp
+++ b/util/resolvertest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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;
}
diff --git a/util/resolvertest.vcproj b/util/resolvertest.vcproj
index 4ced967..26a719b 100644
--- a/util/resolvertest.vcproj
+++ b/util/resolvertest.vcproj
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="resolvertest"
ProjectGUID="{F13141B6-6C87-40BB-8D4E-5CC56EBB4C59}"
RootNamespace="resolvertest"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -70,11 +71,13 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"
+ AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -96,18 +99,14 @@
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"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
@@ -126,21 +125,22 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -148,7 +148,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
+ PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
@@ -156,13 +156,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"
- LinkIncremental="2"
+ AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_3.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"
@@ -183,17 +184,15 @@
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"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
@@ -212,22 +211,21 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
+ Optimization="0"
AdditionalIncludeDirectories=".;..;"..\..\cpp-opensaml2";"..\..\cpp-xmltooling""
- 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
@@ -235,7 +233,7 @@
/>
<Tool
Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
+ PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
@@ -243,12 +241,15 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1.lib saml2.lib xmltooling1.lib xerces-c_2.lib"
- LinkIncremental="1"
+ AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.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"
@@ -269,9 +270,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -330,12 +328,14 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_2D.lib"
+ AdditionalDependencies="log4shib1D.lib saml2D.lib xmltooling1D.lib xerces-c_3D.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -357,9 +357,6 @@
Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list