diff --git a/.fmf/version b/.fmf/version
deleted file mode 100644
index d00491f..0000000
--- a/.fmf/version
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/.gitignore b/.gitignore
index 8df7f18..4f0a93f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,28 +31,3 @@ x86_64
/httpd-*.tar.bz2
/httpd*.8
/results_httpd
-/htcacheclean.service.8
-/httpd.conf.5
-/httpd-2.4.41.tar.bz2.asc
-/apachectl.8
-/httpd-2.4.43.tar.bz2.asc
-/KEYS
-/httpd-2.4.46.tar.bz2.asc
-/httpd-2.4.48.tar.bz2.asc
-/httpd-2.4.49.tar.bz2.asc
-/httpd-2.4.50.tar.bz2.asc
-/httpd-2.4.51.tar.bz2.asc
-/httpd-2.4.52.tar.bz2.asc
-/httpd-2.4.53.tar.bz2.asc
-/httpd-2.4.54.tar.bz2.asc
-/httpd-2.4.55.tar.bz2.asc
-/httpd-2.4.56.tar.bz2.asc
-/httpd-2.4.57.tar.bz2.asc
-/httpd-2.4.58.tar.bz2.asc
-/httpd-2.4.59.tar.bz2.asc
-/httpd-2.4.61.tar.bz2.asc
-/httpd-2.4.62.tar.bz2.asc
-/httpd-2.4.63.tar.bz2.asc
-/httpd-2.4.64.tar.bz2.asc
-/httpd-2.4.65.tar.bz2.asc
-/httpd-2.4.66.tar.bz2.asc
diff --git a/00-base.conf b/00-base.conf
index bae2bf6..7cabce0 100644
--- a/00-base.conf
+++ b/00-base.conf
@@ -15,7 +15,6 @@ LoadModule authn_dbd_module modules/mod_authn_dbd.so
LoadModule authn_dbm_module modules/mod_authn_dbm.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_socache_module modules/mod_authn_socache.so
-LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_dbd_module modules/mod_authz_dbd.so
LoadModule authz_dbm_module modules/mod_authz_dbm.so
@@ -24,6 +23,7 @@ LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_owner_module modules/mod_authz_owner.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule brotli_module modules/mod_brotli.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
LoadModule cache_socache_module modules/mod_cache_socache.so
diff --git a/00-brotli.conf b/00-brotli.conf
deleted file mode 100644
index c2e0e9e..0000000
--- a/00-brotli.conf
+++ /dev/null
@@ -1 +0,0 @@
-LoadModule brotli_module modules/mod_brotli.so
diff --git a/00-mpm.conf b/00-mpm.conf
index a4a70b8..b15f913 100644
--- a/00-mpm.conf
+++ b/00-mpm.conf
@@ -1,5 +1,5 @@
# Select the MPM module which should be used by uncommenting exactly
-# one of the following LoadModule lines. See the httpd.conf(5) man
+# one of the following LoadModule lines. See the httpd.service(8) man
# page for more information on changing the MPM.
# prefork MPM: Implements a non-threaded, pre-forking web server
diff --git a/01-cgi.conf b/01-cgi.conf
index 4b680cf..5b8b936 100644
--- a/01-cgi.conf
+++ b/01-cgi.conf
@@ -2,7 +2,10 @@
# which has been configured in 00-mpm.conf. mod_cgid should be used
# with a threaded MPM; mod_cgi with the prefork MPM.
-
+
+ LoadModule cgid_module modules/mod_cgid.so
+
+
LoadModule cgid_module modules/mod_cgid.so
diff --git a/01-md.conf b/01-md.conf
new file mode 100644
index 0000000..2739202
--- /dev/null
+++ b/01-md.conf
@@ -0,0 +1 @@
+LoadModule md_module modules/mod_md.so
diff --git a/README.confd b/README.confd
index 6071deb..f5e9661 100644
--- a/README.confd
+++ b/README.confd
@@ -5,5 +5,5 @@ processed as httpd configuration files. The directory is used in
addition to the directory /etc/httpd/conf.modules.d/, which contains
configuration files necessary to load modules.
-Files are processed in sorted order. See httpd.conf(5) for more
-information.
+Files are processed in alphabetical order.
+
diff --git a/README.confmod b/README.confmod
index f4b055d..d33d1d4 100644
--- a/README.confmod
+++ b/README.confmod
@@ -6,5 +6,4 @@ configuration fragments necessary only to load modules.
Administrators should use the directory "/etc/httpd/conf.d" to modify
the configuration of httpd, or any modules.
-Files are processed in sorted order and should have a two digit
-numeric prefix. See httpd.conf(5) for more information.
+Files are processed in alphanumeric order.
diff --git a/action-configtest.sh b/action-configtest.sh
index 711d9cd..6685b0a 100644
--- a/action-configtest.sh
+++ b/action-configtest.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-exec /usr/sbin/httpd -t
+exec /sbin/apachectl configtest "$@"
diff --git a/action-graceful.sh b/action-graceful.sh
index 4976087..dc68b2e 100644
--- a/action-graceful.sh
+++ b/action-graceful.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-exec /sbin/apachectl graceful
+exec /sbin/apachectl graceful "$@"
diff --git a/apache-poweredby.png b/apache-poweredby.png
deleted file mode 100644
index 5663a23..0000000
Binary files a/apache-poweredby.png and /dev/null differ
diff --git a/apachectl.sh b/apachectl.sh
deleted file mode 100755
index 823db3b..0000000
--- a/apachectl.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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.
-
-###
-### NOTE: This is a replacement version of the "apachectl" script with
-### some differences in behaviour to the version distributed with
-### Apache httpd. Please read the apachectl(8) man page for more
-### information.
-###
-
-if [ "x$1" = "x-k" ]; then
- shift
-fi
-
-ACMD="$1"
-ARGV="$@"
-SVC='httpd.service'
-HTTPD='@HTTPDBIN@'
-
-if [ "x$2" != "x" ] ; then
- echo Passing arguments to httpd using apachectl is no longer supported.
- echo You can only start/stop/restart httpd using this script.
- echo To pass extra arguments to httpd, see the $SVC'(8)'
- echo man page.
- exit 1
-fi
-
-case $ACMD in
-start|stop|restart|status)
- /usr/bin/systemctl --no-pager $ACMD $SVC
- ERROR=$?
- ;;
-graceful)
- if /usr/bin/systemctl -q is-active $SVC; then
- /usr/bin/systemctl kill --signal=SIGUSR1 --kill-who=main $SVC
- else
- /usr/bin/systemctl start $SVC
- fi
- ERROR=$?
- ;;
-graceful-stop)
- /usr/bin/systemctl kill --signal=SIGWINCH --kill-who=main $SVC
- ERROR=$?
- ;;
-configtest|-t)
- $HTTPD -t
- ERROR=$?
- ;;
--v|-V)
- $HTTPD $ACMD
- ERROR=$?
- ;;
-*)
- echo apachectl: The \"$ACMD\" option is not supported. 1>&2
- ERROR=2
- ;;
-esac
-
-exit $ERROR
-
diff --git a/apachectl.xml b/apachectl.xml
deleted file mode 100644
index 217fbda..0000000
--- a/apachectl.xml
+++ /dev/null
@@ -1,192 +0,0 @@
-
-[
-
-]>
-
-
-
- apachectl
- httpd
- Apache man pageApache Software Foundation contributors
- Fedora man pageDanaFrank
-
-
-
- apachectl
- 8
-
-
-
- apachectl
- Server control interface for httpd
-
-
-
-
- apachectl
- command
-
-
-
-
-
-
- Description
-
- apachectl is a front end to the Apache HyperText
- Transfer Protocol (HTTP) server. It is designed to help the
- administrator control the functioning of the Apache
- httpd daemon.
-
- The apachectl script takes one-word arguments like
- ,
- , and
- , and translates them
- into appropriate signals to httpd.
-
- The apachectl script returns a 0 exit value on
- success, and >0 if an error occurs.
-
-
- Compatibility
-
- The version of apachectl used on this
- system is a replacement script intended to be mostly (but not
- completely) compatible with the version provided with
- Apache httpd. This
- apachectl mostly acts as a wrapper around
- systemctl and manipulates the
- systemd service for httpd.
- The interface to the Apache version of
- apachectl is described at .
-
- The following differences are present in the version of
- apachectl present on this system:
-
-
- Option arguments passed when starting
- httpd are not allowed. These should be
- configured in the systemd service directly (see httpd.service8).
-
- The "fullstatus" option is
- not available.
-
- The "status" option does
- not use or rely on the running server's
- server-status output.
-
-
-
-
-
-
-
- Options
-
-
-
-
- Start the Apache httpd daemon. Gives an error if it
- is already running. This is equivalent to systemctl start httpd.service.
-
-
-
-
-
-
- Stops the Apache httpd daemon. This is equivalent to
- systemctl stop httpd.service.
-
-
-
-
-
-
- Restarts the Apache httpd daemon. If the daemon is
- not running, it is started. This is equivalent
- to systemctl restart httpd.service.
-
-
-
-
-
-
- Displays a brief status report. This is equivalent to systemctl status httpd.service.
-
-
-
-
-
-
- Gracefully restarts the Apache httpd daemon. If the
- daemon is not running, it is started. This differs from a normal
- restart in that currently open connections are not aborted. A side
- effect is that old log files will not be closed immediately. This
- means that if used in a log rotation script, a substantial delay may
- be necessary to ensure that the old log files are closed before
- processing them. This is equivalent to
- systemctl kill --signal=SIGUSR1 --kill-who=main httpd.service.
-
-
-
-
-
-
- Gracefully stops the Apache httpd daemon.
- This differs from a normal stop in that currently open connections are not
- aborted. A side effect is that old log files will not be closed immediately.
- This is equivalent to
- systemctl kill --signal=SIGWINCH --kill-who=main httpd.service.
-
-
-
-
- |
-
- Run a configuration file syntax test. It parses the configuration
- files and either reports Syntax OK
- or detailed information about the particular syntax error. This is
- equivalent to httpd -t.
-
-
-
-
-
-
- Reporting Bugs
- Please report bugs by filing an issue in @BUG_REPORT_URL@.
-
-
-
- See also
-
-
- httpd8,
- httpd.conf5,
- systemd1,
- systemctl1,
- httpd.service8
-
-
-
-
diff --git a/ci.fmf b/ci.fmf
deleted file mode 100644
index c5aa0e0..0000000
--- a/ci.fmf
+++ /dev/null
@@ -1 +0,0 @@
-resultsdb-testcase: separate
diff --git a/config.layout b/config.layout
deleted file mode 100644
index 3a9f6c8..0000000
--- a/config.layout
+++ /dev/null
@@ -1,24 +0,0 @@
-# Layout used in Fedora httpd packaging.
-
- prefix: /etc/httpd
- localstatedir: /var
- exec_prefix: /usr
- bindir: ${exec_prefix}/bin
- sbindir: ${exec_prefix}/sbin
- libdir: ${exec_prefix}/lib
- libexecdir: ${exec_prefix}/libexec
- mandir: ${exec_prefix}/man
- sysconfdir: /etc/httpd/conf
- datadir: ${exec_prefix}/share/httpd
- installbuilddir: ${libdir}/httpd/build
- errordir: ${datadir}/error
- iconsdir: ${datadir}/icons
- htdocsdir: ${localstatedir}/www/html
- manualdir: ${datadir}/manual
- cgidir: ${localstatedir}/www/cgi-bin
- includedir: ${exec_prefix}/include/httpd
- runtimedir: ${prefix}/run
- logfiledir: ${localstatedir}/log/httpd
- statedir: ${prefix}/state
- proxycachedir: ${localstatedir}/cache/httpd/proxy
-
diff --git a/gating.yaml b/gating.yaml
deleted file mode 100644
index fb11fa9..0000000
--- a/gating.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
---- !Policy
-product_versions:
- - fedora-*
-decision_contexts: [bodhi_update_push_testing]
-subject_type: koji_build
-rules:
- - !PassingTestCaseRule {test_case_name: fedora-ci.koji-build./plans/tier1-public.functional}
-
-#gating rawhide
---- !Policy
-product_versions:
- - fedora-*
-decision_contexts: [bodhi_update_push_stable]
-subject_type: koji_build
-rules:
- - !PassingTestCaseRule {test_case_name: fedora-ci.koji-build./plans/tier1-public.functional}
-
-#gating rhel
---- !Policy
-product_versions:
- - rhel-*
-decision_context: osci_compose_gate
-rules:
- - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional}
- - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier2.functional}
- - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier3.functional}
- - !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-internal.functional}
diff --git a/htcacheclean.service b/htcacheclean.service
index e3eeef9..166067b 100644
--- a/htcacheclean.service
+++ b/htcacheclean.service
@@ -1,16 +1,10 @@
[Unit]
-Description=Disk Cache Cleaning Daemon for the Apache HTTP Server
+Description=Disk Cache Cleaning Daemon for Apache HTTP Server
After=httpd.service
-Documentation=man:htcacheclean.service(8)
[Service]
Type=forking
User=apache
PIDFile=/run/httpd/htcacheclean/pid
-Environment=LANG=C
EnvironmentFile=/etc/sysconfig/htcacheclean
ExecStart=/usr/sbin/htcacheclean -P /run/httpd/htcacheclean/pid -d $INTERVAL -p $CACHE_ROOT -l $LIMIT $OPTIONS
-PrivateTmp=true
-
-[Install]
-WantedBy=multi-user.target
diff --git a/htcacheclean.service.xml b/htcacheclean.service.xml
deleted file mode 100644
index c2a98d1..0000000
--- a/htcacheclean.service.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
- htcacheclean systemd unit
- httpd
- AuthorOrtonJoejorton@redhat.com
-
-
-
- htcacheclean.service
- 8
-
-
-
- htcacheclean.service
- htcacheclean unit file for systemd
-
-
-
-
- /usr/lib/systemd/system/htcacheclean.service
-
-
-
-
- Description
-
- This manual page describes the systemd
- unit file for the htcacheclean daemon. This
- unit file provides a service which runs
- htcacheclean in daemon mode,
- periodically cleaning the disk cache root to ensure disk space
- usage is within configured limits.
-
-
-
-
- Options
-
- The service is configured by configuration file
- /etc/sysconfig/htcacheclean. The following
- variables are used, following standard systemd
- EnvironmentFile= syntax:
-
-
-
- INTERVAL=
-
- Sets the interval between cache clean runs, in
- minutes. By default this is configured as
- 15.
-
-
-
- CACHE_ROOT=
-
- Sets the directory name used for the cache
- root. By default this is configured as
- /var/cache/httpd/proxy.
-
-
-
- LIMIT=
-
- Sets the total disk cache space limit, in
- bytes. Use a K or M
- suffix to signify kilobytes or megabytes. By default this is
- set to 100M.
-
-
-
- OPTIONS=
-
- Any other options to pass to
- htcacheclean.
-
-
-
-
-
- Files
-
- /usr/lib/systemd/system/htcacheclean.service,
- /etc/sysconfig/htcacheclean
-
-
-
- Reporting Bugs
- Please report bugs by filing an issue in @BUG_REPORT_URL@.
-
-
-
- See also
-
-
- htcacheclean8,
- httpd8,
- httpd.service8,
- systemd.exec8
-
-
-
-
-
-
diff --git a/httpd-2.4.1-apctl.patch b/httpd-2.4.1-apctl.patch
new file mode 100644
index 0000000..b31c3c5
--- /dev/null
+++ b/httpd-2.4.1-apctl.patch
@@ -0,0 +1,94 @@
+
+- fail gracefully if links is not installed on target system
+- source sysconfig/httpd for custom env. vars etc.
+- make httpd -t work even in SELinux
+- pass $OPTIONS to all $HTTPD invocation
+
+Upstream-HEAD: vendor
+Upstream-2.0: vendor
+Upstream-Status: Vendor-specific changes for better initscript integration
+
+--- httpd-2.4.1/support/apachectl.in.apctl
++++ httpd-2.4.1/support/apachectl.in
+@@ -44,19 +44,25 @@ ARGV="$@"
+ # the path to your httpd binary, including options if necessary
+ HTTPD='@exp_sbindir@/@progname@'
+ #
+-# pick up any necessary environment variables
+-if test -f @exp_sbindir@/envvars; then
+- . @exp_sbindir@/envvars
+-fi
+ #
+ # a command that outputs a formatted text version of the HTML at the
+ # url given on the command line. Designed for lynx, however other
+ # programs may work.
+-LYNX="@LYNX_PATH@ -dump"
++if [ -x "@LYNX_PATH@" ]; then
++ LYNX="@LYNX_PATH@ -dump"
++else
++ LYNX=none
++fi
+ #
+ # the URL to your server's mod_status status page. If you do not
+ # have one, then status and fullstatus will not work.
+ STATUSURL="http://localhost:@PORT@/server-status"
++
++# Source /etc/sysconfig/httpd for $HTTPD setting, etc.
++if [ -r /etc/sysconfig/httpd ]; then
++ . /etc/sysconfig/httpd
++fi
++
+ #
+ # Set this variable to a command that increases the maximum
+ # number of file descriptors allowed per child process. This is
+@@ -76,9 +82,27 @@ if [ "x$ARGV" = "x" ] ; then
+ ARGV="-h"
+ fi
+
++function checklynx() {
++if [ "$LYNX" = "none" ]; then
++ echo "The 'links' package is required for this functionality."
++ exit 8
++fi
++}
++
++function testconfig() {
++# httpd is denied terminal access in SELinux, so run in the
++# current context to get stdout from $HTTPD -t.
++if test -x /usr/sbin/selinuxenabled && /usr/sbin/selinuxenabled; then
++ runcon -- `id -Z` $HTTPD $OPTIONS -t
++else
++ $HTTPD $OPTIONS -t
++fi
++ERROR=$?
++}
++
+ case $ACMD in
+ start|stop|restart|graceful|graceful-stop)
+- $HTTPD -k $ARGV
++ $HTTPD $OPTIONS -k $ARGV
+ ERROR=$?
+ ;;
+ startssl|sslstart|start-SSL)
+@@ -88,17 +112,18 @@ startssl|sslstart|start-SSL)
+ ERROR=2
+ ;;
+ configtest)
+- $HTTPD -t
+- ERROR=$?
++ testconfig
+ ;;
+ status)
++ checklynx
+ $LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
+ ;;
+ fullstatus)
++ checklynx
+ $LYNX $STATUSURL
+ ;;
+ *)
+- $HTTPD "$@"
++ $HTTPD $OPTIONS "$@"
+ ERROR=$?
+ esac
+
diff --git a/httpd-2.4.43-corelimit.patch b/httpd-2.4.1-corelimit.patch
similarity index 72%
rename from httpd-2.4.43-corelimit.patch
rename to httpd-2.4.1-corelimit.patch
index 8c9899c..96f8486 100644
--- a/httpd-2.4.43-corelimit.patch
+++ b/httpd-2.4.1-corelimit.patch
@@ -1,11 +1,13 @@
-Upstream-Status: local customisation
+Bump up the core size limit if CoreDumpDirectory is
+configured.
-diff --git a/server/core.c b/server/core.c
-index 79b2a82..dc0f17a 100644
---- a/server/core.c
-+++ b/server/core.c
-@@ -4996,6 +4996,25 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte
+Upstream-Status: Was discussed but there are competing desires;
+ there are portability oddities here too.
+
+--- httpd-2.4.1/server/core.c.corelimit
++++ httpd-2.4.1/server/core.c
+@@ -4433,6 +4433,25 @@ static int core_post_config(apr_pool_t *
}
apr_pool_cleanup_register(pconf, NULL, ap_mpm_end_gen_helper,
apr_pool_cleanup_null);
diff --git a/httpd-2.4.43-deplibs.patch b/httpd-2.4.1-deplibs.patch
similarity index 68%
rename from httpd-2.4.43-deplibs.patch
rename to httpd-2.4.1-deplibs.patch
index 85b65dc..b73c21d 100644
--- a/httpd-2.4.43-deplibs.patch
+++ b/httpd-2.4.1-deplibs.patch
@@ -1,11 +1,11 @@
-Upstream-Status: local customisation, not needed upstream
+Link straight against .la files.
-diff --git a/configure.in b/configure.in
-index f8f9442..f276550 100644
---- a/configure.in
-+++ b/configure.in
-@@ -786,9 +786,9 @@ APACHE_SUBST(INSTALL_SUEXEC)
+Upstream-Status: vendor specific
+
+--- httpd-2.4.1/configure.in.deplibs
++++ httpd-2.4.1/configure.in
+@@ -707,9 +707,9 @@ APACHE_HELP_STRING(--with-suexec-umask,u
dnl APR should go after the other libs, so the right symbols can be picked up
if test x${apu_found} != xobsolete; then
diff --git a/httpd-2.4.17-socket-activation.patch b/httpd-2.4.17-socket-activation.patch
new file mode 100644
index 0000000..dbdd80c
--- /dev/null
+++ b/httpd-2.4.17-socket-activation.patch
@@ -0,0 +1,300 @@
+diff --git a/server/listen.c b/server/listen.c
+index a8e9e6f..1a6c1d3 100644
+--- a/server/listen.c
++++ b/server/listen.c
+@@ -34,6 +34,10 @@
+ #include
+ #endif
+
++#ifdef HAVE_SYSTEMD
++#include
++#endif
++
+ /* we know core's module_index is 0 */
+ #undef APLOG_MODULE_INDEX
+ #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
+@@ -59,9 +63,12 @@ static int ap_listenbacklog;
+ static int ap_listencbratio;
+ static int send_buffer_size;
+ static int receive_buffer_size;
++#ifdef HAVE_SYSTEMD
++static int use_systemd = -1;
++#endif
+
+ /* TODO: make_sock is just begging and screaming for APR abstraction */
+-static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
++static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server, int do_bind_listen)
+ {
+ apr_socket_t *s = server->sd;
+ int one = 1;
+@@ -94,20 +101,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
+ return stat;
+ }
+
+-#if APR_HAVE_IPV6
+- if (server->bind_addr->family == APR_INET6) {
+- stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
+- if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
+- ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00069)
+- "make_sock: for address %pI, apr_socket_opt_set: "
+- "(IPV6_V6ONLY)",
+- server->bind_addr);
+- apr_socket_close(s);
+- return stat;
+- }
+- }
+-#endif
+-
+ /*
+ * To send data over high bandwidth-delay connections at full
+ * speed we must force the TCP window to open wide enough to keep the
+@@ -169,21 +162,37 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
+ }
+ #endif
+
+- if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
+- ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072)
+- "make_sock: could not bind to address %pI",
+- server->bind_addr);
+- apr_socket_close(s);
+- return stat;
+- }
++ if (do_bind_listen) {
++#if APR_HAVE_IPV6
++ if (server->bind_addr->family == APR_INET6) {
++ stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
++ if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00069)
++ "make_sock: for address %pI, apr_socket_opt_set: "
++ "(IPV6_V6ONLY)",
++ server->bind_addr);
++ apr_socket_close(s);
++ return stat;
++ }
++ }
++#endif
+
+- if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
+- ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073)
+- "make_sock: unable to listen for connections "
+- "on address %pI",
+- server->bind_addr);
+- apr_socket_close(s);
+- return stat;
++ if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
++ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072)
++ "make_sock: could not bind to address %pI",
++ server->bind_addr);
++ apr_socket_close(s);
++ return stat;
++ }
++
++ if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
++ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073)
++ "make_sock: unable to listen for connections "
++ "on address %pI",
++ server->bind_addr);
++ apr_socket_close(s);
++ return stat;
++ }
+ }
+
+ #ifdef WIN32
+@@ -315,6 +324,123 @@ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to,
+ return found;
+ }
+
++#ifdef HAVE_SYSTEMD
++
++static int find_systemd_socket(process_rec * process, apr_port_t port) {
++ int fdcount, fd;
++ int sdc = sd_listen_fds(0);
++
++ if (sdc < 0) {
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, sdc, process->pool, APLOGNO(02486)
++ "find_systemd_socket: Error parsing enviroment, sd_listen_fds returned %d",
++ sdc);
++ return -1;
++ }
++
++ if (sdc == 0) {
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, sdc, process->pool, APLOGNO(02487)
++ "find_systemd_socket: At least one socket must be set.");
++ return -1;
++ }
++
++ fdcount = atoi(getenv("LISTEN_FDS"));
++ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fdcount; fd++) {
++ if (sd_is_socket_inet(fd, 0, 0, -1, port) > 0) {
++ return fd;
++ }
++ }
++
++ return -1;
++}
++
++static apr_status_t alloc_systemd_listener(process_rec * process,
++ int fd, const char *proto,
++ ap_listen_rec **out_rec)
++{
++ apr_status_t rv;
++ struct sockaddr sa;
++ socklen_t len = sizeof(struct sockaddr);
++ apr_os_sock_info_t si;
++ ap_listen_rec *rec;
++ *out_rec = NULL;
++
++ memset(&si, 0, sizeof(si));
++
++ rv = getsockname(fd, &sa, &len);
++
++ if (rv != 0) {
++ rv = apr_get_netos_error();
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02489)
++ "getsockname on %d failed.", fd);
++ return rv;
++ }
++
++ si.os_sock = &fd;
++ si.family = sa.sa_family;
++ si.local = &sa;
++ si.type = SOCK_STREAM;
++ si.protocol = APR_PROTO_TCP;
++
++ rec = apr_palloc(process->pool, sizeof(ap_listen_rec));
++ rec->active = 0;
++ rec->next = 0;
++
++
++ rv = apr_os_sock_make(&rec->sd, &si, process->pool);
++ if (rv != APR_SUCCESS) {
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02490)
++ "apr_os_sock_make on %d failed.", fd);
++ return rv;
++ }
++
++ rv = apr_socket_addr_get(&rec->bind_addr, APR_LOCAL, rec->sd);
++ if (rv != APR_SUCCESS) {
++ ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02491)
++ "apr_socket_addr_get on %d failed.", fd);
++ return rv;
++ }
++
++ rec->protocol = apr_pstrdup(process->pool, proto);
++
++ *out_rec = rec;
++
++ return make_sock(process->pool, rec, 0);
++}
++
++static const char *set_systemd_listener(process_rec *process, apr_port_t port,
++ const char *proto)
++{
++ ap_listen_rec *last, *new;
++ apr_status_t rv;
++ int fd = find_systemd_socket(process, port);
++ if (fd < 0) {
++ return "Systemd socket activation is used, but this port is not "
++ "configured in systemd";
++ }
++
++ last = ap_listeners;
++ while (last && last->next) {
++ last = last->next;
++ }
++
++ rv = alloc_systemd_listener(process, fd, proto, &new);
++ if (rv != APR_SUCCESS) {
++ return "Failed to setup socket passed by systemd using socket activation";
++ }
++
++ if (last == NULL) {
++ ap_listeners = last = new;
++ }
++ else {
++ last->next = new;
++ last = new;
++ }
++
++ return NULL;
++}
++
++#endif /* HAVE_SYSTEMD */
++
+ static const char *alloc_listener(process_rec *process, const char *addr,
+ apr_port_t port, const char* proto,
+ void *slave)
+@@ -495,7 +621,7 @@ static int open_listeners(apr_pool_t *pool)
+ }
+ }
+ #endif
+- if (make_sock(pool, lr) == APR_SUCCESS) {
++ if (make_sock(pool, lr, 1) == APR_SUCCESS) {
+ ++num_open;
+ }
+ else {
+@@ -607,8 +733,28 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
+ }
+ }
+
+- if (open_listeners(s->process->pool)) {
+- return 0;
++#ifdef HAVE_SYSTEMD
++ if (use_systemd) {
++ const char *userdata_key = "ap_open_systemd_listeners";
++ void *data;
++ /* clear the enviroment on our second run
++ * so that none of our future children get confused.
++ */
++ apr_pool_userdata_get(&data, userdata_key, s->process->pool);
++ if (!data) {
++ apr_pool_userdata_set((const void *)1, userdata_key,
++ apr_pool_cleanup_null, s->process->pool);
++ }
++ else {
++ sd_listen_fds(1);
++ }
++ }
++ else
++#endif
++ {
++ if (open_listeners(s->process->pool)) {
++ return 0;
++ }
+ }
+
+ for (lr = ap_listeners; lr; lr = lr->next) {
+@@ -698,7 +844,7 @@ AP_DECLARE(apr_status_t) ap_duplicate_listeners(apr_pool_t *p, server_rec *s,
+ duplr->bind_addr);
+ return stat;
+ }
+- make_sock(p, duplr);
++ make_sock(p, duplr, 1);
+ #if AP_NONBLOCK_WHEN_MULTI_LISTEN
+ use_nonblock = (ap_listeners && ap_listeners->next);
+ stat = apr_socket_opt_set(duplr->sd, APR_SO_NONBLOCK, use_nonblock);
+@@ -825,6 +971,11 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
+ if (argc < 1 || argc > 2) {
+ return "Listen requires 1 or 2 arguments.";
+ }
++#ifdef HAVE_SYSTEMD
++ if (use_systemd == -1) {
++ use_systemd = sd_listen_fds(0) > 0;
++ }
++#endif
+
+ rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
+ if (rv != APR_SUCCESS) {
+@@ -856,6 +1007,12 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
+ ap_str_tolower(proto);
+ }
+
++#ifdef HAVE_SYSTEMD
++ if (use_systemd) {
++ return set_systemd_listener(cmd->server->process, port, proto);
++ }
++#endif
++
+ return alloc_listener(cmd->server->process, host, port, proto, NULL);
+ }
+
diff --git a/httpd-2.4.2-icons.patch b/httpd-2.4.2-icons.patch
new file mode 100644
index 0000000..1341999
--- /dev/null
+++ b/httpd-2.4.2-icons.patch
@@ -0,0 +1,26 @@
+
+- Fix config for /icons/ dir to allow symlink to poweredby.png.
+- Avoid using coredump GIF for a directory called "core"
+
+Upstream-Status: vendor specific patch
+
+--- httpd-2.4.2/docs/conf/extra/httpd-autoindex.conf.in.icons
++++ httpd-2.4.2/docs/conf/extra/httpd-autoindex.conf.in
+@@ -21,7 +21,7 @@ IndexOptions FancyIndexing HTMLTable Ver
+ Alias /icons/ "@exp_iconsdir@/"
+
+
+- Options Indexes MultiViews
++ Options Indexes MultiViews FollowSymlinks
+ AllowOverride None
+ Require all granted
+
+@@ -53,7 +53,7 @@ AddIcon /icons/dvi.gif .dvi
+ AddIcon /icons/uuencoded.gif .uu
+ AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+ AddIcon /icons/tex.gif .tex
+-AddIcon /icons/bomb.gif core
++AddIcon /icons/bomb.gif core.
+
+ AddIcon /icons/back.gif ..
+ AddIcon /icons/hand.right.gif README
diff --git a/httpd-2.4.25-detect-systemd.patch b/httpd-2.4.25-detect-systemd.patch
new file mode 100644
index 0000000..f8e302b
--- /dev/null
+++ b/httpd-2.4.25-detect-systemd.patch
@@ -0,0 +1,75 @@
+diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
+diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
+diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
+--- httpd-2.4.25/acinclude.m4.detectsystemd
++++ httpd-2.4.25/acinclude.m4
+@@ -604,6 +604,30 @@
+ fi
+ ])
+
++AC_DEFUN(APACHE_CHECK_SYSTEMD, [
++dnl Check for systemd support for listen.c's socket activation.
++case $host in
++*-linux-*)
++ if test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd; then
++ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd`
++ elif test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd-daemon; then
++ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd-daemon`
++ else
++ AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon")
++ fi
++ if test -n "$SYSTEMD_LIBS"; then
++ AC_CHECK_HEADERS(systemd/sd-daemon.h)
++ if test "${ac_cv_header_systemd_sd_daemon_h}" = "no" || test -z "${SYSTEMD_LIBS}"; then
++ AC_MSG_WARN([Your system does not support systemd.])
++ else
++ APR_ADDTO(HTTPD_LIBS, [$SYSTEMD_LIBS])
++ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is supported])
++ fi
++ fi
++ ;;
++esac
++])
++
+ dnl
+ dnl APACHE_EXPORT_ARGUMENTS
+ dnl Export (via APACHE_SUBST) the various path-related variables that
+diff -uap httpd-2.4.25/configure.in.detectsystemd httpd-2.4.25/configure.in
+--- httpd-2.4.25/configure.in.detectsystemd
++++ httpd-2.4.25/configure.in
+@@ -234,6 +234,7 @@
+ AC_MSG_NOTICE([Using external PCRE library from $PCRE_CONFIG])
+ APR_ADDTO(PCRE_INCLUDES, [`$PCRE_CONFIG --cflags`])
+ APR_ADDTO(PCRE_LIBS, [`$PCRE_CONFIG --libs`])
++ APR_ADDTO(HTTPD_LIBS, [\$(PCRE_LIBS)])
+ else
+ AC_MSG_ERROR([pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/])
+ fi
+@@ -504,6 +510,8 @@
+ AC_DEFINE(HAVE_GMTOFF, 1, [Define if struct tm has a tm_gmtoff field])
+ fi
+
++APACHE_CHECK_SYSTEMD
++
+ dnl ## Set up any appropriate OS-specific environment variables for apachectl
+
+ case $host in
+@@ -668,6 +676,7 @@
+ APACHE_SUBST(BUILTIN_LIBS)
+ APACHE_SUBST(SHLIBPATH_VAR)
+ APACHE_SUBST(OS_SPECIFIC_VARS)
++APACHE_SUBST(HTTPD_LIBS)
+
+ PRE_SHARED_CMDS='echo ""'
+ POST_SHARED_CMDS='echo ""'
+--- httpd-2.4.25/Makefile.in.detectsystemd
++++ httpd-2.4.25/Makefile.in
+@@ -4,7 +4,7 @@
+
+ PROGRAM_NAME = $(progname)
+ PROGRAM_SOURCES = modules.c
+-PROGRAM_LDADD = buildmark.o $(HTTPD_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(PCRE_LIBS) $(EXTRA_LIBS) $(AP_LIBS) $(LIBS)
++PROGRAM_LDADD = buildmark.o $(HTTPD_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(HTTPD_LIBS) $(EXTRA_LIBS) $(AP_LIBS) $(LIBS)
+ PROGRAM_PRELINK = $(COMPILE) -c $(top_srcdir)/server/buildmark.c
+ PROGRAM_DEPENDENCIES = \
+ server/libmain.la \
diff --git a/httpd-2.4.25-selinux.patch b/httpd-2.4.25-selinux.patch
new file mode 100644
index 0000000..fa4614a
--- /dev/null
+++ b/httpd-2.4.25-selinux.patch
@@ -0,0 +1,61 @@
+
+Log the SELinux context at startup.
+
+Upstream-Status: unlikely to be any interest in this upstream
+
+--- httpd-2.4.1/configure.in.selinux
++++ httpd-2.4.1/configure.in
+@@ -458,6 +458,11 @@ fopen64
+ dnl confirm that a void pointer is large enough to store a long integer
+ APACHE_CHECK_VOID_PTR_LEN
+
++AC_CHECK_LIB(selinux, is_selinux_enabled, [
++ AC_DEFINE(HAVE_SELINUX, 1, [Defined if SELinux is supported])
++ APR_ADDTO(HTTPD_LIBS, [-lselinux])
++])
++
+ AC_CACHE_CHECK([for gettid()], ac_cv_gettid,
+ [AC_TRY_RUN(#define _GNU_SOURCE
+ #include
+--- httpd-2.4.1/server/core.c.selinux
++++ httpd-2.4.1/server/core.c
+@@ -58,6 +58,10 @@
+ #include
+ #endif
+
++#ifdef HAVE_SELINUX
++#include
++#endif
++
+ /* LimitRequestBody handling */
+ #define AP_LIMIT_REQ_BODY_UNSET ((apr_off_t) -1)
+ #define AP_DEFAULT_LIMIT_REQ_BODY ((apr_off_t) 0)
+@@ -4452,6 +4456,28 @@ static int core_post_config(apr_pool_t *
+ }
+ #endif
+
++#ifdef HAVE_SELINUX
++ {
++ static int already_warned = 0;
++ int is_enabled = is_selinux_enabled() > 0;
++
++ if (is_enabled && !already_warned) {
++ security_context_t con;
++
++ if (getcon(&con) == 0) {
++
++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
++ "SELinux policy enabled; "
++ "httpd running as context %s", con);
++
++ already_warned = 1;
++
++ freecon(con);
++ }
++ }
++ }
++#endif
++
+ return OK;
+ }
+
diff --git a/httpd-2.4.3-apctl-systemd.patch b/httpd-2.4.3-apctl-systemd.patch
new file mode 100644
index 0000000..c6bf5da
--- /dev/null
+++ b/httpd-2.4.3-apctl-systemd.patch
@@ -0,0 +1,51 @@
+
+Make apachectl run via systemctl.
+
+Note: "apachectl graceful" is documented to start httpd if not running.
+
+Upstream-Status: vendor specific patch
+
+--- httpd-2.4.18/support/apachectl.in.apctlsystemd
++++ httpd-2.4.18/support/apachectl.in
+@@ -100,9 +100,28 @@ fi
+ ERROR=$?
+ }
+
++if [ "x$2" != "x" ] ; then
++ echo Passing arguments to httpd using apachectl is no longer supported.
++ echo You can only start/stop/restart httpd using this script.
++ echo If you want to pass extra arguments to httpd, edit the
++ echo /etc/sysconfig/httpd config file.
++fi
++
+ case $ACMD in
+-start|stop|restart|graceful|graceful-stop)
+- $HTTPD $OPTIONS -k $ARGV
++start|stop|restart|status)
++ /usr/bin/systemctl $ACMD httpd.service
++ ERROR=$?
++ ;;
++graceful)
++ if /usr/bin/systemctl -q is-active httpd.service; then
++ /usr/bin/systemctl reload httpd.service
++ else
++ /usr/bin/systemctl start httpd.service
++ fi
++ ERROR=$?
++ ;;
++graceful-stop)
++ /usr/bin/systemctl stop httpd.service
+ ERROR=$?
+ ;;
+ startssl|sslstart|start-SSL)
+@@ -114,10 +133,6 @@ startssl|sslstart|start-SSL)
+ configtest)
+ testconfig
+ ;;
+-status)
+- checklynx
+- $LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
+- ;;
+ fullstatus)
+ checklynx
+ $LYNX $STATUSURL
diff --git a/httpd-2.4.33-export.patch b/httpd-2.4.33-export.patch
new file mode 100644
index 0000000..9adf398
--- /dev/null
+++ b/httpd-2.4.33-export.patch
@@ -0,0 +1,20 @@
+
+There is no need to "suck in" the apr/apr-util symbols when using
+a shared libapr{,util}, it just bloats the symbol table; so don't.
+
+Upstream-HEAD: needed
+Upstream-2.0: omit
+Upstream-Status: EXPORT_DIRS change is conditional on using shared apr
+
+--- httpd-2.4.33/server/Makefile.in.export
++++ httpd-2.4.33/server/Makefile.in
+@@ -60,9 +60,6 @@
+ ls $$dir/*.h ; \
+ done; \
+ echo "$(top_srcdir)/server/mpm_fdqueue.h"; \
+- for dir in $(EXPORT_DIRS_APR); do \
+- ls $$dir/ap[ru].h $$dir/ap[ru]_*.h 2>/dev/null; \
+- done; \
+ ) | sed -e s,//,/,g | sort -u > $@
+
+ exports.c: export_files
diff --git a/httpd-2.4.33-mddefault.patch b/httpd-2.4.33-mddefault.patch
new file mode 100644
index 0000000..9e82fb8
--- /dev/null
+++ b/httpd-2.4.33-mddefault.patch
@@ -0,0 +1,21 @@
+
+Override default.
+
+--- httpd-2.4.33/modules/md/mod_md_config.c.mddefault
++++ httpd-2.4.33/modules/md/mod_md_config.c
+@@ -54,10 +54,14 @@
+
+ #define DEF_VAL (-1)
+
++#ifndef MD_DEFAULT_STORE_DIR
++#define MD_DEFAULT_STORE_DIR "state/md"
++#endif
++
+ /* Default settings for the global conf */
+ static md_mod_conf_t defmc = {
+ NULL,
+- "md",
++ MD_DEFAULT_STORE_DIR,
+ NULL,
+ NULL,
+ 80,
diff --git a/httpd-2.4.33-sslmultiproxy.patch b/httpd-2.4.33-sslmultiproxy.patch
new file mode 100644
index 0000000..679f229
--- /dev/null
+++ b/httpd-2.4.33-sslmultiproxy.patch
@@ -0,0 +1,126 @@
+From ce2d1d7d4b2bebe34cf37fdeb30d35050092c5b5 Mon Sep 17 00:00:00 2001
+From: Rob Crittenden
+Date: Thu, 12 Apr 2018 14:36:28 -0400
+Subject: [PATCH] httpd-2.4.18-sslmultiproxy.patch
+
+---
+ modules/ssl/mod_ssl.c | 24 ++++++++++++++++++++++--
+ modules/ssl/ssl_engine_vars.c | 18 +++++++++++++++++-
+ 2 files changed, 39 insertions(+), 3 deletions(-)
+
+diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
+index 48d64cb..42e85a3 100644
+diff -uap httpd-2.4.33/modules/ssl/mod_ssl.c.sslmultiproxy httpd-2.4.33/modules/ssl/mod_ssl.c
+--- httpd-2.4.33/modules/ssl/mod_ssl.c.sslmultiproxy
++++ httpd-2.4.33/modules/ssl/mod_ssl.c
+@@ -444,12 +444,19 @@
+ return OK;
+ }
+
++static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *othermod_engine_disable;
++static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *othermod_engine_set;
++
+ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
+ ap_conf_vector_t *per_dir_config)
+ {
+ SSLConnRec *sslconn = myConnConfig(c);
+ SSLSrvConfigRec *sc;
+
++ if (othermod_engine_disable) {
++ othermod_engine_disable(c);
++ }
++
+ if (sslconn) {
+ return sslconn;
+ }
+@@ -508,6 +515,10 @@
+ {
+ SSLConnRec *sslconn;
+ int status;
++
++ if (othermod_engine_set) {
++ return othermod_engine_set(c, per_dir_config, proxy, enable);
++ }
+
+ if (proxy) {
+ sslconn = ssl_init_connection_ctx(c, per_dir_config);
+@@ -537,12 +548,18 @@
+
+ static int ssl_proxy_enable(conn_rec *c)
+ {
+- return ssl_engine_set(c, NULL, 1, 1);
++ if (othermod_engine_set)
++ return othermod_engine_set(c, NULL, 1, 1);
++ else
++ return ssl_engine_set(c, NULL, 1, 1);
+ }
+
+ static int ssl_engine_disable(conn_rec *c)
+ {
+- return ssl_engine_set(c, NULL, 0, 0);
++ if (othermod_engine_set)
++ return othermod_engine_set(c, NULL, 0, 0);
++ else
++ return ssl_engine_set(c, NULL, 0, 0);
+ }
+
+ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
+@@ -730,6 +747,9 @@
+ APR_HOOK_MIDDLE);
+
+ ssl_var_register(p);
++
++ othermod_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
++ othermod_engine_set = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set);
+
+ APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
+ APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
+diff -uap httpd-2.4.33/modules/ssl/ssl_engine_vars.c.sslmultiproxy httpd-2.4.33/modules/ssl/ssl_engine_vars.c
+--- httpd-2.4.33/modules/ssl/ssl_engine_vars.c.sslmultiproxy
++++ httpd-2.4.33/modules/ssl/ssl_engine_vars.c
+@@ -54,6 +54,8 @@
+ static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
+ static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var);
+ static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
++static APR_OPTIONAL_FN_TYPE(ssl_is_https) *othermod_is_https;
++static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *othermod_var_lookup;
+
+ static SSLConnRec *ssl_get_effective_config(conn_rec *c)
+ {
+@@ -68,7 +70,9 @@
+ static int ssl_is_https(conn_rec *c)
+ {
+ SSLConnRec *sslconn = ssl_get_effective_config(c);
+- return sslconn && sslconn->ssl;
++
++ return (sslconn && sslconn->ssl)
++ || (othermod_is_https && othermod_is_https(c));
+ }
+
+ static const char var_interface[] = "mod_ssl/" AP_SERVER_BASEREVISION;
+@@ -137,6 +141,9 @@
+ {
+ char *cp, *cp2;
+
++ othermod_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
++ othermod_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
++
+ APR_REGISTER_OPTIONAL_FN(ssl_is_https);
+ APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
+ APR_REGISTER_OPTIONAL_FN(ssl_ext_list);
+@@ -271,6 +278,15 @@
+ */
+ if (result == NULL && c != NULL) {
+ SSLConnRec *sslconn = ssl_get_effective_config(c);
++
++ if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
++ && (!sslconn || !sslconn->ssl) && othermod_var_lookup) {
++ /* For an SSL_* variable, if mod_ssl is not enabled for
++ * this connection and another SSL module is present, pass
++ * through to that module. */
++ return othermod_var_lookup(p, s, c, r, var);
++ }
++
+ if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
+ && sslconn && sslconn->ssl)
+ result = ssl_var_lookup_ssl(p, sslconn, r, var+4);
diff --git a/httpd-2.4.33-systemd.patch b/httpd-2.4.33-systemd.patch
new file mode 100644
index 0000000..7f5ee3b
--- /dev/null
+++ b/httpd-2.4.33-systemd.patch
@@ -0,0 +1,245 @@
+--- httpd-2.4.33/modules/arch/unix/config5.m4.systemd
++++ httpd-2.4.33/modules/arch/unix/config5.m4
+@@ -18,6 +18,16 @@
+ fi
+ ])
+
++APACHE_MODULE(systemd, Systemd support, , , all, [
++ if test "${ac_cv_header_systemd_sd_daemon_h}" = "no" || test -z "${SYSTEMD_LIBS}"; then
++ AC_MSG_WARN([Your system does not support systemd.])
++ enable_systemd="no"
++ else
++ APR_ADDTO(MOD_SYSTEMD_LDADD, [$SYSTEMD_LIBS])
++ enable_systemd="yes"
++ fi
++])
++
+ APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
+
+ APACHE_MODPATH_FINISH
+--- httpd-2.4.33/modules/arch/unix/mod_systemd.c.systemd
++++ httpd-2.4.33/modules/arch/unix/mod_systemd.c
+@@ -0,0 +1,223 @@
++/* Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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.
++ *
++ */
++
++#include
++#include
++#include "ap_mpm.h"
++#include
++#include
++#include
++#include
++#include
++#include
++#include "unixd.h"
++#include "scoreboard.h"
++#include "mpm_common.h"
++
++#include "systemd/sd-daemon.h"
++#include "systemd/sd-journal.h"
++
++#if APR_HAVE_UNISTD_H
++#include
++#endif
++
++static int shutdown_timer = 0;
++static int shutdown_counter = 0;
++static unsigned long bytes_served;
++static pid_t mainpid;
++static char describe_listeners[50];
++
++static int systemd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
++ apr_pool_t *ptemp)
++{
++ sd_notify(0,
++ "RELOADING=1\n"
++ "STATUS=Reading configuration...\n");
++ ap_extended_status = 1;
++ return OK;
++}
++
++static char *dump_listener(ap_listen_rec *lr, apr_pool_t *p)
++{
++ apr_sockaddr_t *sa = lr->bind_addr;
++ char addr[128];
++
++ if (apr_sockaddr_is_wildcard(sa)) {
++ return apr_pstrcat(p, "port ", apr_itoa(p, sa->port), NULL);
++ }
++
++ apr_sockaddr_ip_getbuf(addr, sizeof addr, sa);
++
++ return apr_psprintf(p, "%s port %u", addr, sa->port);
++}
++
++static int systemd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
++ apr_pool_t *ptemp, server_rec *s)
++{
++ ap_listen_rec *lr;
++ apr_size_t plen = sizeof describe_listeners;
++ char *p = describe_listeners;
++
++ if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
++ return OK;
++
++ for (lr = ap_listeners; lr; lr = lr->next) {
++ char *s = dump_listener(lr, ptemp);
++
++ if (strlen(s) + 3 < plen) {
++ char *newp = apr_cpystrn(p, s, plen);
++ if (lr->next)
++ newp = apr_cpystrn(newp, ", ", 3);
++ plen -= newp - p;
++ p = newp;
++ }
++ else {
++ if (plen < 4) {
++ p = describe_listeners + sizeof describe_listeners - 4;
++ plen = 4;
++ }
++ apr_cpystrn(p, "...", plen);
++ break;
++ }
++ }
++
++ sd_journal_print(LOG_INFO, "Server configured, listening on: %s", describe_listeners);
++
++ return OK;
++}
++
++static int systemd_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
++{
++ int rv;
++
++ mainpid = getpid();
++
++ rv = sd_notifyf(0, "READY=1\n"
++ "STATUS=Started, listening on: %s\n"
++ "MAINPID=%" APR_PID_T_FMT,
++ describe_listeners, mainpid);
++ if (rv < 0) {
++ ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p, APLOGNO(02395)
++ "sd_notifyf returned an error %d", rv);
++ }
++
++ return OK;
++}
++
++static int systemd_monitor(apr_pool_t *p, server_rec *s)
++{
++ ap_sload_t sload;
++ apr_interval_time_t up_time;
++ char bps[5];
++ int rv;
++
++ if (!ap_extended_status) {
++ /* Nothing useful to report if ExtendedStatus disabled. */
++ return DECLINED;
++ }
++
++ ap_get_sload(&sload);
++
++ if (sload.access_count == 0) {
++ rv = sd_notifyf(0, "READY=1\n"
++ "STATUS=Running, listening on: %s\n",
++ describe_listeners);
++ }
++ else {
++ /* up_time in seconds */
++ up_time = (apr_uint32_t) apr_time_sec(apr_time_now() -
++ ap_scoreboard_image->global->restart_time);
++
++ apr_strfsize((unsigned long)((float) (sload.bytes_served)
++ / (float) up_time), bps);
++
++ rv = sd_notifyf(0, "READY=1\n"
++ "STATUS=Total requests: %lu; Idle/Busy workers %d/%d;"
++ "Requests/sec: %.3g; Bytes served/sec: %sB/sec\n",
++ sload.access_count, sload.idle, sload.busy,
++ ((float) sload.access_count) / (float) up_time, bps);
++ }
++
++ if (rv < 0) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02396)
++ "sd_notifyf returned an error %d", rv);
++ }
++
++ /* Shutdown httpd when nothing is sent for shutdown_timer seconds. */
++ if (sload.bytes_served == bytes_served) {
++ /* mpm_common.c: INTERVAL_OF_WRITABLE_PROBES is 10 */
++ shutdown_counter += 10;
++ if (shutdown_timer > 0 && shutdown_counter >= shutdown_timer) {
++ rv = sd_notifyf(0, "READY=1\n"
++ "STATUS=Stopped as result of IdleShutdown "
++ "timeout.");
++ if (rv < 0) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02804)
++ "sd_notifyf returned an error %d", rv);
++ }
++ kill(mainpid, AP_SIG_GRACEFUL);
++ }
++ }
++ else {
++ shutdown_counter = 0;
++ }
++
++ bytes_served = sload.bytes_served;
++
++ return DECLINED;
++}
++
++static void systemd_register_hooks(apr_pool_t *p)
++{
++ /* Enable ap_extended_status. */
++ ap_hook_pre_config(systemd_pre_config, NULL, NULL, APR_HOOK_LAST);
++ /* Grab the listener config. */
++ ap_hook_post_config(systemd_post_config, NULL, NULL, APR_HOOK_LAST);
++ /* We know the PID in this hook ... */
++ ap_hook_pre_mpm(systemd_pre_mpm, NULL, NULL, APR_HOOK_LAST);
++ /* Used to update httpd's status line using sd_notifyf */
++ ap_hook_monitor(systemd_monitor, NULL, NULL, APR_HOOK_MIDDLE);
++}
++
++static const char *set_shutdown_timer(cmd_parms *cmd, void *dummy,
++ const char *arg)
++{
++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++ if (err != NULL) {
++ return err;
++ }
++
++ shutdown_timer = atoi(arg);
++ return NULL;
++}
++
++static const command_rec systemd_cmds[] =
++{
++AP_INIT_TAKE1("IdleShutdown", set_shutdown_timer, NULL, RSRC_CONF,
++ "Number of seconds in idle-state after which httpd is shutdown"),
++ {NULL}
++};
++
++AP_DECLARE_MODULE(systemd) = {
++ STANDARD20_MODULE_STUFF,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ systemd_cmds,
++ systemd_register_hooks,
++};
diff --git a/httpd-2.4.34-r1555631.patch b/httpd-2.4.34-r1555631.patch
new file mode 100644
index 0000000..7ca9478
--- /dev/null
+++ b/httpd-2.4.34-r1555631.patch
@@ -0,0 +1,14 @@
+# ./pullrev.sh 1555631
+http://svn.apache.org/viewvc?view=revision&revision=1555631
+
+--- httpd-2.4.34/modules/ssl/ssl_engine_ocsp.c
++++ httpd-2.4.34/modules/ssl/ssl_engine_ocsp.c
+@@ -61,7 +61,7 @@
+ /* Use default responder URL if forced by configuration, else use
+ * certificate-specified responder, falling back to default if
+ * necessary and possible. */
+- if (sc->server->ocsp_force_default) {
++ if (sc->server->ocsp_force_default == TRUE) {
+ s = sc->server->ocsp_responder;
+ }
+ else {
diff --git a/httpd-2.4.34-r1738878.patch b/httpd-2.4.34-r1738878.patch
new file mode 100644
index 0000000..5af48f5
--- /dev/null
+++ b/httpd-2.4.34-r1738878.patch
@@ -0,0 +1,130 @@
+--- httpd-2.4.34/modules/proxy/ajp_header.c.r1738878
++++ httpd-2.4.34/modules/proxy/ajp_header.c
+@@ -213,7 +213,8 @@
+
+ static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
+ request_rec *r,
+- apr_uri_t *uri)
++ apr_uri_t *uri,
++ const char *secret)
+ {
+ int method;
+ apr_uint32_t i, num_headers = 0;
+@@ -293,17 +294,15 @@
+ i, elts[i].key, elts[i].val);
+ }
+
+-/* XXXX need to figure out how to do this
+- if (s->secret) {
++ if (secret) {
+ if (ajp_msg_append_uint8(msg, SC_A_SECRET) ||
+- ajp_msg_append_string(msg, s->secret)) {
++ ajp_msg_append_string(msg, secret)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(03228)
+- "Error ajp_marshal_into_msgb - "
++ "ajp_marshal_into_msgb: "
+ "Error appending secret");
+ return APR_EGENERAL;
+ }
+ }
+- */
+
+ if (r->user) {
+ if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
+@@ -671,7 +670,8 @@
+ apr_status_t ajp_send_header(apr_socket_t *sock,
+ request_rec *r,
+ apr_size_t buffsize,
+- apr_uri_t *uri)
++ apr_uri_t *uri,
++ const char *secret)
+ {
+ ajp_msg_t *msg;
+ apr_status_t rc;
+@@ -683,7 +683,7 @@
+ return rc;
+ }
+
+- rc = ajp_marshal_into_msgb(msg, r, uri);
++ rc = ajp_marshal_into_msgb(msg, r, uri, secret);
+ if (rc != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00988)
+ "ajp_send_header: ajp_marshal_into_msgb failed");
+--- httpd-2.4.34/modules/proxy/ajp.h.r1738878
++++ httpd-2.4.34/modules/proxy/ajp.h
+@@ -413,12 +413,14 @@
+ * @param sock backend socket
+ * @param r current request
+ * @param buffsize max size of the AJP packet.
++ * @param secret authentication secret
+ * @param uri requested uri
+ * @return APR_SUCCESS or error
+ */
+ apr_status_t ajp_send_header(apr_socket_t *sock, request_rec *r,
+ apr_size_t buffsize,
+- apr_uri_t *uri);
++ apr_uri_t *uri,
++ const char *secret);
+
+ /**
+ * Read the ajp message and return the type of the message.
+--- httpd-2.4.34/modules/proxy/mod_proxy_ajp.c.r1738878
++++ httpd-2.4.34/modules/proxy/mod_proxy_ajp.c
+@@ -193,6 +193,7 @@
+ apr_off_t content_length = 0;
+ int original_status = r->status;
+ const char *original_status_line = r->status_line;
++ const char *secret = NULL;
+
+ if (psf->io_buffer_size_set)
+ maxsize = psf->io_buffer_size;
+@@ -202,12 +203,15 @@
+ maxsize = AJP_MSG_BUFFER_SZ;
+ maxsize = APR_ALIGN(maxsize, 1024);
+
++ if (*conn->worker->s->secret)
++ secret = conn->worker->s->secret;
++
+ /*
+ * Send the AJP request to the remote server
+ */
+
+ /* send request headers */
+- status = ajp_send_header(conn->sock, r, maxsize, uri);
++ status = ajp_send_header(conn->sock, r, maxsize, uri, secret);
+ if (status != APR_SUCCESS) {
+ conn->close = 1;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00868)
+--- httpd-2.4.34/modules/proxy/mod_proxy.c.r1738878
++++ httpd-2.4.34/modules/proxy/mod_proxy.c
+@@ -319,6 +319,12 @@
+ (int)sizeof(worker->s->upgrade));
+ }
+ }
++ else if (!strcasecmp(key, "secret")) {
++ if (PROXY_STRNCPY(worker->s->secret, val) != APR_SUCCESS) {
++ return apr_psprintf(p, "Secret length must be < %d characters",
++ (int)sizeof(worker->s->secret));
++ }
++ }
+ else if (!strcasecmp(key, "responsefieldsize")) {
+ long s = atol(val);
+ if (s < 0) {
+--- httpd-2.4.34/modules/proxy/mod_proxy.h.r1738878
++++ httpd-2.4.34/modules/proxy/mod_proxy.h
+@@ -357,6 +357,7 @@
+ #define PROXY_WORKER_MAX_HOSTNAME_SIZE 64
+ #define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE
+ #define PROXY_BALANCER_MAX_STICKY_SIZE 64
++#define PROXY_WORKER_MAX_SECRET_SIZE 64
+
+ #define PROXY_RFC1035_HOSTNAME_SIZE 256
+
+@@ -453,6 +454,7 @@
+ char hostname_ex[PROXY_RFC1035_HOSTNAME_SIZE]; /* RFC1035 compliant version of the remote backend address */
+ apr_size_t response_field_size; /* Size of proxy response buffer in bytes. */
+ unsigned int response_field_size_set:1;
++ char secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */
+ } proxy_worker_shared;
+
+ #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared)))
diff --git a/httpd-2.4.43-sslciphdefault.patch b/httpd-2.4.34-sslciphdefault.patch
similarity index 75%
rename from httpd-2.4.43-sslciphdefault.patch
rename to httpd-2.4.34-sslciphdefault.patch
index 85ae568..6060f24 100644
--- a/httpd-2.4.43-sslciphdefault.patch
+++ b/httpd-2.4.34-sslciphdefault.patch
@@ -1,8 +1,11 @@
-diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
-index 97778a8..27e7a53 100644
---- a/modules/ssl/ssl_engine_config.c
-+++ b/modules/ssl/ssl_engine_config.c
-@@ -778,9 +778,11 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1109119
+
+Don't prepend !aNULL etc if PROFILE= is used with SSLCipherSuite.
+
+--- httpd-2.4.34/modules/ssl/ssl_engine_config.c.sslciphdefault
++++ httpd-2.4.34/modules/ssl/ssl_engine_config.c
+@@ -774,9 +774,11 @@
}
if (!strcmp("SSL", arg1)) {
@@ -16,7 +19,7 @@ index 97778a8..27e7a53 100644
dc->szCipherSuite = arg2;
}
else {
-@@ -1544,8 +1546,10 @@ const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
+@@ -1540,8 +1542,10 @@
}
if (!strcmp("SSL", arg1)) {
diff --git a/httpd-2.4.37-r1857129.patch b/httpd-2.4.37-r1857129.patch
new file mode 100644
index 0000000..4dbf05a
--- /dev/null
+++ b/httpd-2.4.37-r1857129.patch
@@ -0,0 +1,65 @@
+# ./pullrev.sh 1857129
+http://svn.apache.org/viewvc?view=revision&revision=1857129
+
+--- httpd-2.4.37/modules/filters/mod_reqtimeout.c
++++ httpd-2.4.37/modules/filters/mod_reqtimeout.c
+@@ -31,7 +31,7 @@
+ #define UNSET -1
+ #define MRT_DEFAULT_handshake_TIMEOUT 0 /* disabled */
+ #define MRT_DEFAULT_handshake_MAX_TIMEOUT 0
+-#define MRT_DEFAULT_handshake_MIN_RATE APR_INT32_MAX
++#define MRT_DEFAULT_handshake_MIN_RATE 0
+ #define MRT_DEFAULT_header_TIMEOUT 20
+ #define MRT_DEFAULT_header_MAX_TIMEOUT 40
+ #define MRT_DEFAULT_header_MIN_RATE 500
+@@ -220,7 +220,7 @@
+ if (block == APR_NONBLOCK_READ || mode == AP_MODE_INIT
+ || mode == AP_MODE_EATCRLF) {
+ rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
+- if (ccfg->cur_stage.rate_factor > 0 && rv == APR_SUCCESS) {
++ if (ccfg->cur_stage.rate_factor && rv == APR_SUCCESS) {
+ extend_timeout(ccfg, bb);
+ }
+ return rv;
+@@ -254,7 +254,7 @@
+ }
+
+ if (!APR_BRIGADE_EMPTY(bb)) {
+- if (ccfg->cur_stage.rate_factor > 0) {
++ if (ccfg->cur_stage.rate_factor) {
+ extend_timeout(ccfg, bb);
+ }
+
+@@ -315,7 +315,7 @@
+ * the real (relevant) bytes to be asked later, within the
+ * currently alloted time.
+ */
+- if (ccfg->cur_stage.rate_factor > 0 && rv == APR_SUCCESS
++ if (ccfg->cur_stage.rate_factor && rv == APR_SUCCESS
+ && mode != AP_MODE_SPECULATIVE) {
+ extend_timeout(ccfg, bb);
+ }
+@@ -638,17 +638,17 @@
+ ap_hook_post_read_request(reqtimeout_before_body, NULL, NULL,
+ APR_HOOK_MIDDLE);
+
+-#if MRT_DEFAULT_HANDSHAKE_MIN_RATE > 0
++#if MRT_DEFAULT_handshake_MIN_RATE
+ default_handshake_rate_factor = apr_time_from_sec(1) /
+- MRT_DEFAULT_HANDSHAKE_MIN_RATE;
++ MRT_DEFAULT_handshake_MIN_RATE;
+ #endif
+-#if MRT_DEFAULT_HEADER_MIN_RATE > 0
++#if MRT_DEFAULT_header_MIN_RATE
+ default_header_rate_factor = apr_time_from_sec(1) /
+- MRT_DEFAULT_HEADER_MIN_RATE;
++ MRT_DEFAULT_header_MIN_RATE;
+ #endif
+-#if MRT_DEFAULT_BODY_MIN_RATE > 0
++#if MRT_DEFAULT_body_MIN_RATE
+ default_body_rate_factor = apr_time_from_sec(1) /
+- MRT_DEFAULT_BODY_MIN_RATE;
++ MRT_DEFAULT_body_MIN_RATE;
+ #endif
+ }
+
diff --git a/httpd-2.4.64-sslprotdefault.patch b/httpd-2.4.37-sslprotdefault.patch
similarity index 82%
rename from httpd-2.4.64-sslprotdefault.patch
rename to httpd-2.4.37-sslprotdefault.patch
index 6d97935..546fa1f 100644
--- a/httpd-2.4.64-sslprotdefault.patch
+++ b/httpd-2.4.37-sslprotdefault.patch
@@ -1,8 +1,8 @@
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
-index 8fae1f8..c5dce7f 100644
+index 55c237e..5467d23 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
-@@ -127,7 +127,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
+@@ -119,7 +119,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
mctx->ticket_key = NULL;
#endif
@@ -11,27 +11,27 @@ index 8fae1f8..c5dce7f 100644
mctx->protocol_set = 0;
mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET;
-@@ -268,6 +268,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
+@@ -262,6 +262,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
+ {
if (add->protocol_set) {
- mrg->protocol_set = 1;
mrg->protocol = add->protocol;
+ mrg->protocol_set = 1;
}
else {
- mrg->protocol_set = base->protocol_set;
+ mrg->protocol = base->protocol;
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
-index 4e265b3..2fbd076 100644
+index e3f62fe..31fc0e6 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
-@@ -638,6 +638,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+@@ -568,6 +568,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL;
char *cp;
int protocol = mctx->protocol;
+ int protocol_set = mctx->protocol_set;
SSLSrvConfigRec *sc = mySrvConfig(s);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- /* default is highest supported version, will be overridden below */
-@@ -652,12 +653,18 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+ int prot;
+@@ -577,12 +578,18 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
* Create the new per-server SSL context
*/
if (protocol == SSL_PROTOCOL_NONE) {
@@ -55,7 +55,7 @@ index 4e265b3..2fbd076 100644
#ifndef OPENSSL_NO_SSL3
(protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
#endif
-@@ -670,7 +677,8 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+@@ -595,7 +602,8 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
#endif
#endif
NULL);
@@ -65,7 +65,7 @@ index 4e265b3..2fbd076 100644
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
"Creating new SSL context (protocols: %s)", cp);
-@@ -776,13 +784,15 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+@@ -696,13 +704,15 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
prot = SSL3_VERSION;
#endif
} else {
@@ -87,7 +87,7 @@ index 4e265b3..2fbd076 100644
/* Next we scan for the minimal protocol version we should provide,
* but we do not allow holes between max and min */
-@@ -806,7 +816,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+@@ -726,7 +736,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
prot = SSL3_VERSION;
}
#endif
diff --git a/httpd-2.4.38-r1830819+.patch b/httpd-2.4.38-r1830819+.patch
new file mode 100644
index 0000000..7df5ff6
--- /dev/null
+++ b/httpd-2.4.38-r1830819+.patch
@@ -0,0 +1,677 @@
+# ./pullrev.sh 1830819 1830836 1830912 1830913 1830927 1831168 1831173
+
+http://svn.apache.org/viewvc?view=revision&revision=1830819
+http://svn.apache.org/viewvc?view=revision&revision=1830912
+http://svn.apache.org/viewvc?view=revision&revision=1830913
+http://svn.apache.org/viewvc?view=revision&revision=1830927
+http://svn.apache.org/viewvc?view=revision&revision=1831168
+http://svn.apache.org/viewvc?view=revision&revision=1831173
+http://svn.apache.org/viewvc?view=revision&revision=1835240
+http://svn.apache.org/viewvc?view=revision&revision=1835242
+
+diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
+index d276fea..5467d23 100644
+--- httpd-2.4.38/modules/ssl/ssl_engine_config.c.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_engine_config.c
+@@ -916,7 +916,9 @@
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+- if ((err = ssl_cmd_check_file(cmd, &arg))) {
++ /* Only check for non-ENGINE based certs. */
++ if (!modssl_is_engine_id(arg)
++ && (err = ssl_cmd_check_file(cmd, &arg))) {
+ return err;
+ }
+
+@@ -932,7 +934,9 @@
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+- if ((err = ssl_cmd_check_file(cmd, &arg))) {
++ /* Check keyfile exists for non-ENGINE keys. */
++ if (!modssl_is_engine_id(arg)
++ && (err = ssl_cmd_check_file(cmd, &arg))) {
+ return err;
+ }
+
+--- httpd-2.4.38/modules/ssl/ssl_engine_init.c.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_engine_init.c
+@@ -1228,12 +1228,18 @@
+ (certfile = APR_ARRAY_IDX(mctx->pks->cert_files, i,
+ const char *));
+ i++) {
++ EVP_PKEY *pkey;
++ const char *engine_certfile = NULL;
++
+ key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
+
+ ERR_clear_error();
+
+ /* first the certificate (public key) */
+- if (mctx->cert_chain) {
++ if (modssl_is_engine_id(certfile)) {
++ engine_certfile = certfile;
++ }
++ else if (mctx->cert_chain) {
+ if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile,
+ SSL_FILETYPE_PEM) < 1)) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561)
+@@ -1262,12 +1268,46 @@
+
+ ERR_clear_error();
+
+- if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
+- SSL_FILETYPE_PEM) < 1) &&
+- (ERR_GET_FUNC(ERR_peek_last_error())
+- != X509_F_X509_CHECK_PRIVATE_KEY)) {
++ if (modssl_is_engine_id(keyfile)) {
++ apr_status_t rv;
++
++ cert = NULL;
++
++ if ((rv = modssl_load_engine_keypair(s, ptemp, vhost_id,
++ engine_certfile, keyfile,
++ &cert, &pkey))) {
++ return rv;
++ }
++
++ if (cert) {
++ if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) < 1) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10137)
++ "Failed to configure engine certificate %s, check %s",
++ key_id, certfile);
++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
++ return APR_EGENERAL;
++ }
++
++ /* SSL_CTX now owns the cert. */
++ X509_free(cert);
++ }
++
++ if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)
++ "Failed to configure private key %s from engine",
++ keyfile);
++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
++ return APR_EGENERAL;
++ }
++
++ /* SSL_CTX now owns the key */
++ EVP_PKEY_free(pkey);
++ }
++ else if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
++ SSL_FILETYPE_PEM) < 1)
++ && (ERR_GET_FUNC(ERR_peek_last_error())
++ != X509_F_X509_CHECK_PRIVATE_KEY)) {
+ ssl_asn1_t *asn1;
+- EVP_PKEY *pkey;
+ const unsigned char *ptr;
+
+ ERR_clear_error();
+@@ -1354,8 +1394,9 @@
+ /*
+ * Try to read DH parameters from the (first) SSLCertificateFile
+ */
+- if ((certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *)) &&
+- (dhparams = ssl_dh_GetParamFromFile(certfile))) {
++ certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *);
++ if (certfile && !modssl_is_engine_id(certfile)
++ && (dhparams = ssl_dh_GetParamFromFile(certfile))) {
+ SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
+ "Custom DH parameters (%d bits) for %s loaded from %s",
+@@ -1367,10 +1408,10 @@
+ /*
+ * Similarly, try to read the ECDH curve name from SSLCertificateFile...
+ */
+- if ((certfile != NULL) &&
+- (ecparams = ssl_ec_GetParamFromFile(certfile)) &&
+- (nid = EC_GROUP_get_curve_name(ecparams)) &&
+- (eckey = EC_KEY_new_by_curve_name(nid))) {
++ if (certfile && !modssl_is_engine_id(certfile)
++ && (ecparams = ssl_ec_GetParamFromFile(certfile))
++ && (nid = EC_GROUP_get_curve_name(ecparams))
++ && (eckey = EC_KEY_new_by_curve_name(nid))) {
+ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541)
+ "ECDH curve %s for %s specified in %s",
+--- httpd-2.4.38/modules/ssl/ssl_engine_pphrase.c.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_engine_pphrase.c
+@@ -143,8 +143,6 @@
+ const char *key_id = asn1_table_vhost_key(mc, p, sc->vhost_id, idx);
+ EVP_PKEY *pPrivateKey = NULL;
+ ssl_asn1_t *asn1;
+- unsigned char *ucp;
+- long int length;
+ int nPassPhrase = (*pphrases)->nelts;
+ int nPassPhraseRetry = 0;
+ apr_time_t pkey_mtime = 0;
+@@ -221,7 +219,7 @@
+ * is not empty. */
+ ERR_clear_error();
+
+- pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file, NULL,
++ pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file,
+ ssl_pphrase_Handle_CB, &ppcb_arg);
+ /* If the private key was successfully read, nothing more to
+ do here. */
+@@ -351,19 +349,12 @@
+ nPassPhrase++;
+ }
+
+- /*
+- * Insert private key into the global module configuration
+- * (we convert it to a stand-alone DER byte sequence
+- * because the SSL library uses static variables inside a
+- * RSA structure which do not survive DSO reloads!)
+- */
+- length = i2d_PrivateKey(pPrivateKey, NULL);
+- ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
+- (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
++ /* Cache the private key in the global module configuration so it
++ * can be used after subsequent reloads. */
++ asn1 = ssl_asn1_table_set(mc->tPrivateKey, key_id, pPrivateKey);
+
+ if (ppcb_arg.nPassPhraseDialogCur != 0) {
+ /* remember mtime of encrypted keys */
+- asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
+ asn1->source_mtime = pkey_mtime;
+ }
+
+@@ -614,3 +605,288 @@
+ */
+ return (len);
+ }
++
++
++#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
++
++/* OpenSSL UI implementation for passphrase entry; largely duplicated
++ * from ssl_pphrase_Handle_CB but adjusted for UI API. TODO: Might be
++ * worth trying to shift pphrase handling over to the UI API
++ * completely. */
++static int passphrase_ui_open(UI *ui)
++{
++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
++ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
++
++ ppcb->nPassPhraseDialog++;
++ ppcb->nPassPhraseDialogCur++;
++
++ /*
++ * Builtin or Pipe dialog
++ */
++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
++ if (!readtty) {
++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s,
++ APLOGNO(10143)
++ "Init: Creating pass phrase dialog pipe child "
++ "'%s'", sc->server->pphrase_dialog_path);
++ if (ssl_pipe_child_create(ppcb->p,
++ sc->server->pphrase_dialog_path)
++ != APR_SUCCESS) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s,
++ APLOGNO(10144)
++ "Init: Failed to create pass phrase pipe '%s'",
++ sc->server->pphrase_dialog_path);
++ return 0;
++ }
++ }
++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10145)
++ "Init: Requesting pass phrase via piped dialog");
++ }
++ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
++#ifdef WIN32
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s, APLOGNO(10146)
++ "Init: Failed to create pass phrase pipe '%s'",
++ sc->server->pphrase_dialog_path);
++ return 0;
++#else
++ /*
++ * stderr has already been redirected to the error_log.
++ * rather than attempting to temporarily rehook it to the terminal,
++ * we print the prompt to stdout before EVP_read_pw_string turns
++ * off tty echo
++ */
++ apr_file_open_stdout(&writetty, ppcb->p);
++
++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10147)
++ "Init: Requesting pass phrase via builtin terminal "
++ "dialog");
++#endif
++ }
++
++ /*
++ * The first time display a header to inform the user about what
++ * program he actually speaks to, which module is responsible for
++ * this terminal dialog and why to the hell he has to enter
++ * something...
++ */
++ if (ppcb->nPassPhraseDialog == 1) {
++ apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n",
++ AP_SERVER_BASEVERSION);
++ apr_file_printf(writetty,
++ "A pass phrase is required to access the private key.\n");
++ }
++ if (ppcb->bPassPhraseDialogOnce) {
++ ppcb->bPassPhraseDialogOnce = FALSE;
++ apr_file_printf(writetty, "\n");
++ apr_file_printf(writetty, "Private key %s (%s)\n",
++ ppcb->key_id, ppcb->pkey_file);
++ }
++ }
++
++ return 1;
++}
++
++static int passphrase_ui_read(UI *ui, UI_STRING *uis)
++{
++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
++ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
++ const char *prompt;
++ int i;
++ int bufsize;
++ int len;
++ char *buf;
++
++ prompt = UI_get0_output_string(uis);
++ if (prompt == NULL) {
++ prompt = "Enter pass phrase:";
++ }
++
++ /*
++ * Get the maximum expected size and allocate the buffer
++ */
++ bufsize = UI_get_result_maxsize(uis);
++ buf = apr_pcalloc(ppcb->p, bufsize);
++
++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
++ /*
++ * Get the pass phrase through a callback.
++ * Empty input is not accepted.
++ */
++ for (;;) {
++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
++ i = pipe_get_passwd_cb(buf, bufsize, "", FALSE);
++ }
++ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
++ i = EVP_read_pw_string(buf, bufsize, "", FALSE);
++ }
++ if (i != 0) {
++ OPENSSL_cleanse(buf, bufsize);
++ return 0;
++ }
++ len = strlen(buf);
++ if (len < 1){
++ apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase"
++ "empty (needs to be at least 1 character).\n");
++ apr_file_puts(prompt, writetty);
++ }
++ else {
++ break;
++ }
++ }
++ }
++ /*
++ * Filter program
++ */
++ else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) {
++ const char *cmd = sc->server->pphrase_dialog_path;
++ const char **argv = apr_palloc(ppcb->p, sizeof(char *) * 3);
++ char *result;
++
++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10148)
++ "Init: Requesting pass phrase from dialog filter "
++ "program (%s)", cmd);
++
++ argv[0] = cmd;
++ argv[1] = ppcb->key_id;
++ argv[2] = NULL;
++
++ result = ssl_util_readfilter(ppcb->s, ppcb->p, cmd, argv);
++ apr_cpystrn(buf, result, bufsize);
++ len = strlen(buf);
++ }
++
++ /*
++ * Ok, we now have the pass phrase, so give it back
++ */
++ ppcb->cpPassPhraseCur = apr_pstrdup(ppcb->p, buf);
++ UI_set_result(ui, uis, buf);
++
++ /* Clear sensitive data. */
++ OPENSSL_cleanse(buf, bufsize);
++ return 1;
++}
++
++static int passphrase_ui_write(UI *ui, UI_STRING *uis)
++{
++ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
++ SSLSrvConfigRec *sc;
++ const char *prompt;
++
++ sc = mySrvConfig(ppcb->s);
++
++ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
++ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
++ prompt = UI_get0_output_string(uis);
++ apr_file_puts(prompt, writetty);
++ }
++
++ return 1;
++}
++
++static int passphrase_ui_close(UI *ui)
++{
++ /*
++ * Close the pipes if they were opened
++ */
++ if (readtty) {
++ apr_file_close(readtty);
++ apr_file_close(writetty);
++ readtty = writetty = NULL;
++ }
++ return 1;
++}
++
++static apr_status_t pp_ui_method_cleanup(void *uip)
++{
++ UI_METHOD *uim = uip;
++
++ UI_destroy_method(uim);
++
++ return APR_SUCCESS;
++}
++
++static UI_METHOD *get_passphrase_ui(apr_pool_t *p)
++{
++ UI_METHOD *ui_method = UI_create_method("Passphrase UI");
++
++ UI_method_set_opener(ui_method, passphrase_ui_open);
++ UI_method_set_reader(ui_method, passphrase_ui_read);
++ UI_method_set_writer(ui_method, passphrase_ui_write);
++ UI_method_set_closer(ui_method, passphrase_ui_close);
++
++ apr_pool_cleanup_register(p, ui_method, pp_ui_method_cleanup,
++ pp_ui_method_cleanup);
++
++ return ui_method;
++}
++
++
++apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
++ const char *vhostid,
++ const char *certid, const char *keyid,
++ X509 **pubkey, EVP_PKEY **privkey)
++{
++ SSLModConfigRec *mc = myModConfig(s);
++ ENGINE *e;
++ UI_METHOD *ui_method = get_passphrase_ui(p);
++ pphrase_cb_arg_t ppcb;
++
++ memset(&ppcb, 0, sizeof ppcb);
++ ppcb.s = s;
++ ppcb.p = p;
++ ppcb.bPassPhraseDialogOnce = TRUE;
++ ppcb.key_id = vhostid;
++ ppcb.pkey_file = keyid;
++
++ if (!mc->szCryptoDevice) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
++ "Init: Cannot load private key `%s' without engine",
++ keyid);
++ return ssl_die(s);
++ }
++
++ if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
++ "Init: Failed to load Crypto Device API `%s'",
++ mc->szCryptoDevice);
++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
++ return ssl_die(s);
++ }
++
++ if (APLOGdebug(s)) {
++ ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
++ }
++
++ if (certid) {
++ struct {
++ const char *cert_id;
++ X509 *cert;
++ } params = { certid, NULL };
++
++ if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10136)
++ "Init: Unable to get the certificate");
++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
++ return ssl_die(s);
++ }
++
++ *pubkey = params.cert;
++ }
++
++ *privkey = ENGINE_load_private_key(e, keyid, ui_method, &ppcb);
++ if (*privkey == NULL) {
++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
++ "Init: Unable to get the private key");
++ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
++ return ssl_die(s);
++ }
++
++ ENGINE_free(e);
++
++ return APR_SUCCESS;
++}
++#endif
+--- httpd-2.4.38/modules/ssl/ssl_private.h.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_private.h
+@@ -1002,21 +1002,28 @@
+ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
+ const char *, apr_array_header_t **);
+
++/* Load public and/or private key from the configured ENGINE. Private
++ * key returned as *pkey. certid can be NULL, in which case *pubkey
++ * is not altered. Errors logged on failure. */
++apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
++ const char *vhostid,
++ const char *certid, const char *keyid,
++ X509 **pubkey, EVP_PKEY **privkey);
++
+ /** Diffie-Hellman Parameter Support */
+ DH *ssl_dh_GetParamFromFile(const char *);
+ #ifdef HAVE_ECC
+ EC_GROUP *ssl_ec_GetParamFromFile(const char *);
+ #endif
+
+-unsigned char *ssl_asn1_table_set(apr_hash_t *table,
+- const char *key,
+- long int length);
+-
+-ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
+- const char *key);
+-
+-void ssl_asn1_table_unset(apr_hash_t *table,
+- const char *key);
++/* Store the EVP_PKEY key (serialized into DER) in the hash table with
++ * key, returning the ssl_asn1_t structure pointer. */
++ssl_asn1_t *ssl_asn1_table_set(apr_hash_t *table, const char *key,
++ EVP_PKEY *pkey);
++/* Retrieve the ssl_asn1_t structure with given key from the hash. */
++ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table, const char *key);
++/* Remove and free the ssl_asn1_t structure with given key. */
++void ssl_asn1_table_unset(apr_hash_t *table, const char *key);
+
+ /** Mutex Support */
+ int ssl_mutex_init(server_rec *, apr_pool_t *);
+@@ -1109,6 +1116,10 @@
+ int ssl_is_challenge(conn_rec *c, const char *servername,
+ X509 **pcert, EVP_PKEY **pkey);
+
++/* Returns non-zero if the cert/key filename should be handled through
++ * the configured ENGINE. */
++int modssl_is_engine_id(const char *name);
++
+ #endif /* SSL_PRIVATE_H */
+ /** @} */
+
+--- httpd-2.4.38/modules/ssl/ssl_util.c.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_util.c
+@@ -192,45 +192,37 @@
+ return TRUE;
+ }
+
+-/*
+- * certain key data needs to survive restarts,
+- * which are stored in the user data table of s->process->pool.
+- * to prevent "leaking" of this data, we use malloc/free
+- * rather than apr_palloc and these wrappers to help make sure
+- * we do not leak the malloc-ed data.
+- */
+-unsigned char *ssl_asn1_table_set(apr_hash_t *table,
+- const char *key,
+- long int length)
++/* Decrypted private keys are cached to survive restarts. The cached
++ * data must have lifetime of the process (hence malloc/free rather
++ * than pools), and uses raw DER since the EVP_PKEY structure
++ * internals may not survive across a module reload. */
++ssl_asn1_t *ssl_asn1_table_set(apr_hash_t *table, const char *key,
++ EVP_PKEY *pkey)
+ {
+ apr_ssize_t klen = strlen(key);
+ ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
++ apr_size_t length = i2d_PrivateKey(pkey, NULL);
++ unsigned char *p;
+
+- /*
+- * if a value for this key already exists,
+- * reuse as much of the already malloc-ed data
+- * as possible.
+- */
++ /* Re-use structure if cached previously. */
+ if (asn1) {
+ if (asn1->nData != length) {
+- free(asn1->cpData); /* XXX: realloc? */
+- asn1->cpData = NULL;
++ asn1->cpData = ap_realloc(asn1->cpData, length);
+ }
+ }
+ else {
+ asn1 = ap_malloc(sizeof(*asn1));
+ asn1->source_mtime = 0; /* used as a note for encrypted private keys */
+- asn1->cpData = NULL;
+- }
+-
+- asn1->nData = length;
+- if (!asn1->cpData) {
+ asn1->cpData = ap_malloc(length);
++
++ apr_hash_set(table, key, klen, asn1);
+ }
+
+- apr_hash_set(table, key, klen, asn1);
++ asn1->nData = length;
++ p = asn1->cpData;
++ i2d_PrivateKey(pkey, &p); /* increases p by length */
+
+- return asn1->cpData; /* caller will assign a value to this */
++ return asn1;
+ }
+
+ ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
+@@ -480,3 +472,13 @@
+ }
+
+ #endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
++
++int modssl_is_engine_id(const char *name)
++{
++#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
++ /* ### Can handle any other special ENGINE key names here? */
++ return strncmp(name, "pkcs11:", 7) == 0;
++#else
++ return 0;
++#endif
++}
+--- httpd-2.4.38/modules/ssl/ssl_util_ssl.c.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_util_ssl.c
+@@ -74,7 +74,7 @@
+ ** _________________________________________________________________
+ */
+
+-EVP_PKEY *modssl_read_privatekey(const char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s)
++EVP_PKEY *modssl_read_privatekey(const char *filename, pem_password_cb *cb, void *s)
+ {
+ EVP_PKEY *rc;
+ BIO *bioS;
+@@ -83,7 +83,7 @@
+ /* 1. try PEM (= DER+Base64+headers) */
+ if ((bioS=BIO_new_file(filename, "r")) == NULL)
+ return NULL;
+- rc = PEM_read_bio_PrivateKey(bioS, key, cb, s);
++ rc = PEM_read_bio_PrivateKey(bioS, NULL, cb, s);
+ BIO_free(bioS);
+
+ if (rc == NULL) {
+@@ -107,41 +107,9 @@
+ BIO_free(bioS);
+ }
+ }
+- if (rc != NULL && key != NULL) {
+- if (*key != NULL)
+- EVP_PKEY_free(*key);
+- *key = rc;
+- }
+ return rc;
+ }
+
+-typedef struct {
+- const char *pass;
+- int pass_len;
+-} pass_ctx;
+-
+-static int provide_pass(char *buf, int size, int rwflag, void *baton)
+-{
+- pass_ctx *ctx = baton;
+- if (ctx->pass_len > 0) {
+- if (ctx->pass_len < size) {
+- size = (int)ctx->pass_len;
+- }
+- memcpy(buf, ctx->pass, size);
+- }
+- return ctx->pass_len;
+-}
+-
+-EVP_PKEY *modssl_read_encrypted_pkey(const char *filename, EVP_PKEY **key,
+- const char *pass, apr_size_t pass_len)
+-{
+- pass_ctx ctx;
+-
+- ctx.pass = pass;
+- ctx.pass_len = pass_len;
+- return modssl_read_privatekey(filename, key, provide_pass, &ctx);
+-}
+-
+ /* _________________________________________________________________
+ **
+ ** Smart shutdown
+--- httpd-2.4.38/modules/ssl/ssl_util_ssl.h.r1830819+
++++ httpd-2.4.38/modules/ssl/ssl_util_ssl.h
+@@ -64,8 +64,11 @@
+ void modssl_init_app_data2_idx(void);
+ void *modssl_get_app_data2(SSL *);
+ void modssl_set_app_data2(SSL *, void *);
+-EVP_PKEY *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, void *);
+-EVP_PKEY *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t);
++
++/* Read private key from filename in either PEM or raw base64(DER)
++ * format, using password entry callback cb and userdata. */
++EVP_PKEY *modssl_read_privatekey(const char *filename, pem_password_cb *cb, void *ud);
++
+ int modssl_smart_shutdown(SSL *ssl);
+ BOOL modssl_X509_getBC(X509 *, int *, int *);
+ char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne,
diff --git a/httpd-2.4.43-cachehardmax.patch b/httpd-2.4.4-cachehardmax.patch
similarity index 86%
rename from httpd-2.4.43-cachehardmax.patch
rename to httpd-2.4.4-cachehardmax.patch
index 755f822..de360ce 100644
--- a/httpd-2.4.43-cachehardmax.patch
+++ b/httpd-2.4.4-cachehardmax.patch
@@ -1,8 +1,8 @@
diff --git a/modules/cache/cache_util.h b/modules/cache/cache_util.h
-index 6b92151..4c42a8e 100644
+index eec38f3..1a2d5ee 100644
--- a/modules/cache/cache_util.h
+++ b/modules/cache/cache_util.h
-@@ -195,6 +195,9 @@ typedef struct {
+@@ -194,6 +194,9 @@ typedef struct {
unsigned int store_nostore_set:1;
unsigned int enable_set:1;
unsigned int disable_set:1;
@@ -13,10 +13,10 @@ index 6b92151..4c42a8e 100644
/* A linked-list of authn providers. */
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c
-index 3b9aa4f..8268503 100644
+index 4f2d3e0..30c88f4 100644
--- a/modules/cache/mod_cache.c
+++ b/modules/cache/mod_cache.c
-@@ -1455,6 +1455,11 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
+@@ -1299,6 +1299,11 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
exp = date + dconf->defex;
}
}
@@ -28,7 +28,7 @@ index 3b9aa4f..8268503 100644
info->expire = exp;
/* We found a stale entry which wasn't really stale. */
-@@ -1954,7 +1959,9 @@ static void *create_dir_config(apr_pool_t *p, char *dummy)
+@@ -1717,7 +1722,9 @@ static void *create_dir_config(apr_pool_t *p, char *dummy)
/* array of providers for this URL space */
dconf->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
@@ -39,7 +39,7 @@ index 3b9aa4f..8268503 100644
return dconf;
}
-@@ -2004,7 +2011,10 @@ static void *merge_dir_config(apr_pool_t *p, void *basev, void *addv) {
+@@ -1767,7 +1774,10 @@ static void *merge_dir_config(apr_pool_t *p, void *basev, void *addv) {
new->enable_set = add->enable_set || base->enable_set;
new->disable = (add->disable_set == 0) ? base->disable : add->disable;
new->disable_set = add->disable_set || base->disable_set;
@@ -51,7 +51,7 @@ index 3b9aa4f..8268503 100644
return new;
}
-@@ -2332,12 +2342,18 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy,
+@@ -2096,12 +2106,18 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy,
}
static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
@@ -71,7 +71,7 @@ index 3b9aa4f..8268503 100644
return NULL;
}
-@@ -2545,7 +2561,7 @@ static const command_rec cache_cmds[] =
+@@ -2309,7 +2325,7 @@ static const command_rec cache_cmds[] =
"caching is enabled"),
AP_INIT_TAKE1("CacheDisable", add_cache_disable, NULL, RSRC_CONF|ACCESS_CONF,
"A partial URL prefix below which caching is disabled"),
diff --git a/httpd-2.4.4-r1337344+.patch b/httpd-2.4.4-r1337344+.patch
new file mode 100644
index 0000000..6e5c3e7
--- /dev/null
+++ b/httpd-2.4.4-r1337344+.patch
@@ -0,0 +1,250 @@
+# ./pullrev.sh 1337344 1341905 1342065 1341930
+
+suexec enhancements:
+
+1) use syslog for logging
+2) use capabilities not setuid/setgid root binary
+
+http://svn.apache.org/viewvc?view=revision&revision=1337344
+http://svn.apache.org/viewvc?view=revision&revision=1341905
+http://svn.apache.org/viewvc?view=revision&revision=1342065
+http://svn.apache.org/viewvc?view=revision&revision=1341930
+
+--- httpd-2.4.4/configure.in.r1337344+
++++ httpd-2.4.4/configure.in
+@@ -734,7 +734,24 @@ APACHE_HELP_STRING(--with-suexec-gidmin,
+
+ AC_ARG_WITH(suexec-logfile,
+ APACHE_HELP_STRING(--with-suexec-logfile,Set the logfile),[
+- AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file] ) ] )
++ if test "x$withval" = "xyes"; then
++ AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file])
++ fi
++])
++
++AC_ARG_WITH(suexec-syslog,
++APACHE_HELP_STRING(--with-suexec-syslog,Set the logfile),[
++ if test $withval = "yes"; then
++ if test "x${with_suexec_logfile}" != "xno"; then
++ AC_MSG_NOTICE([hint: use "--without-suexec-logfile --with-suexec-syslog"])
++ AC_MSG_ERROR([suexec does not support both logging to file and syslog])
++ fi
++ AC_CHECK_FUNCS([vsyslog], [], [
++ AC_MSG_ERROR([cannot support syslog from suexec without vsyslog()])])
++ AC_DEFINE(AP_LOG_SYSLOG, 1, [SuExec log to syslog])
++ fi
++])
++
+
+ AC_ARG_WITH(suexec-safepath,
+ APACHE_HELP_STRING(--with-suexec-safepath,Set the safepath),[
+@@ -744,6 +761,15 @@ AC_ARG_WITH(suexec-umask,
+ APACHE_HELP_STRING(--with-suexec-umask,umask for suexec'd process),[
+ AC_DEFINE_UNQUOTED(AP_SUEXEC_UMASK, 0$withval, [umask for suexec'd process] ) ] )
+
++INSTALL_SUEXEC=setuid
++AC_ARG_ENABLE([suexec-capabilities],
++APACHE_HELP_STRING(--enable-suexec-capabilities,Use Linux capability bits not setuid root suexec), [
++INSTALL_SUEXEC=caps
++AC_DEFINE(AP_SUEXEC_CAPABILITIES, 1,
++ [Enable if suexec is installed with Linux capabilities, not setuid])
++])
++APACHE_SUBST(INSTALL_SUEXEC)
++
+ dnl APR should go after the other libs, so the right symbols can be picked up
+ if test x${apu_found} != xobsolete; then
+ AP_LIBS="$AP_LIBS `$apu_config --avoid-ldap --link-libtool`"
+--- httpd-2.4.4/docs/manual/suexec.html.en.r1337344+
++++ httpd-2.4.4/docs/manual/suexec.html.en
+@@ -372,6 +372,21 @@
+ together with the --enable-suexec option to let
+ APACI accept your request for using the suEXEC feature.
+
++
--enable-suexec-capabilities
++
++
Linux specific: Normally,
++ the suexec binary is installed "setuid/setgid
++ root", which allows it to run with the full privileges of the
++ root user. If this option is used, the suexec
++ binary will instead be installed with only the setuid/setgid
++ "capability" bits set, which is the subset of full root
++ priviliges required for suexec operation. Note that
++ the suexec binary may not be able to write to a log
++ file in this mode; it is recommended that the
++ --with-suexec-syslog --without-suexec-logfile
++ options are used in conjunction with this mode, so that syslog
++ logging is used instead.
++
+
--with-suexec-bin=PATH
+
+
The path to the suexec binary must be hard-coded
+@@ -433,6 +448,12 @@
+ "suexec_log" and located in your standard logfile
+ directory (--logfiledir).
+
++
--with-suexec-syslog
++
++
If defined, suexec will log notices and errors to syslog
++ instead of a logfile. This option must be combined
++ with --without-suexec-logfile.
++
+
--with-suexec-safepath=PATH
+
+
Define a safe PATH environment to pass to CGI
+@@ -550,9 +571,12 @@ Group webgroup
+
+
The suEXEC wrapper will write log information
+ to the file defined with the --with-suexec-logfile
+- option as indicated above. If you feel you have configured and
+- installed the wrapper properly, have a look at this log and the
+- error_log for the server to see where you may have gone astray.
++ option as indicated above, or to syslog if --with-suexec-syslog
++ is used. If you feel you have configured and
++ installed the wrapper properly, have a look at the log and the
++ error_log for the server to see where you may have gone astray.
++ The output of "suexec -V" will show the options
++ used to compile suexec, if using a binary distribution.