Bug#925473: tomcat9: sysvinit script missing (Policy §9.11¶2 =?UTF-8?Q?=E2=80=9Cmust=E2=80=9D?=)

Thorsten Glaser t.glaser at tarent.de
Mon Apr 1 14:49:37 BST 2019


Hi Emmanuel,

> > When it's ready please let me review the update before uploading.
> 
> OK.

Here we are, now. I’m posting the entire diff, but with comments
in between. This is exactly what’s on git master right now. I’d
like to merge the fixes for #925928 and #925929 and upload once
you have reviewed this.

diff --git a/debian/libexec/tomcat-locate-java.sh b/debian/libexec/tomcat-locate-java.sh
old mode 100755
new mode 100644
index 341f9b15..b6dbb01e
--- a/debian/libexec/tomcat-locate-java.sh
+++ b/debian/libexec/tomcat-locate-java.sh
@@ -1,4 +1,3 @@
-#!/bin/sh
 #
 # Script looking for a Java runtime suitable for running Tomcat
 #

This script is only ever sourced, not executed, so it ought to not
have a shebang and not be executable. (As it merely sets a variable,
executing it makes no sense anyway.)

diff --git a/debian/libexec/tomcat-start.sh b/debian/libexec/tomcat-start.sh
index 31aaecf8..f22a3422 100755
--- a/debian/libexec/tomcat-start.sh
+++ b/debian/libexec/tomcat-start.sh
@@ -15,7 +15,7 @@ export JAVA_OPTS
 
 # Enable the Java security manager?
 SECURITY=""
-[ "$TOMCAT_SECURITY" = "yes" ] && SECURITY="-security"
+[ "$SECURITY_MANAGER" = "true" ] && SECURITY="-security"
 
 
 # Start Tomcat

This unbreaks using the SECURITY_MANAGER parameter, which
TOMCAT_SECURITY was renamed to (also yes/no → true/not true).
It’s an unrelated fix discovered in the meantime.

diff --git a/debian/README.Debian b/debian/README.Debian
index d11fb47b..c005bb0b 100644
--- a/debian/README.Debian
+++ b/debian/README.Debian
@@ -54,6 +54,13 @@ Getting started
       systemctl daemon-reload
       systemctl restart tomcat9
 
+    ⚠ This is supported only when Tomcat is started with the systemd unit.
+
+    Using Tomcat with other init systems is supported, however that will
+    negate the security hardening detailed above, make Tomcat not have
+    its own temporary directory, not drop privileges/capabilities after
+    start, and not be restarted on crashing. Use at your own risk.
+
   * To run more than one Tomcat instance on your server, install the package
     tomcat9-user and run the tomcat9-instance-create utility.
     You should remove the tomcat9 package if you don't want Tomcat to
diff --git a/debian/logging.properties b/debian/logging.properties
index 37fa30d1..69ac42f0 100644
--- a/debian/logging.properties
+++ b/debian/logging.properties
@@ -33,7 +33,9 @@ handlers = 1catalina.org.apache.juli.AsyncFileHandler, 2localhost.org.apache.jul
 2localhost.org.apache.juli.AsyncFileHandler.maxDays = 90
 
 java.util.logging.ConsoleHandler.level = FINE
+# use one of these depending on whether you use systemd or not, or roll your own
 java.util.logging.ConsoleHandler.formatter = org.apache.juli.SystemdFormatter
+#java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
 
 
 ############################################################

These update some comments for non-systemd users and warn them off.

diff --git a/debian/control b/debian/control
index 41ab0f8f..a1652a93 100644
--- a/debian/control
+++ b/debian/control
@@ -47,7 +47,7 @@ Package: tomcat9
 Architecture: all
 Depends:
  lsb-base (>= 3.0-6),
- systemd (>= 215),
+ systemd (>= 215) | adduser,
  tomcat9-common (>= ${source:Version}),
  ucf,
  ${misc:Depends}
diff --git a/debian/tomcat9.lintian-overrides b/debian/tomcat9.lintian-overrides
new file mode 100644
index 00000000..9b0d6593
--- /dev/null
+++ b/debian/tomcat9.lintian-overrides
@@ -0,0 +1,2 @@
+# handled in dependencies and maintainer script as alternative
+tomcat9: maintainer-script-needs-depends-on-adduser postinst
diff --git a/debian/tomcat9.postinst b/debian/tomcat9.postinst
index 55fb55c2..7cd34950 100644
--- a/debian/tomcat9.postinst
+++ b/debian/tomcat9.postinst
@@ -5,6 +5,7 @@
 
 set -e
 
+# Note these are no longer configurable (as of commit 243d00dc688ea47f4c7cde570ccaaa70efe269bf)
 TOMCAT_USER="tomcat"
 TOMCAT_GROUP="tomcat"
 
@@ -12,8 +13,18 @@ CONFFILES="tomcat-users.xml web.xml server.xml logging.properties context.xml ca
 
 case "$1" in
     configure)
-	# Create the tomcat user as defined in /usr/lib/sysusers.d/tomcat9.conf
-	systemd-sysusers
+	if which systemd-sysusers >/dev/null; then
+		# Create the tomcat user as defined in /usr/lib/sysusers.d/tomcat9.conf
+		systemd-sysusers
+	elif id tomcat >/dev/null 2>&1; then
+		: The tomcat user already exists
+	else
+		# Create the tomcat user without systemd
+		adduser --system --home /var/lib/tomcat9 \
+		    --shell /usr/sbin/nologin --no-create-home \
+		    --group --disabled-password --disabled-login \
+		    --gecos 'Apache Tomcat' tomcat
+	fi
 
 	# Install the configuration files
 	for conffile in $CONFFILES;

This restores the ability to create the tomcat user without systemd.

diff --git a/debian/libexec/sysv-getjre.sh b/debian/libexec/sysv-getjre.sh
new file mode 100755
index 00000000..456bdf64
--- /dev/null
+++ b/debian/libexec/sysv-getjre.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# SYSVinit script helper to determine the JRE (for start-stop-daemon)
+#
+
+. /usr/libexec/tomcat9/tomcat-locate-java.sh
+set +e
+
+. /usr/share/tomcat9/bin/setclasspath.sh
+
+if test -n "$_RUNJAVA"; then
+	printf "OK<%s>" "$_RUNJAVA"
+else
+	echo UNSET
+fi
diff --git a/debian/libexec/sysv-start.sh b/debian/libexec/sysv-start.sh
new file mode 100755
index 00000000..ac8c46e0
--- /dev/null
+++ b/debian/libexec/sysv-start.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# SYSVinit script helper to wrap the systemd startup script
+#
+
+set -e
+
+# redirect stdio
+exec </dev/null
+exec >>/var/log/tomcat9/catalina.out
+exec 2>&1
+# write an initial log entry
+echo "[$(date +'%FT%T%z')] starting..."
+
+# make sure Tomcat is started with system locale
+
+# restore LC_ALL that was (un)set at initscript startup
+case $saved_LC_ALL in
+(x*)	LC_ALL=${saved_LC_ALL#x} ;;
+(*)	unset LC_ALL ;;
+esac
+# read global locale configuration
+test -r /etc/default/locale && . /etc/default/locale
+# export all POSIX locale-relevant environment variables if set
+for v in LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY \
+    LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE \
+    LC_MEASUREMENT LC_IDENTIFICATION LC_ALL; do
+	eval "x=\${$v-x}"
+	test x"$x" = x"x" || eval export "$v"
+done
+
+# hand control to the systemd startup script we wrap
+exec /usr/libexec/tomcat9/tomcat-start.sh "$@"
diff --git a/debian/tomcat9.init b/debian/tomcat9.init
new file mode 100644
index 00000000..e948c173
--- /dev/null
+++ b/debian/tomcat9.init
@@ -0,0 +1,163 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          tomcat9
+# 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: Tomcat 9
+# Description:       The Tomcat 9 servlet engine runs Java Web Archives.
+### END INIT INFO
+
+# stuff away, used later
+saved_LC_ALL=${LC_ALL+x$LC_ALL}
+export saved_LC_ALL
+
+# absolute basics
+LC_ALL=C PATH=/sbin:/usr/sbin:/bin:/usr/bin
+export LC_ALL PATH
+unset LANGUAGE
+
+# exit cleanly if disabled or not installed
+test -x /usr/libexec/tomcat9/sysv-start.sh || exit 0
+test -x /usr/libexec/tomcat9/sysv-getjre.sh || exit 0
+test -x /usr/libexec/tomcat9/tomcat-update-policy.sh || exit 0
+test -x /usr/libexec/tomcat9/tomcat-start.sh || exit 0
+
+# Debian/LSB init script foobar
+DESC='Tomcat 9 servlet engine'
+NAME=tomcat9
+readonly DESC NAME
+. /lib/init/vars.sh
+test -t 0 && VERBOSE=yes
+. /lib/lsb/init-functions
+
+# somewhat LSB-compliant exit with failure
+if test x"$1" = x"status"; then
+	exit_failure_msg() {
+		log_failure_msg "$@"
+		exit 4
+	}
+else
+	exit_failure_msg() {
+		log_failure_msg "$@"
+		exit 1
+	}
+fi
+
+# set defaults for options
+CATALINA_HOME=/usr/share/tomcat9
+CATALINA_BASE=/var/lib/tomcat9
+CATALINA_TMPDIR=/tmp/tomcat9-tmp
+export CATALINA_HOME CATALINA_BASE CATALINA_TMPDIR
+JAVA_HOME= # determined later if empty
+JAVA_OPTS=-Djava.awt.headless=true
+JSP_COMPILER= # only used if nonempty
+SECURITY_MANAGER=false
+export JAVA_HOME JAVA_OPTS JSP_COMPILER SECURITY_MANAGER
+UMASK=022
+export UMASK
+# read options
+test -r /etc/default/tomcat9 && . /etc/default/tomcat9
+
+# ensure the temporary directory exist and change to it
+rm -rf "$CATALINA_TMPDIR"
+mkdir "$CATALINA_TMPDIR" || \
+    exit_failure_msg 'could not create JVM temporary directory'
+chown -h tomcat "$CATALINA_TMPDIR"
+cd "$CATALINA_TMPDIR"
+
+# figure out the JRE executable catalina.sh will use
+# (we need it for start-stop-daemon --exec for reliability)
+_RUNJAVA=$(su tomcat -s /bin/sh -c /usr/libexec/tomcat9/sysv-getjre.sh) || \
+    _RUNJAVA="FAIL:$?"
+case $_RUNJAVA in
+('OK<'*'>')
+	_RUNJAVA=${_RUNJAVA#'OK<'}
+	_RUNJAVA=${_RUNJAVA%'>'}
+	;;
+(*)
+	exit_failure_msg "could not determine JRE: $_RUNJAVA"
+	;;
+esac
+
+# prepare for actions
+case $1 in
+(start|stop|restart|force-reload)
+	# handled below
+	;;
+(try-restart|status)
+	start-stop-daemon --status --quiet \
+	    --pidfile /var/run/tomcat9.pid \
+	    --exec "$_RUNJAVA" --user tomcat
+	rv=$?
+	# clean up stale pidfile if necessary
+	(test x"$rv" = x"1" && rm -f /var/run/tomcat9.pid || :)
+	# process status result
+	case $1 in
+	(try-restart)
+		test x"$rv" = x"0" || {
+			# service is not running, or status is unknown
+			log_success_msg "$NAME is not running"
+			exit 0
+		}
+		# service running, restart it
+		;;
+	(status)
+		case $rv in
+		(0)
+			log_success_msg "$NAME is running"
+			;;
+		(4)
+			log_failure_msg "could not access PID file for $NAME"
+			;;
+		(*)
+			log_failure_msg "$NAME is not running"
+			;;
+		esac
+		exit $rv
+		;;
+	esac
+	;;
+(reload|*)
+	# not supported
+	echo >&2 "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
+	exit 3
+	;;
+esac
+
+# handle stopping/starting
+rv=0
+
+case $1 in
+(stop|restart|try-restart|force-reload)
+	test x"$VERBOSE" = x"no" || log_daemon_msg "Stopping $DESC"
+	start-stop-daemon --stop --quiet \
+	    --retry=10 --oknodo --remove-pidfile \
+	    --pidfile /var/run/tomcat9.pid \
+	    --exec "$_RUNJAVA" --user tomcat
+	rv=$?
+	test x"$VERBOSE" = x"no" || log_end_msg $rv
+	;;
+esac
+
+test x"$rv" = x"0" || exit $rv
+
+case $1 in
+(start|restart|try-restart|force-reload)
+	/usr/libexec/tomcat9/tomcat-update-policy.sh || \
+	    exit_failure_msg 'could not regenerating catalina.policy file'
+	rm -f /var/run/tomcat9.pid
+	test x"$VERBOSE" = x"no" || log_daemon_msg "Starting $DESC"
+	start-stop-daemon --start --quiet \
+	    --chuid tomcat --umask "$UMASK" \
+	    --startas /usr/libexec/tomcat9/sysv-start.sh \
+	    --background --make-pidfile \
+	    --pidfile /var/run/tomcat9.pid \
+	    --exec "$_RUNJAVA" --user tomcat
+	rv=$?
+	test x"$VERBOSE" = x"no" || log_end_msg $rv
+	;;
+esac
+
+exit $rv
diff --git a/debian/tomcat9.install b/debian/tomcat9.install
index f9fa6756..1daa7147 100644
--- a/debian/tomcat9.install
+++ b/debian/tomcat9.install
@@ -8,5 +8,6 @@ debian/default.template    /usr/share/tomcat9/
 debian/logrotate.template  /usr/share/tomcat9/
 debian/sysusers/*.conf     /usr/lib/sysusers.d/
 
+debian/libexec/sysv-*                  /usr/libexec/tomcat9/
 debian/libexec/tomcat-start.sh         /usr/libexec/tomcat9/
 debian/libexec/tomcat-update-policy.sh /usr/libexec/tomcat9/

This is the initscript itself and two helper scripts.
I managed to make the sysvinit scripts just call the systemd scripts,
so there is no duplication except where necessary (e.g. the sysvinit
script creates the temporary directory manually).

diff --git a/debian/copyright b/debian/copyright
index eace6038..8d605065 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -49,6 +49,7 @@ Copyright: 2008,2011, Canonical Ltd.
            2013-2014, Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
            2013-2018, Emmanuel Bourg <ebourg at apache.org>
            2001-2017, Markus Koschany <apo at debian.org>
+           2015–2019, mirabilos <t.glaser at tarent.de>
 License: Apache-2.0
 
 License: Apache-2.0
diff --git a/debian/changelog b/debian/changelog
index 9e1dab71..163eb8d9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+tomcat9 (9.0.16-4) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * debian/logging.properties: Add commented-out non-systemd configuration
+  * Make tomcat9 installable without systemd:
+    - Readd logic to create the system user via adduser
+    - Add sysvinit script, for init independence (Closes: #925473)
+  * debian/README.Debian: Document non-systemd risks
+  * debian/libexec/tomcat-locate-java.sh: Remove shebang and make
+    not executable as this is only ever sourced (makes no sense otherwise)
+  * Make the systemd startup script honour the (renamed) $SECURITY_MANAGER
+
+ -- Thorsten Glaser <tg at mirbsd.de>  Mon, 01 Apr 2019 15:42:02 +0200
+
 tomcat9 (9.0.16-3) unstable; urgency=medium
 
   * Removed read/write access to /var/lib/solr (Closes: #923299)

Metadata update.

bye,
//mirabilos
-- 
tarent solutions GmbH
Rochusstraße 2-4, D-53123 Bonn • http://www.tarent.de/
Tel: +49 228 54881-393 • Fax: +49 228 54881-235
HRB 5168 (AG Bonn) • USt-ID (VAT): DE122264941
Geschäftsführer: Dr. Stefan Barth, Kai Ebenrett, Boris Esser, Alexander Steeg

**********

Mit der tarent Academy bieten wir auch Trainings und Schulungen in den
Bereichen Softwareentwicklung, Agiles Arbeiten und Zukunftstechnologien an.

Besuchen Sie uns auf www.tarent.de/academy. Wir freuen uns auf Ihren Kontakt.

**********



More information about the pkg-java-maintainers mailing list