Subject: Collected Debian patches for shibboleth-sp2
Author: Russ Allbery <rra@debian.org>

The packaging for shibboleth-sp2 is maintained in Git using multiple
branches for fixes, which makes it complex to separate the changes
into individual patches.  They are therefore all included in a single
Debian patch.

For full commit history and separated commits, see the packaging Git
repository.
--- shibboleth-sp2-2.4.3+dfsg.orig/configs/Makefile.am
+++ shibboleth-sp2-2.4.3+dfsg/configs/Makefile.am
@@ -4,8 +4,8 @@ AUTOMAKE_OPTIONS = foreign
 
 pkglibdir = ${libdir}/@PACKAGE@
 pkglogdir = ${localstatedir}/log/@PACKAGE@
-pkgdocdir = $(datadir)/doc/@PACKAGE@-@PACKAGE_VERSION@
-shirelogdir = ${localstatedir}/log/httpd
+pkgdocdir = ${datadir}/doc/@PACKAGE@
+shirelogdir = ${localstatedir}/log/apache2
 pkgxmldir = $(datadir)/xml/@PACKAGE@
 pkgrundir = $(localstatedir)/run/@PACKAGE@
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
--- shibboleth-sp2-2.4.3+dfsg.orig/configs/keygen.sh
+++ shibboleth-sp2-2.4.3+dfsg/configs/keygen.sh
@@ -1,5 +1,11 @@
 #! /bin/sh
 
+# Defaults added for Debian.  They can still be overridden by command-line
+# options.
+OUT=/etc/shibboleth
+USER=_shibd
+GROUP=_shibd
+
 while getopts h:u:g:o:e:y:bf c
      do
          case $c in
@@ -32,8 +38,9 @@ if  [ -s $OUT/sp-key.pem -o -s $OUT/sp-c
     exit 0
 fi
 
+# --fqdn flag added for Debian to generate better names for certificates.
 if [ -z "$FQDN" ] ; then
-    FQDN=`hostname`
+    FQDN=`hostname --fqdn`
 fi
 
 if [ -z "$YEARS" ] ; then
--- shibboleth-sp2-2.4.3+dfsg.orig/configs/metagen.sh
+++ shibboleth-sp2-2.4.3+dfsg/configs/metagen.sh
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
 
 DECLS=1
 
--- shibboleth-sp2-2.4.3+dfsg.orig/configs/native.logger.in
+++ shibboleth-sp2-2.4.3+dfsg/configs/native.logger.in
@@ -26,17 +26,29 @@ log4j.category.XMLTooling.libcurl=INFO
 
 # define the appender
 
-log4j.appender.native_log=org.apache.log4j.RollingFileAppender
-log4j.appender.native_log.fileName=@-SHIRELOGDIR-@/native.log
-log4j.appender.native_log.maxFileSize=1000000
-log4j.appender.native_log.maxBackupIndex=10
-log4j.appender.native_log.layout=org.apache.log4j.PatternLayout
-log4j.appender.native_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+# This is the default, but it's essentially useless under normal
+# circumstances since Apache doesn't have access to write to that
+# directory.
+#log4j.appender.native_log=org.apache.log4j.RollingFileAppender
+#log4j.appender.native_log.fileName=@-SHIRELOGDIR-@/native.log
+#log4j.appender.native_log.maxFileSize=1000000
+#log4j.appender.native_log.maxBackupIndex=10
+#log4j.appender.native_log.layout=org.apache.log4j.PatternLayout
+#log4j.appender.native_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+#log4j.appender.warn_log=org.apache.log4j.RollingFileAppender
+#log4j.appender.warn_log.fileName=@-SHIRELOGDIR-@/native_warn.log
+#log4j.appender.warn_log.maxFileSize=1000000
+#log4j.appender.warn_log.maxBackupIndex=10
+#log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout
+#log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+#log4j.appender.warn_log.threshold=WARN
 
-log4j.appender.warn_log=org.apache.log4j.RollingFileAppender
-log4j.appender.warn_log.fileName=@-SHIRELOGDIR-@/native_warn.log
-log4j.appender.warn_log.maxFileSize=1000000
-log4j.appender.warn_log.maxBackupIndex=10
-log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout
-log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
-log4j.appender.warn_log.threshold=WARN
+# Use syslog instead, since then at least the messages will go somewhere.
+# That facility is LOG_DAEMON, since log4cpp apparently doesn't recognize
+# symbolic log facilities.
+#
+# This is a Debian-specific change.
+log4j.appender.native_log=org.apache.log4j.LocalSyslogAppender
+log4j.appender.native_log.syslogName=shibboleth-sp
+log4j.appender.native_log.facility=3
+log4j.appender.native_log.layout=org.apache.log4j.BasicLayout
--- shibboleth-sp2-2.4.3+dfsg.orig/configs/shibd-debian.in
+++ shibboleth-sp2-2.4.3+dfsg/configs/shibd-debian.in
@@ -1,18 +1,20 @@
 #! /bin/sh
 ### BEGIN INIT INFO
-# Provides: shibd
-# Required-Start: $local_fs $remote_fs $network
-# Required-Stop: $local_fs $remote_fs $network
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Shibboleth 2 Service Provider Daemon
-# Description: Starts the separate daemon used by the Shibboleth
-# Apache module to manage sessions and to retrieve
-# attributes from Shibboleth Identity Providers.
+# Provides:             shibd
+# Required-Start:       $local_fs $remote_fs $network
+# Required-Stop:        $local_fs $remote_fs
+# Default-Start:        2 3 4 5
+# Default-Stop:
+# Short-Description:    Shibboleth 2 Service Provider Daemon
+# Description:          Starts the separate daemon used by the Shibboleth
+#                       Apache module to manage sessions and to retrieve
+#                       attributes from Shibboleth Identity Providers.
 ### END INIT INFO
 #
 # Written by Quanah Gibson-Mount <quanah@stanford.edu>
 # Modified by Lukas Haemmerle <lukas.haemmerle@switch.ch> for Shibboleth 2
+# Updated to use the LSB init functions by Russ Allbery <rra@debian.org>
+#
 # Based on the dh-make template written by:
 #
 # Written by Miquel van Smoorenburg <miquels@cistron.nl>.
@@ -29,6 +31,7 @@ DAEMON=@-PREFIX-@/sbin/$NAME
 SCRIPTNAME=/etc/init.d/$NAME
 PIDFILE=@-PKGRUNDIR-@/$NAME.pid
 DAEMON_OPTS=""
+DAEMON_USER=_shibd
 
 # Force removal of socket
 DAEMON_OPTS="$DAEMON_OPTS -f"
@@ -48,38 +51,122 @@ DAEMON_OPTS="$DAEMON_OPTS -w 30"
 # Read configuration if it is present.
 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
 
-# Get the setting of VERBOSE and other rcS variables.
-[ -f /etc/default/rcS ] && . /etc/default/rcS
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+. /lib/lsb/init-functions
+
+prepare_environment () {
+    # Ensure @-PKGRUNDIR-@ exists.  /var/run may be on a tmpfs file system.
+    [ -d '@-PKGRUNDIR-@' ] || mkdir -p '@-PKGRUNDIR-@'
+
+    # If $DAEMON_USER is set, try to run shibd as that user.  However,
+    # versions of the Debian package prior to 2.3+dfsg-1 ran shibd as root,
+    # and the local administrator may not have made the server's private key
+    # readable by $DAEMON_USER.  We therefore test first by running shibd -t
+    # and looking for the error code indicating that the private key could not
+    # be read.  If we get that error, we fall back on running shibd as root.
+    if [ -n "$DAEMON_USER" ]; then
+        DIAG=$(su -s $DAEMON $DAEMON_USER -- -t $DAEMON_OPTS 2>/dev/null)
+        if [ $? = 0 ] ; then
+            # openssl errstr 200100D (hex for 33558541) says:
+            # error:0200100D:system library:fopen:Permission denied
+            ERROR='ERROR OpenSSL : error code: 33558541 '
+            if echo "$DIAG" | fgrep -q "$ERROR" ; then
+                unset DAEMON_USER
+                log_warning_msg "$NAME: file permissions require running as" \
+                    "root"
+            else
+                chown -Rh "$DAEMON_USER" '@-PKGRUNDIR-@' '@-PKGLOGDIR-@'
+            fi
+        else
+            unset DAEMON_USER
+            log_warning_msg "$NAME: unable to run config check as user" \
+                "$DAEMON_USER"
+        fi
+        unset DIAG
+    fi
+}
+
+# Start shibd.
+do_start () {
+    # Return
+    #   0 if daemon has been started
+    #   1 if daemon was already running
+    #   2 if daemon could not be started
+    start-stop-daemon --start --quiet ${DAEMON_USER:+--chuid $DAEMON_USER} \
+        --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+        || return 1
+    start-stop-daemon --start --quiet ${DAEMON_USER:+--chuid $DAEMON_USER} \
+        --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS \
+        || return 2
+}
+
+# Stop shibd.
+do_stop () {
+    # Return
+    #   0 if daemon has been stopped
+    #   1 if daemon was already stopped
+    #   2 if daemon could not be stopped
+    #   other if a failure occurred
+    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
+        --pidfile $PIDFILE --name $NAME
+    RETVAL="$?"
+    return "$RETVAL"
+}
 
 case "$1" in
 start)
+    prepare_environment
+
     # Don't start shibd if NO_START is set.
     if [ "$NO_START" = 1 ] ; then
-        echo "Not starting $DESC (see /etc/default/$NAME)"
+        if [ "$VERBOSE" != no ] ; then
+            echo "Not starting $DESC (see /etc/default/$NAME)"
+        fi
         exit 0
     fi
-    echo -n "Starting $DESC: "
-    start-stop-daemon --start --quiet \
-        --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
-    echo "$NAME."
+    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+    do_start
+    case "$?" in
+        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+        2)   [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+    esac
     ;;
 stop)
-    echo -n "Stopping $DESC: "
-    start-stop-daemon --stop --quiet --pidfile $PIDFILE \
-        --exec $DAEMON
-    echo "$NAME."
+    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+    do_stop
+    case "$?" in
+        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+        2)   [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+    esac
     ;;
 restart|force-reload)
-    echo -n "Restarting $DESC: "
-    start-stop-daemon --stop --quiet --pidfile $PIDFILE \
-        --exec $DAEMON
-    sleep 1
-    start-stop-daemon --start --quiet \
-        --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
-    echo "$NAME."
+    prepare_environment
+
+    log_daemon_msg "Restarting $DESC" "$NAME"
+    do_stop
+    case "$?" in
+        0|1)
+            do_start
+            case "$?" in
+                0) log_end_msg 0 ;;
+                1) log_end_msg 1 ;; # Old process is still running
+                *) log_end_msg 1 ;; # Failed to start
+            esac
+            ;;
+        *)
+            # Failed to stop
+            log_end_msg 1
+            ;;
+    esac
+    ;;
+status)
+    status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
     ;;
 *)
-    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
+    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
     exit 1
     ;;
 esac
--- shibboleth-sp2-2.4.3+dfsg.orig/memcache-store/memcache-store.cpp
+++ shibboleth-sp2-2.4.3+dfsg/memcache-store/memcache-store.cpp
@@ -308,7 +308,7 @@ bool MemcacheBase::deleteMemcache(const
     success = false;
   } else if (rv == MEMCACHED_ERRNO) {
     // System error
-    string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(memcached_last_error_message(memc));
     log.error(error);
     throw IOException(error);
   } else {
@@ -349,7 +349,7 @@ bool MemcacheBase::getMemcache(const cha
     success = false;
   } else if (rv == MEMCACHED_ERRNO) {
     // System error
-    string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(memcached_last_error_message(memc));
     log.error(error);
     throw IOException(error);
   } else {
@@ -388,7 +388,7 @@ bool MemcacheBase::addMemcache(const cha
     success = false;
   } else if (rv == MEMCACHED_ERRNO) {
     // System error
-    string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(memcached_last_error_message(memc));
     log.error(error);
     throw IOException(error);
   } else {
@@ -424,7 +424,7 @@ bool MemcacheBase::setMemcache(const cha
     success = true;
   } else if (rv == MEMCACHED_ERRNO) {
     // System error
-    string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(memcached_last_error_message(memc));
     log.error(error);
     throw IOException(error);
   } else {
@@ -463,7 +463,7 @@ bool MemcacheBase::replaceMemcache(const
     success = false;
   } else if (rv == MEMCACHED_ERRNO) {
     // System error
-    string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(memcached_last_error_message(memc));
     log.error(error);
     throw IOException(error);
   } else {
--- shibboleth-sp2-2.4.3+dfsg.orig/schemas/Makefile.am
+++ shibboleth-sp2-2.4.3+dfsg/schemas/Makefile.am
@@ -13,8 +13,7 @@ schemafiles = \
     shibboleth-2.0-afp.xsd \
     shibboleth-2.0-afp-mf-basic.xsd \
     shibboleth-2.0-afp-mf-saml.xsd \
-    shibboleth-2.0-attribute-map.xsd \
-    WS-Trust.xsd
+    shibboleth-2.0-attribute-map.xsd
 
 pkgxml_DATA = \
 	catalog.xml \
--- shibboleth-sp2-2.4.3+dfsg.orig/schemas/catalog.xml.in
+++ shibboleth-sp2-2.4.3+dfsg/schemas/catalog.xml.in
@@ -9,5 +9,7 @@
     <system systemId="urn:mace:shibboleth:2.0:afp:mf:saml" uri="@-PKGXMLDIR-@/shibboleth-2.0-afp-mf-saml.xsd"/>
     <system systemId="urn:mace:shibboleth:2.0:attribute-map" uri="@-PKGXMLDIR-@/shibboleth-2.0-attribute-map.xsd"/>
     <system systemId="urn:mace:shibboleth:1.0" uri="@-PKGXMLDIR-@/shibboleth.xsd"/>
+  <!-- WS-Trust.xsd has been removed from the Debian package because of license problems
     <system systemId="http://schemas.xmlsoap.org/ws/2005/02/trust" uri="@-PKGXMLDIR-@/WS-Trust.xsd"/>
+   -->
 </catalog>
--- shibboleth-sp2-2.4.3+dfsg.orig/shibsp/handler/impl/SAML2Consumer.cpp
+++ shibboleth-sp2-2.4.3+dfsg/shibsp/handler/impl/SAML2Consumer.cpp
@@ -42,6 +42,7 @@
 # include <xmltooling/XMLToolingConfig.h>
 # include <xmltooling/io/HTTPRequest.h>
 # include <xmltooling/util/DateTime.h>
+# include <xmltooling/validation/ValidatorSuite.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
@@ -294,6 +295,9 @@ void SAML2Consumer::implementProtocol(
             continue;
 
         try {
+            // Run the schema validators against the assertion, since it was hidden by encryption.
+            SchemaValidators.validate(decrypted);
+
             // We clear the security flag, so we can tell whether the token was secured on its own.
             policy.setAuthenticated(false);
             policy.reset(true);
--- shibboleth-sp2-2.4.3+dfsg.orig/shibsp/impl/StorageServiceSessionCache.cpp
+++ shibboleth-sp2-2.4.3+dfsg/shibsp/impl/StorageServiceSessionCache.cpp
@@ -1038,7 +1038,7 @@ void SSCache::insert(
 
     // Store the reverse mapping for logout.
     try {
-        if (nameid)
+        if (name.get() && *name.get())
             insert(key.get(), expires, name.get(), index.get());
     }
     catch (exception& ex) {
