Hello,
I know Pat doesn't like suid binaries, nevertheless in the next Slackware release I would like to have mod_suexec enabled in the httpd package.
Sometimes it's invaluable to have scripts running as a separate user, especially with virtual hosts or at home. To be honest I'm addicted to it.
mod_suexec in itself is harmless, the nasty part is a setuid-root helper program whose only purpose is to run php and (f)cgi's setuid-some-user-not-apache.
Up until now I was rebuilding the httpd package every time an update came out (quick, no problem), another solution I tried was to build a separate package with just mod_suexec and the helper, but the helper had necessarily to go in usr/bin (making me prefer the full rebuild).
I think that a well planned build will not create security problems: mod_suexec will be disabled by default, and the nasty helper program will be installed 0755 outside $PATH reach.
Just like smbmnt and smnunmount it will require some competent work to get it going.
Here are my ideas for the patch against the 14.2 SlackBuild:
- By design mod_suexec doesn't load or refuses to work if its helper is not installed properly, nothing bad can happen just uncommenting LoadModule. To enable mod_suexec one should at least LoadModule mod_suexec AND configure suexec options AND chmod 04511 /usr/libexec/suexec (the helper).
- Most people may want to customize the helper, they will find its tiny source code in /usr/doc/httpd-*/suexec/).
- The real problem arises during upgrades. The new helper cannot overwrite the old one by default, or user customizatons will be lost. We can not afford to leave a old dangerous program unpatched either. So I came up with the idea of watermarking the helper. doinst.sh will overwrite the watermarked binary or it will warn the user to upgrade his own.
rc.httpd had a couple of problems:
- "restart" checks for misconfiguration and refuses to stop the daemon until all problems are fixed.
"graceful-restart" conversely does not check for misconfiguration and leaves the daemon unable to start until all problems are fixed.
these two commands should behave consistently. I made "graceful-restart" behave like "restart".
- "force-restart" sometimes fails, because "start" cannot bind the socket while some process is still dying.
"stop" now waits that all processes are stopped.
- I added ". /etc/default/httpd". As "$1" is passed along, /etc/default/httpd can set environment variables and ulimits for the daemon
I hope you will accept my proposals,
regards
Code:
#!/bin/sh
# workaround to patch gzipped files
gzip -d <doinst.sh.gz >doinst.sh
patch --strip=1 --verbose <"${0}"
gzip -9 <doinst.sh >doinst.sh.gz
tar c -z >suexec.tar.gz suexec/
rm -rf *.orig doinst.sh suexec
exit
diff -Naur httpd.old/doinst.sh httpd.new/doinst.sh
--- httpd.old/doinst.sh 2018-09-24 20:58:08.000000000 +0200
+++ httpd.new/doinst.sh 2018-10-22 12:00:00.000000000 +0200
@@ -66,3 +66,21 @@
done
config var/www/htdocs/index.html.new
+# This is a potentially nasty binary.
+# If it came from an official package it can be safely upgraded
+# (binutils can be missing, "strings" replaces "objdump -x")
+if strings usr/libexec/suexec | grep -Fqw Slackware_Upgradable_Helper ; then
+ preserve_perms usr/libexec/suexec.new
+else
+ config usr/libexec/suexec.new
+fi
+if [ -e usr/libexec/suexec.new ] ; then
+cat <<_EOF_
+
+WARNING: $ROOT/usr/libexec/suexec was not replaced!
+If you have made a custom suexec, please check if you need to upgrade it.
+Else, please delete the old suexec and replace it with suexec.new now!
+
+_EOF_
+fi
+
diff -Naur httpd.old/httpd.SlackBuild httpd.new/httpd.SlackBuild
--- httpd.old/httpd.SlackBuild 2018-09-24 21:02:21.000000000 +0200
+++ httpd.new/httpd.SlackBuild 2018-10-22 12:00:00.000000000 +0200
@@ -134,12 +134,33 @@
--enable-authnz-ldap \
--enable-authn-anon \
--enable-authn-alias \
+ --enable-suexec \
+ --with-suexec-uidmin=80 \
+ --with-suexec-gidmin=80 \
+ --with-suexec-caller=apache \
+ --with-suexec-bin=/usr/libexec/suexec \
+ --with-suexec-docroot=/var/www \
+ --with-suexec-logfile=/var/log/httpd/suexec_log \
+ --with-suexec-userdir=public_html \
--build=$ARCH-slackware-linux || exit 1
# Build and install:
make $NUMJOBS || make || exit 1
make install DESTDIR=$PKG || exit 1
+# A suid program designed to run other programs is potentially very dangerous.
+# Scrupulous people will have to manually chmod 04511 their /usr/libexec/suexec
+mkdir -p $PKG/usr/libexec/
+mv $PKG/usr/sbin/suexec $PKG/usr/libexec/suexec.new || exit 1
+chmod 0755 $PKG/usr/libexec/suexec.new || exit 1
+# During upgrades doinst.sh will be able to recognize this specific binary with
+# objdump -x usr/libexec/suexec | grep -Fqw Slackware_Upgradable_Helper
+objcopy $PKG/usr/libexec/suexec.new --add-section Slackware_Upgradable_Helper=/dev/null || exit 1
+# Let people tweak their /usr/libexec/suexec providing the source code
+mkdir -p $PKG/usr/doc/$PKGNAM-$VERSION/
+tar x -z -C $PKG/usr/doc/$PKGNAM-$VERSION/ <$CWD/suexec.tar.gz
+cp -a support/suexec.{c,h} $PKG/usr/doc/$PKGNAM-$VERSION/suexec/
+
rmdir $PKG/usr/bin
# Tweak default apache configuration
diff -Naur httpd.old/rc.httpd httpd.new/rc.httpd
--- httpd.old/rc.httpd 2012-05-16 22:56:13.000000000 +0200
+++ httpd.new/rc.httpd 2018-10-22 12:00:00.000000000 +0200
@@ -10,35 +10,40 @@
#
# For information on these options, "man apachectl".
-case "$1" in
- 'start')
- /usr/sbin/apachectl -k start
- ;;
- 'stop')
- /usr/sbin/apachectl -k stop
- killall httpd
- # Remove both old and new .pid locations:
- rm -f /var/run/httpd.pid /var/run/httpd/httpd.pid
- ;;
- 'force-restart')
+rc_httpd_stop()
+{
+ /usr/sbin/apachectl stop
+ for i in $(seq 1 10) ; do
+ /bin/killall -0 httpd 2>/dev/null || break
+ sleep .2
+ done
+ /bin/killall -9 httpd 2>/dev/null
+ # Remove both old and new .pid locations:
+ /bin/rm -f /var/run/httpd.pid /var/run/httpd/httpd.pid
+}
+rc_httpd_start()
+{
+ /usr/sbin/apachectl configtest >/dev/null || return
+ if [ "$1" = 'force-restart' ] ; then
# Because sometimes restarting through apachectl just doesn't do the trick...
- /usr/sbin/apachectl -k stop
- killall httpd
- # Remove both old and new .pid locations:
- rm -f /var/run/httpd.pid /var/run/httpd/httpd.pid
- /usr/sbin/apachectl -k start
- ;;
- 'restart')
- /usr/sbin/apachectl -k restart
+ rc_httpd_stop
+ fi
+ /usr/sbin/apachectl "${1/force-re/}"
+}
+
+test -s /etc/default/httpd && . /etc/default/httpd "$1"
+case "$1" in
+ (start|force-restart|graceful)
+ rc_httpd_start "$1"
;;
- 'graceful')
- /usr/sbin/apachectl -k graceful
+ (stop)
+ rc_httpd_stop
;;
- 'graceful-stop')
- /usr/sbin/apachectl -k graceful-stop
+ (configtest|graceful-stop|restart)
+ /usr/sbin/apachectl "$1"
;;
*)
- echo "Usage: $0 {start|stop|restart|graceful|graceful-stop}"
+ echo "Usage: $0 {start|stop|restart|force-restart|graceful|graceful-stop|configtest}"
;;
esac
diff -Naur httpd.old/suexec/Makefile httpd.new/suexec/Makefile
--- httpd.old/suexec/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ httpd.new/suexec/Makefile 2018-10-22 12:00:00.000000000 +0200
@@ -0,0 +1,16 @@
+BIN = $(patsubst %.c,%,$(wildcard *.c))
+BINDIR = /usr/libexec
+CFLAGS = -Wall -O2
+
+all: $(BIN)
+
+.PHONY: clean
+clean:
+ $(RM) $(BIN)
+
+install: $(BIN)
+ ginstall -d $(DESTDIR)/$(BINDIR)
+ ginstall -o root -g root -m 04511 -s $(^) $(DESTDIR)/$(BINDIR)
+
+%: %.c *.h
+ $(CC) $(CFLAGS) -I$(shell apxs -q APR_INCLUDEDIR) -I$(shell apxs -q exp_includedir) -o $(@) $(<) $(LDFLAGS)
diff -Naur httpd.old/suexec/README httpd.new/suexec/README
--- httpd.old/suexec/README 1970-01-01 01:00:00.000000000 +0100
+++ httpd.new/suexec/README 2018-10-22 12:00:00.000000000 +0200
@@ -0,0 +1,5 @@
+This directory contains the source code for Apache httpd mod_suexec helper program.
+If you need to tweak your suexec helper program
+- copy this directory somewhere else
+- customize ap_config.h
+- run "make install"
diff -Naur httpd.old/suexec/ap_config.h httpd.new/suexec/ap_config.h
--- httpd.old/suexec/ap_config.h 1970-01-01 01:00:00.000000000 +0100
+++ httpd.new/suexec/ap_config.h 2018-10-22 12:00:00.000000000 +0200
@@ -0,0 +1,25 @@
+#include <errno.h>
+#include "ap_config_auto.h"
+/*
+ #undef and (optionally) #define the identifiers you wish to change:
+ configure option identifier type
+ --with-suexec-bin SUEXEC_BIN char*
+ --with-suexec-caller AP_HTTPD_USER char*
+ --with-suexec-userdir AP_USERDIR_SUFFIX char*
+ --with-suexec-docroot AP_DOC_ROOT char*
+ --with-suexec-uidmin AP_UID_MIN uid_t
+ --with-suexec-gidmin AP_GID_MIN gid_t
+ --with-suexec-logfile AP_LOG_EXEC char*
+ --with-suexec-syslog AP_LOG_SYSLOG (undef/defined)
+ --with-suexec-safepath AP_SAFE_PATH (undef/defined)
+ --with-suexec-umask AP_SUEXEC_UMASK (undef/defined)
+
+ examples:
+ #undef AP_DOC_ROOT
+ #define AP_DOC_ROOT "/var/www"
+
+ #undef AP_UID_MIN
+ #define AP_UID_MIN 80
+
+ #undef AP_SUEXEC_UMASK
+*/