Import rpm: 692b48d0dcb7d82ec523751d970b07dfeede90a9
This commit is contained in:
commit
c700398165
1
.fmf/version
Normal file
1
.fmf/version
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
SOURCES/apache-poweredby.png
|
||||
SOURCES/httpd-2.4.37.tar.bz2
|
68
00-base.conf
Normal file
68
00-base.conf
Normal file
@ -0,0 +1,68 @@
|
||||
#
|
||||
# This file loads most of the modules included with the Apache HTTP
|
||||
# Server itself.
|
||||
#
|
||||
|
||||
LoadModule access_compat_module modules/mod_access_compat.so
|
||||
LoadModule actions_module modules/mod_actions.so
|
||||
LoadModule alias_module modules/mod_alias.so
|
||||
LoadModule allowmethods_module modules/mod_allowmethods.so
|
||||
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||
LoadModule auth_digest_module modules/mod_auth_digest.so
|
||||
LoadModule authn_anon_module modules/mod_authn_anon.so
|
||||
LoadModule authn_core_module modules/mod_authn_core.so
|
||||
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 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
|
||||
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
|
||||
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
|
||||
LoadModule data_module modules/mod_data.so
|
||||
LoadModule dbd_module modules/mod_dbd.so
|
||||
LoadModule deflate_module modules/mod_deflate.so
|
||||
LoadModule dir_module modules/mod_dir.so
|
||||
LoadModule dumpio_module modules/mod_dumpio.so
|
||||
LoadModule echo_module modules/mod_echo.so
|
||||
LoadModule env_module modules/mod_env.so
|
||||
LoadModule expires_module modules/mod_expires.so
|
||||
LoadModule ext_filter_module modules/mod_ext_filter.so
|
||||
LoadModule filter_module modules/mod_filter.so
|
||||
LoadModule headers_module modules/mod_headers.so
|
||||
LoadModule include_module modules/mod_include.so
|
||||
LoadModule info_module modules/mod_info.so
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
LoadModule logio_module modules/mod_logio.so
|
||||
LoadModule macro_module modules/mod_macro.so
|
||||
LoadModule mime_magic_module modules/mod_mime_magic.so
|
||||
LoadModule mime_module modules/mod_mime.so
|
||||
LoadModule negotiation_module modules/mod_negotiation.so
|
||||
LoadModule remoteip_module modules/mod_remoteip.so
|
||||
LoadModule reqtimeout_module modules/mod_reqtimeout.so
|
||||
LoadModule request_module modules/mod_request.so
|
||||
LoadModule rewrite_module modules/mod_rewrite.so
|
||||
LoadModule setenvif_module modules/mod_setenvif.so
|
||||
LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
|
||||
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
|
||||
LoadModule socache_dbm_module modules/mod_socache_dbm.so
|
||||
LoadModule socache_memcache_module modules/mod_socache_memcache.so
|
||||
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
|
||||
LoadModule status_module modules/mod_status.so
|
||||
LoadModule substitute_module modules/mod_substitute.so
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
LoadModule unique_id_module modules/mod_unique_id.so
|
||||
LoadModule unixd_module modules/mod_unixd.so
|
||||
LoadModule userdir_module modules/mod_userdir.so
|
||||
LoadModule version_module modules/mod_version.so
|
||||
LoadModule vhost_alias_module modules/mod_vhost_alias.so
|
||||
LoadModule watchdog_module modules/mod_watchdog.so
|
||||
|
1
00-brotli.conf
Normal file
1
00-brotli.conf
Normal file
@ -0,0 +1 @@
|
||||
LoadModule brotli_module modules/mod_brotli.so
|
3
00-dav.conf
Normal file
3
00-dav.conf
Normal file
@ -0,0 +1,3 @@
|
||||
LoadModule dav_module modules/mod_dav.so
|
||||
LoadModule dav_fs_module modules/mod_dav_fs.so
|
||||
LoadModule dav_lock_module modules/mod_dav_lock.so
|
1
00-lua.conf
Normal file
1
00-lua.conf
Normal file
@ -0,0 +1 @@
|
||||
LoadModule lua_module modules/mod_lua.so
|
23
00-mpm.conf
Normal file
23
00-mpm.conf
Normal file
@ -0,0 +1,23 @@
|
||||
# Select the MPM module which should be used by uncommenting exactly
|
||||
# one of the following LoadModule lines. See the httpd.conf(5) man
|
||||
# page for more information on changing the MPM.
|
||||
|
||||
# prefork MPM: Implements a non-threaded, pre-forking web server
|
||||
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
|
||||
#
|
||||
# NOTE: If enabling prefork, the httpd_graceful_shutdown SELinux
|
||||
# boolean should be enabled, to allow graceful stop/shutdown.
|
||||
#
|
||||
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
|
||||
|
||||
# worker MPM: Multi-Processing Module implementing a hybrid
|
||||
# multi-threaded multi-process web server
|
||||
# See: http://httpd.apache.org/docs/2.4/mod/worker.html
|
||||
#
|
||||
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
|
||||
|
||||
# event MPM: A variant of the worker MPM with the goal of consuming
|
||||
# threads only for connections with active processing
|
||||
# See: http://httpd.apache.org/docs/2.4/mod/event.html
|
||||
#
|
||||
#LoadModule mpm_event_module modules/mod_mpm_event.so
|
18
00-optional.conf
Normal file
18
00-optional.conf
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# This file lists modules included with the Apache HTTP Server
|
||||
# which are not enabled by default.
|
||||
#
|
||||
|
||||
#LoadModule asis_module modules/mod_asis.so
|
||||
#LoadModule buffer_module modules/mod_buffer.so
|
||||
#LoadModule heartbeat_module modules/mod_heartbeat.so
|
||||
#LoadModule heartmonitor_module modules/mod_heartmonitor.so
|
||||
#LoadModule usertrack_module modules/mod_usertrack.so
|
||||
#LoadModule dialup_module modules/mod_dialup.so
|
||||
#LoadModule charset_lite_module modules/mod_charset_lite.so
|
||||
#LoadModule log_debug_module modules/mod_log_debug.so
|
||||
#LoadModule log_forensic_module modules/mod_log_forensic.so
|
||||
#LoadModule ratelimit_module modules/mod_ratelimit.so
|
||||
#LoadModule reflector_module modules/mod_reflector.so
|
||||
#LoadModule sed_module modules/mod_sed.so
|
||||
#LoadModule speling_module modules/mod_speling.so
|
18
00-proxy.conf
Normal file
18
00-proxy.conf
Normal file
@ -0,0 +1,18 @@
|
||||
# This file configures all the proxy modules:
|
||||
LoadModule proxy_module modules/mod_proxy.so
|
||||
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
|
||||
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
|
||||
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
|
||||
LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
|
||||
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
|
||||
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
|
||||
LoadModule proxy_connect_module modules/mod_proxy_connect.so
|
||||
LoadModule proxy_express_module modules/mod_proxy_express.so
|
||||
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
|
||||
LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
|
||||
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
|
||||
LoadModule proxy_http_module modules/mod_proxy_http.so
|
||||
LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
|
||||
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
|
||||
LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
|
||||
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
|
3
00-proxyhtml.conf
Normal file
3
00-proxyhtml.conf
Normal file
@ -0,0 +1,3 @@
|
||||
# This file configures mod_proxy_html and mod_xml2enc:
|
||||
LoadModule xml2enc_module modules/mod_xml2enc.so
|
||||
LoadModule proxy_html_module modules/mod_proxy_html.so
|
1
00-ssl.conf
Normal file
1
00-ssl.conf
Normal file
@ -0,0 +1 @@
|
||||
LoadModule ssl_module modules/mod_ssl.so
|
2
00-systemd.conf
Normal file
2
00-systemd.conf
Normal file
@ -0,0 +1,2 @@
|
||||
# This file configures systemd module:
|
||||
LoadModule systemd_module modules/mod_systemd.so
|
14
01-cgi.conf
Normal file
14
01-cgi.conf
Normal file
@ -0,0 +1,14 @@
|
||||
# This configuration file loads a CGI module appropriate to the MPM
|
||||
# which has been configured in 00-mpm.conf. mod_cgid should be used
|
||||
# with a threaded MPM; mod_cgi with the prefork MPM.
|
||||
|
||||
<IfModule mpm_worker_module>
|
||||
LoadModule cgid_module modules/mod_cgid.so
|
||||
</IfModule>
|
||||
<IfModule mpm_event_module>
|
||||
LoadModule cgid_module modules/mod_cgid.so
|
||||
</IfModule>
|
||||
<IfModule mpm_prefork_module>
|
||||
LoadModule cgi_module modules/mod_cgi.so
|
||||
</IfModule>
|
||||
|
3
01-ldap.conf
Normal file
3
01-ldap.conf
Normal file
@ -0,0 +1,3 @@
|
||||
# This file configures the LDAP modules:
|
||||
LoadModule ldap_module modules/mod_ldap.so
|
||||
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
|
6
01-session.conf
Normal file
6
01-session.conf
Normal file
@ -0,0 +1,6 @@
|
||||
LoadModule session_module modules/mod_session.so
|
||||
LoadModule session_cookie_module modules/mod_session_cookie.so
|
||||
LoadModule session_dbd_module modules/mod_session_dbd.so
|
||||
LoadModule auth_form_module modules/mod_auth_form.so
|
||||
|
||||
#LoadModule session_crypto_module modules/mod_session_crypto.so
|
5
10-listen443.conf
Normal file
5
10-listen443.conf
Normal file
@ -0,0 +1,5 @@
|
||||
# This file is part of mod_ssl. It enables listening on port 443 when
|
||||
# socket activation is used.
|
||||
|
||||
[Socket]
|
||||
ListenStream=443
|
9
README.confd
Normal file
9
README.confd
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
This directory holds configuration files for the Apache HTTP Server;
|
||||
any files in this directory which have the ".conf" extension will be
|
||||
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.
|
10
README.confmod
Normal file
10
README.confmod
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
This directory holds configuration files for the Apache HTTP Server;
|
||||
any files in this directory which have the ".conf" extension will be
|
||||
processed as httpd configuration files. This directory contains
|
||||
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.
|
2
action-configtest.sh
Normal file
2
action-configtest.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec /sbin/apachectl configtest "$@"
|
2
action-graceful.sh
Normal file
2
action-graceful.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec /sbin/apachectl graceful "$@"
|
BIN
apache-poweredby.png
Normal file
BIN
apache-poweredby.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
74
apachectl.sh
Executable file
74
apachectl.sh
Executable file
@ -0,0 +1,74 @@
|
||||
#!/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
|
||||
|
191
apachectl.xml
Normal file
191
apachectl.xml
Normal file
@ -0,0 +1,191 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">[
|
||||
|
||||
]>
|
||||
<!--
|
||||
Copyright 2020 Red Hat, Inc.
|
||||
|
||||
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.
|
||||
-->
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<title>apachectl</title>
|
||||
<productname>httpd</productname>
|
||||
<author><contrib>Apache man page</contrib><othername>Apache Software Foundation contributors</othername></author>
|
||||
<author><contrib>Fedora man page</contrib><surname>Dana</surname><firstname>Frank</firstname></author>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>apachectl</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>apachectl</refname>
|
||||
<refpurpose>Server control interface for httpd</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv id='synopsis'>
|
||||
<cmdsynopsis>
|
||||
<command>apachectl</command>
|
||||
<arg choice='opt'><replaceable>command</replaceable> </arg>
|
||||
<sbr/>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<!-- body begins here -->
|
||||
<refsect1 id='description'>
|
||||
<title>Description</title>
|
||||
|
||||
<para><command>apachectl</command> 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
|
||||
<command>httpd</command> daemon.</para>
|
||||
|
||||
<para>The <command>apachectl</command> script takes one-word arguments like
|
||||
<option>start</option>,
|
||||
<option>restart</option>, and
|
||||
<option>stop</option>, and translates them
|
||||
into appropriate signals to <command>httpd</command>.</para>
|
||||
|
||||
<para>The <command>apachectl</command> script returns a 0 exit value on
|
||||
success, and >0 if an error occurs.</para>
|
||||
|
||||
<refsect2 id="compatibility">
|
||||
<title>Compatibility</title>
|
||||
|
||||
<para>The version of <command>apachectl</command> used on this
|
||||
system is a replacement script intended to be mostly (but not
|
||||
completely) compatible with version provided with
|
||||
<emphasis>Apache httpd</emphasis>. This
|
||||
<command>apachectl</command> mostly acts as a wrapper around
|
||||
<command>systemctl</command> and manipulates the
|
||||
<command>systemd</command> service for <command>httpd</command>.
|
||||
The interface to the <emphasis>Apache</emphasis> version of
|
||||
<command>apachectl</command> is described at <ulink
|
||||
url="https://httpd.apache.org/docs/2.4/programs/apachectl.html"/>.</para>
|
||||
|
||||
<para>The following differences are present in the version of
|
||||
<command>apachectl</command> present on this system:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>Option arguments passed when starting
|
||||
<command>httpd</command> are not allowed. These should be
|
||||
configured in the systemd service directly (see <citerefentry><refentrytitle>httpd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>).</para></listitem>
|
||||
|
||||
<listitem><para>The <command>"fullstatus"</command> option is
|
||||
not available.</para></listitem>
|
||||
|
||||
<listitem><para>The <command>"status"</command> option does
|
||||
not use or rely on the running server's
|
||||
<emphasis>server-status</emphasis> output.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id='options'>
|
||||
<title>Options</title>
|
||||
<variablelist remap='TP'>
|
||||
<varlistentry>
|
||||
<term><option>start</option></term>
|
||||
<listitem>
|
||||
<para>Start the Apache <command>httpd</command> daemon. Gives an error if it
|
||||
is already running. This is equivalent to <command>systemctl start httpd.service</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>stop</option></term>
|
||||
<listitem>
|
||||
<para>Stops the Apache <command>httpd</command> daemon. This is equivalent to
|
||||
<command>systemctl stop httpd.service</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>restart</option></term>
|
||||
<listitem>
|
||||
<para>Restarts the Apache <command>httpd</command> daemon. If the daemon is
|
||||
not running, it is started. This is equivalent
|
||||
to <command>systemctl restart httpd.service</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>status</option></term>
|
||||
<listitem>
|
||||
<para>Displays a brief status report. This is equivalent to <command>systemctl status httpd.service.</command></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>graceful</option></term>
|
||||
<listitem>
|
||||
<para>Gracefully restarts the Apache <command>httpd</command> 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
|
||||
<command>systemctl kill --signal=SIGUSR1 --kill-who=main httpd.service</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>graceful-stop</option></term>
|
||||
<listitem>
|
||||
<para>Gracefully stops the Apache <command>httpd</command> 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
|
||||
<command>systemctl kill --signal=SIGWINCH --kill-who=main httpd.service</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>configtest</option></term>
|
||||
<listitem>
|
||||
<para>Run a configuration file syntax test. It parses the configuration
|
||||
files and either reports <literal>Syntax OK</literal>
|
||||
or detailed information about the particular syntax error. This is
|
||||
equivalent to <command>httpd -t</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id='bugs'>
|
||||
<title>Bugs</title>
|
||||
<para>Please report bugs by filing an issue in Bugzilla via <ulink url='https://bugzilla.redhat.com/'/>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>httpd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>httpd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>httpd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
24
config.layout
Normal file
24
config.layout
Normal file
@ -0,0 +1,24 @@
|
||||
# Layout used in Fedora httpd packaging.
|
||||
<Layout Fedora>
|
||||
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
|
||||
</Layout>
|
11
gating.yaml
Normal file
11
gating.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- rhel-9
|
||||
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: baseos-ci.brew-build.acceptance-tier.functional}
|
||||
- !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-internal.functional}
|
||||
|
11
htcacheclean.service
Normal file
11
htcacheclean.service
Normal file
@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Disk Cache Cleaning Daemon for the Apache HTTP Server
|
||||
After=httpd.service
|
||||
Documentation=man:htcacheclean.service(8)
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=apache
|
||||
PIDFile=/run/httpd/htcacheclean/pid
|
||||
EnvironmentFile=/etc/sysconfig/htcacheclean
|
||||
ExecStart=/usr/sbin/htcacheclean -P /run/httpd/htcacheclean/pid -d $INTERVAL -p $CACHE_ROOT -l $LIMIT $OPTIONS
|
123
htcacheclean.service.xml
Normal file
123
htcacheclean.service.xml
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
||||
|
||||
]>
|
||||
<!--
|
||||
Copyright 2018 Red Hat, Inc.
|
||||
|
||||
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 overning permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<title>htcacheclean systemd unit</title>
|
||||
<productname>httpd</productname>
|
||||
<author><contrib>Author</contrib><surname>Orton</surname><firstname>Joe</firstname><email>jorton@redhat.com</email></author>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>htcacheclean.service</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>htcacheclean.service</refname>
|
||||
<refpurpose>htcacheclean unit file for systemd</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para>
|
||||
<filename>/usr/lib/systemd/system/htcacheclean.service</filename>
|
||||
</para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This manual page describes the <command>systemd</command>
|
||||
unit file for the <command>htcacheclean</command> daemon. This
|
||||
unit file provides a service which runs
|
||||
<command>htcacheclean</command> in daemon mode,
|
||||
periodically cleaning the disk cache root to ensure disk space
|
||||
usage is within configured limits.</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>The service is configured by configuration file
|
||||
<filename>/etc/sysconfig/htcacheclean</filename>. The following
|
||||
variables are used, following standard <command>systemd</command>
|
||||
<varname>EnvironmentFile=</varname> syntax:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><varname>INTERVAL=</varname></term>
|
||||
|
||||
<listitem><para>Sets the interval between cache clean runs, in
|
||||
minutes. By default this is configured as
|
||||
<emphasis>15</emphasis>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>CACHE_ROOT=</varname></term>
|
||||
|
||||
<listitem><para>Sets the directory name used for the cache
|
||||
root. By default this is configured as
|
||||
<filename>/var/cache/httpd/proxy</filename>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>LIMIT=</varname></term>
|
||||
|
||||
<listitem><para>Sets the total disk cache space limit, in
|
||||
bytes. Use a <emphasis>K</emphasis> or <emphasis>M</emphasis>
|
||||
suffix to signify kilobytes or megabytes. By default this is
|
||||
set to <emphasis>100M</emphasis>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>OPTIONS=</varname></term>
|
||||
|
||||
<listitem><para>Any other options to pass to
|
||||
<command>htcacheclean</command>.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Files</title>
|
||||
|
||||
<para><filename>/usr/lib/systemd/system/htcacheclean.service</filename>,
|
||||
<filename>/etc/sysconfig/htcacheclean</filename></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>htcacheclean</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>httpd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>httpd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- LocalWords: systemd httpd htcacheclean
|
||||
-->
|
16
htcacheclean.sysconf
Normal file
16
htcacheclean.sysconf
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Configuration options for systemd service, htcacheclean.service.
|
||||
# See htcacheclean(8) for more information on available options.
|
||||
#
|
||||
|
||||
# Interval between cache clean runs, in minutes
|
||||
INTERVAL=15
|
||||
|
||||
# Default cache root.
|
||||
CACHE_ROOT=/var/cache/httpd/proxy
|
||||
|
||||
# Cache size limit in bytes (K=Kbytes, M=Mbytes)
|
||||
LIMIT=100M
|
||||
|
||||
# Any other options...
|
||||
OPTIONS=
|
58
httpd-2.4.28-apxs.patch
Normal file
58
httpd-2.4.28-apxs.patch
Normal file
@ -0,0 +1,58 @@
|
||||
diff --git a/support/apxs.in b/support/apxs.in
|
||||
index ad1287f..efcfcf6 100644
|
||||
--- a/support/apxs.in
|
||||
+++ b/support/apxs.in
|
||||
@@ -25,7 +25,18 @@ package apxs;
|
||||
|
||||
my %config_vars = ();
|
||||
|
||||
-my $installbuilddir = "@exp_installbuilddir@";
|
||||
+# Awful hack to make apxs libdir-agnostic:
|
||||
+my $pkg_config = "/usr/bin/pkg-config";
|
||||
+if (! -x "$pkg_config") {
|
||||
+ error("$pkg_config not found!");
|
||||
+ exit(1);
|
||||
+}
|
||||
+
|
||||
+my $libdir = `pkg-config --variable=libdir apr-1`;
|
||||
+chomp $libdir;
|
||||
+
|
||||
+my $installbuilddir = $libdir . "/httpd/build";
|
||||
+
|
||||
get_config_vars("$installbuilddir/config_vars.mk",\%config_vars);
|
||||
|
||||
# read the configuration variables once
|
||||
@@ -275,7 +286,7 @@ if ($opt_g) {
|
||||
$data =~ s|%NAME%|$name|sg;
|
||||
$data =~ s|%TARGET%|$CFG_TARGET|sg;
|
||||
$data =~ s|%PREFIX%|$prefix|sg;
|
||||
- $data =~ s|%INSTALLBUILDDIR%|$installbuilddir|sg;
|
||||
+ $data =~ s|%LIBDIR%|$libdir|sg;
|
||||
|
||||
my ($mkf, $mods, $src) = ($data =~ m|^(.+)-=#=-\n(.+)-=#=-\n(.+)|s);
|
||||
|
||||
@@ -453,11 +464,11 @@ if ($opt_c) {
|
||||
my $ldflags = "$CFG_LDFLAGS";
|
||||
if ($opt_p == 1) {
|
||||
|
||||
- my $apr_libs=`$apr_config --cflags --ldflags --link-libtool --libs`;
|
||||
+ my $apr_libs=`$apr_config --cflags --ldflags --link-libtool`;
|
||||
chomp($apr_libs);
|
||||
my $apu_libs="";
|
||||
if ($apr_major_version < 2) {
|
||||
- $apu_libs=`$apu_config --ldflags --link-libtool --libs`;
|
||||
+ $apu_libs=`$apu_config --ldflags --link-libtool`;
|
||||
chomp($apu_libs);
|
||||
}
|
||||
|
||||
@@ -672,8 +683,8 @@ __DATA__
|
||||
|
||||
builddir=.
|
||||
top_srcdir=%PREFIX%
|
||||
-top_builddir=%PREFIX%
|
||||
-include %INSTALLBUILDDIR%/special.mk
|
||||
+top_builddir=%LIBDIR%/httpd
|
||||
+include %LIBDIR%/httpd/build/special.mk
|
||||
|
||||
# the used tools
|
||||
APACHECTL=apachectl
|
29
httpd-2.4.28-icons.patch
Normal file
29
httpd-2.4.28-icons.patch
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
- 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
|
||||
|
||||
diff --git a/docs/conf/extra/httpd-autoindex.conf.in b/docs/conf/extra/httpd-autoindex.conf.in
|
||||
index 51b02ed..dd6f2c6 100644
|
||||
--- a/docs/conf/extra/httpd-autoindex.conf.in
|
||||
+++ b/docs/conf/extra/httpd-autoindex.conf.in
|
||||
@@ -21,7 +21,7 @@ IndexOptions FancyIndexing HTMLTable VersionSort
|
||||
Alias /icons/ "@exp_iconsdir@/"
|
||||
|
||||
<Directory "@exp_iconsdir@">
|
||||
- Options Indexes MultiViews
|
||||
+ Options Indexes MultiViews FollowSymlinks
|
||||
AllowOverride None
|
||||
Require all granted
|
||||
</Directory>
|
||||
@@ -53,7 +53,8 @@ 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/bomb.gif */core.*
|
||||
|
||||
AddIcon /icons/back.gif ..
|
||||
AddIcon /icons/hand.right.gif README
|
81
httpd-2.4.28-r1811831.patch
Normal file
81
httpd-2.4.28-r1811831.patch
Normal file
@ -0,0 +1,81 @@
|
||||
diff --git a/server/util_script.c b/server/util_script.c
|
||||
index 4121ae0..b7f8674 100644
|
||||
--- a/server/util_script.c
|
||||
+++ b/server/util_script.c
|
||||
@@ -92,9 +92,21 @@ static void add_unless_null(apr_table_t *table, const char *name, const char *va
|
||||
}
|
||||
}
|
||||
|
||||
-static void env2env(apr_table_t *table, const char *name)
|
||||
+/* Sets variable @name in table @dest from r->subprocess_env if
|
||||
+ * available, else from the environment, else from @fallback if
|
||||
+ * non-NULL. */
|
||||
+static void env2env(apr_table_t *dest, request_rec *r,
|
||||
+ const char *name, const char *fallback)
|
||||
{
|
||||
- add_unless_null(table, name, getenv(name));
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = apr_table_get(r->subprocess_env, name);
|
||||
+ if (!val)
|
||||
+ val = apr_pstrdup(r->pool, getenv(name));
|
||||
+ if (!val)
|
||||
+ val = apr_pstrdup(r->pool, fallback);
|
||||
+ if (val)
|
||||
+ apr_table_addn(dest, name, val);
|
||||
}
|
||||
|
||||
AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
|
||||
@@ -211,37 +223,29 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r)
|
||||
add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
|
||||
}
|
||||
|
||||
- env_temp = apr_table_get(r->subprocess_env, "PATH");
|
||||
- if (env_temp == NULL) {
|
||||
- env_temp = getenv("PATH");
|
||||
- }
|
||||
- if (env_temp == NULL) {
|
||||
- env_temp = DEFAULT_PATH;
|
||||
- }
|
||||
- apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp));
|
||||
-
|
||||
+ env2env(e, r, "PATH", DEFAULT_PATH);
|
||||
#if defined(WIN32)
|
||||
- env2env(e, "SystemRoot");
|
||||
- env2env(e, "COMSPEC");
|
||||
- env2env(e, "PATHEXT");
|
||||
- env2env(e, "WINDIR");
|
||||
+ env2env(e, r, "SystemRoot", NULL);
|
||||
+ env2env(e, r, "COMSPEC", NULL);
|
||||
+ env2env(e, r, "PATHEXT", NULL);
|
||||
+ env2env(e, r, "WINDIR", NULL);
|
||||
#elif defined(OS2)
|
||||
- env2env(e, "COMSPEC");
|
||||
- env2env(e, "ETC");
|
||||
- env2env(e, "DPATH");
|
||||
- env2env(e, "PERLLIB_PREFIX");
|
||||
+ env2env(e, r, "COMSPEC", NULL);
|
||||
+ env2env(e, r, "ETC", NULL);
|
||||
+ env2env(e, r, "DPATH", NULL);
|
||||
+ env2env(e, r, "PERLLIB_PREFIX", NULL);
|
||||
#elif defined(BEOS)
|
||||
- env2env(e, "LIBRARY_PATH");
|
||||
+ env2env(e, r, "LIBRARY_PATH", NULL);
|
||||
#elif defined(DARWIN)
|
||||
- env2env(e, "DYLD_LIBRARY_PATH");
|
||||
+ env2env(e, r, "DYLD_LIBRARY_PATH", NULL);
|
||||
#elif defined(_AIX)
|
||||
- env2env(e, "LIBPATH");
|
||||
+ env2env(e, r, "LIBPATH", NULL);
|
||||
#elif defined(__HPUX__)
|
||||
/* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */
|
||||
- env2env(e, "SHLIB_PATH");
|
||||
- env2env(e, "LD_LIBRARY_PATH");
|
||||
+ env2env(e, r, "SHLIB_PATH", NULL);
|
||||
+ env2env(e, r, "LD_LIBRARY_PATH", NULL);
|
||||
#else /* Some Unix */
|
||||
- env2env(e, "LD_LIBRARY_PATH");
|
||||
+ env2env(e, r, "LD_LIBRARY_PATH", NULL);
|
||||
#endif
|
||||
|
||||
apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
|
300
httpd-2.4.28-socket-activation.patch
Normal file
300
httpd-2.4.28-socket-activation.patch
Normal file
@ -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 <unistd.h>
|
||||
#endif
|
||||
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+#include <systemd/sd-daemon.h>
|
||||
+#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);
|
||||
}
|
||||
|
16
httpd-2.4.28-statements-comment.patch
Normal file
16
httpd-2.4.28-statements-comment.patch
Normal file
@ -0,0 +1,16 @@
|
||||
diff --git a/modules/aaa/mod_access_compat.c b/modules/aaa/mod_access_compat.c
|
||||
index 3023803..2edf440 100644
|
||||
--- a/modules/aaa/mod_access_compat.c
|
||||
+++ b/modules/aaa/mod_access_compat.c
|
||||
@@ -152,6 +152,11 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from,
|
||||
if (strcasecmp(from, "from"))
|
||||
return "allow and deny must be followed by 'from'";
|
||||
|
||||
+ s = ap_strchr(where, '#');
|
||||
+ if (s) {
|
||||
+ *s = '\0';
|
||||
+ }
|
||||
+
|
||||
a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys);
|
||||
a->x.from = where;
|
||||
a->limited = cmd->limited;
|
22
httpd-2.4.32-export.patch
Normal file
22
httpd-2.4.32-export.patch
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
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
|
||||
|
||||
diff --git a/server/Makefile.in b/server/Makefile.in
|
||||
index 1fa3344..f635d76 100644
|
||||
--- a/server/Makefile.in
|
||||
+++ b/server/Makefile.in
|
||||
@@ -60,9 +60,6 @@ export_files:
|
||||
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
|
19
httpd-2.4.34-CVE-2019-9511-and-9516-and-9517.patch
Normal file
19
httpd-2.4.34-CVE-2019-9511-and-9516-and-9517.patch
Normal file
@ -0,0 +1,19 @@
|
||||
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
|
||||
index 16e39be..2543693 100644
|
||||
--- a/server/mpm/event/event.c
|
||||
+++ b/server/mpm/event/event.c
|
||||
@@ -1111,10 +1111,11 @@ read_request:
|
||||
"network write failure in core output filter");
|
||||
cs->pub.state = CONN_STATE_LINGER;
|
||||
}
|
||||
- else if (c->data_in_output_filters) {
|
||||
+ else if (c->data_in_output_filters ||
|
||||
+ cs->pub.sense == CONN_SENSE_WANT_READ) {
|
||||
/* Still in WRITE_COMPLETION_STATE:
|
||||
- * Set a write timeout for this connection, and let the
|
||||
- * event thread poll for writeability.
|
||||
+ * Set a read/write timeout for this connection, and let the
|
||||
+ * event thread poll for read/writeability.
|
||||
*/
|
||||
cs->queue_timestamp = apr_time_now();
|
||||
notify_suspend(cs);
|
113
httpd-2.4.35-apachectl.patch
Normal file
113
httpd-2.4.35-apachectl.patch
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/docs/man/apachectl.8 b/docs/man/apachectl.8
|
||||
index 870a048..32d3ee5 100644
|
||||
--- a/docs/man/apachectl.8
|
||||
+++ b/docs/man/apachectl.8
|
||||
@@ -74,7 +74,7 @@ Restarts the Apache httpd daemon\&. If the daemon is not running, it is started\
|
||||
Displays a full status report from mod_status\&. For this to work, you need to have mod_status enabled on your server and a text-based browser such as \fBlynx\fR available on your system\&. The URL used to access the status report can be set by editing the \fBSTATUSURL\fR variable in the script\&.
|
||||
.TP
|
||||
\fBstatus\fR
|
||||
-Displays a brief status report\&. Similar to the \fBfullstatus\fR option, except that the list of requests currently being served is omitted\&.
|
||||
+Displays a brief status report using systemd\&.
|
||||
.TP
|
||||
\fBgraceful\fR
|
||||
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 command automatically checks the configuration files as in \fBconfigtest\fR before initiating the restart to make sure Apache doesn't die\&. This is equivalent to \fBapachectl -k graceful\fR\&.
|
||||
diff --git a/support/apachectl.in b/support/apachectl.in
|
||||
index 3281c2e..8ce6f2b 100644
|
||||
--- a/support/apachectl.in
|
||||
+++ b/support/apachectl.in
|
||||
@@ -44,19 +44,20 @@ 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"
|
||||
+
|
||||
#
|
||||
# Set this variable to a command that increases the maximum
|
||||
# number of file descriptors allowed per child process. This is
|
||||
@@ -76,9 +77,46 @@ 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` /usr/sbin/httpd $OPTIONS -t
|
||||
+else
|
||||
+ /usr/sbin/httpd $OPTIONS -t
|
||||
+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 -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)
|
||||
@@ -88,17 +126,14 @@ startssl|sslstart|start-SSL)
|
||||
ERROR=2
|
||||
;;
|
||||
configtest)
|
||||
- $HTTPD -t
|
||||
- ERROR=$?
|
||||
- ;;
|
||||
-status)
|
||||
- $LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
|
||||
+ testconfig
|
||||
;;
|
||||
fullstatus)
|
||||
+ checklynx
|
||||
$LYNX $STATUSURL
|
||||
;;
|
||||
*)
|
||||
- $HTTPD "$@"
|
||||
+ /usr/sbin/httpd $OPTIONS "$@"
|
||||
ERROR=$?
|
||||
esac
|
||||
|
82
httpd-2.4.35-cachehardmax.patch
Normal file
82
httpd-2.4.35-cachehardmax.patch
Normal file
@ -0,0 +1,82 @@
|
||||
diff --git a/modules/cache/cache_util.h b/modules/cache/cache_util.h
|
||||
index 6b92151..4c42a8e 100644
|
||||
--- a/modules/cache/cache_util.h
|
||||
+++ b/modules/cache/cache_util.h
|
||||
@@ -195,6 +195,9 @@ typedef struct {
|
||||
unsigned int store_nostore_set:1;
|
||||
unsigned int enable_set:1;
|
||||
unsigned int disable_set:1;
|
||||
+ /* treat maxex as hard limit */
|
||||
+ unsigned int hardmaxex:1;
|
||||
+ unsigned int hardmaxex_set:1;
|
||||
} cache_dir_conf;
|
||||
|
||||
/* A linked-list of authn providers. */
|
||||
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c
|
||||
index 56a09f5..41015b5 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)
|
||||
exp = date + dconf->defex;
|
||||
}
|
||||
}
|
||||
+ /* else, forcibly cap the expiry date if required */
|
||||
+ else if (dconf->hardmaxex && (date + dconf->maxex) < exp) {
|
||||
+ exp = date + dconf->maxex;
|
||||
+ }
|
||||
+
|
||||
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)
|
||||
|
||||
/* array of providers for this URL space */
|
||||
dconf->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
|
||||
-
|
||||
+ /* flag; treat maxex as hard limit */
|
||||
+ dconf->hardmaxex = 0;
|
||||
+ dconf->hardmaxex_set = 0;
|
||||
return dconf;
|
||||
}
|
||||
|
||||
@@ -2004,7 +2011,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;
|
||||
-
|
||||
+ new->hardmaxex =
|
||||
+ (add->hardmaxex_set == 0)
|
||||
+ ? base->hardmaxex
|
||||
+ : add->hardmaxex;
|
||||
return new;
|
||||
}
|
||||
|
||||
@@ -2332,12 +2342,18 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy,
|
||||
}
|
||||
|
||||
static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
|
||||
- const char *arg)
|
||||
+ const char *arg, const char *hard)
|
||||
{
|
||||
cache_dir_conf *dconf = (cache_dir_conf *)dummy;
|
||||
|
||||
dconf->maxex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
|
||||
dconf->maxex_set = 1;
|
||||
+
|
||||
+ if (hard && strcasecmp(hard, "hard") == 0) {
|
||||
+ dconf->hardmaxex = 1;
|
||||
+ dconf->hardmaxex_set = 1;
|
||||
+ }
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2545,7 +2561,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"),
|
||||
- AP_INIT_TAKE1("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
+ AP_INIT_TAKE12("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
"The maximum time in seconds to cache a document"),
|
||||
AP_INIT_TAKE1("CacheMinExpire", set_cache_minex, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
"The minimum time in seconds to cache a document"),
|
37
httpd-2.4.35-corelimit.patch
Normal file
37
httpd-2.4.35-corelimit.patch
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
Bump up the core size limit if CoreDumpDirectory is
|
||||
configured.
|
||||
|
||||
Upstream-Status: Was discussed but there are competing desires;
|
||||
there are portability oddities here too.
|
||||
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index aa62e15..ec74029 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -4952,6 +4952,25 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte
|
||||
}
|
||||
apr_pool_cleanup_register(pconf, NULL, ap_mpm_end_gen_helper,
|
||||
apr_pool_cleanup_null);
|
||||
+
|
||||
+#ifdef RLIMIT_CORE
|
||||
+ if (ap_coredumpdir_configured) {
|
||||
+ struct rlimit lim;
|
||||
+
|
||||
+ if (getrlimit(RLIMIT_CORE, &lim) == 0 && lim.rlim_cur == 0) {
|
||||
+ lim.rlim_cur = lim.rlim_max;
|
||||
+ if (setrlimit(RLIMIT_CORE, &lim) == 0) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
|
||||
+ "core dump file size limit raised to %lu bytes",
|
||||
+ lim.rlim_cur);
|
||||
+ } else {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, errno, NULL,
|
||||
+ "core dump file size is zero, setrlimit failed");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
return OK;
|
||||
}
|
||||
|
21
httpd-2.4.35-deplibs.patch
Normal file
21
httpd-2.4.35-deplibs.patch
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Link straight against .la files.
|
||||
|
||||
Upstream-Status: vendor specific
|
||||
|
||||
diff --git a/configure.in b/configure.in
|
||||
index 9feaceb..82bfeef 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -784,9 +784,9 @@ 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 --libs`"
|
||||
+ AP_LIBS="$AP_LIBS `$apu_config --avoid-ldap --link-libtool`"
|
||||
fi
|
||||
-AP_LIBS="$AP_LIBS `$apr_config --link-libtool --libs`"
|
||||
+AP_LIBS="$AP_LIBS `$apr_config --link-libtool`"
|
||||
APACHE_SUBST(AP_LIBS)
|
||||
APACHE_SUBST(AP_BUILD_SRCLIB_DIRS)
|
||||
APACHE_SUBST(AP_CLEAN_SRCLIB_DIRS)
|
77
httpd-2.4.35-detect-systemd.patch
Normal file
77
httpd-2.4.35-detect-systemd.patch
Normal file
@ -0,0 +1,77 @@
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index ea8366e..06b8c5a 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -4,7 +4,7 @@ CLEAN_SUBDIRS = test
|
||||
|
||||
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/acinclude.m4 b/acinclude.m4
|
||||
index ce1d637..0ad0c13 100644
|
||||
--- a/acinclude.m4
|
||||
+++ b/acinclude.m4
|
||||
@@ -606,6 +606,30 @@ AC_DEFUN([APACHE_CHECK_OPENSSL],[
|
||||
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 --git a/configure.in b/configure.in
|
||||
index 82bfeef..eedba50 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -234,6 +234,7 @@ if test "$PCRE_CONFIG" != "false"; then
|
||||
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 +505,8 @@ if test "$ac_cv_struct_tm_gmtoff" = "yes"; then
|
||||
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
|
||||
@@ -677,6 +680,7 @@ APACHE_SUBST(OS_DIR)
|
||||
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 ""'
|
125
httpd-2.4.35-freebind.patch
Normal file
125
httpd-2.4.35-freebind.patch
Normal file
@ -0,0 +1,125 @@
|
||||
diff --git a/include/ap_listen.h b/include/ap_listen.h
|
||||
index 58c2574..1a53292 100644
|
||||
--- a/include/ap_listen.h
|
||||
+++ b/include/ap_listen.h
|
||||
@@ -137,6 +137,9 @@ AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, void *dummy
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_listencbratio(cmd_parms *cmd, void *dummy, const char *arg);
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
|
||||
int argc, char *const argv[]);
|
||||
+AP_DECLARE_NONSTD(const char *) ap_set_freelistener(cmd_parms *cmd, void *dummy,
|
||||
+ int argc, char *const argv[]);
|
||||
+
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
|
||||
const char *arg);
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
|
||||
@@ -150,6 +153,8 @@ AP_INIT_TAKE1("ListenCoresBucketsRatio", ap_set_listencbratio, NULL, RSRC_CONF,
|
||||
"Ratio between the number of CPU cores (online) and the number of listeners buckets"), \
|
||||
AP_INIT_TAKE_ARGV("Listen", ap_set_listener, NULL, RSRC_CONF, \
|
||||
"A port number or a numeric IP address and a port number, and an optional protocol"), \
|
||||
+AP_INIT_TAKE_ARGV("ListenFree", ap_set_freelistener, NULL, RSRC_CONF, \
|
||||
+ "A port number or a numeric IP address and a port number, and an optional protocol"), \
|
||||
AP_INIT_TAKE1("SendBufferSize", ap_set_send_buffer_size, NULL, RSRC_CONF, \
|
||||
"Send buffer size in bytes"), \
|
||||
AP_INIT_TAKE1("ReceiveBufferSize", ap_set_receive_buffer_size, NULL, \
|
||||
diff --git a/server/listen.c b/server/listen.c
|
||||
index 1a6c1d3..d375fee 100644
|
||||
--- a/server/listen.c
|
||||
+++ b/server/listen.c
|
||||
@@ -63,6 +63,7 @@ static int ap_listenbacklog;
|
||||
static int ap_listencbratio;
|
||||
static int send_buffer_size;
|
||||
static int receive_buffer_size;
|
||||
+static int ap_listenfreebind;
|
||||
#ifdef HAVE_SYSTEMD
|
||||
static int use_systemd = -1;
|
||||
#endif
|
||||
@@ -162,6 +163,21 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server, int do_bind_
|
||||
}
|
||||
#endif
|
||||
|
||||
+
|
||||
+#if defined(APR_SO_FREEBIND)
|
||||
+ if (ap_listenfreebind) {
|
||||
+ if (apr_socket_opt_set(s, APR_SO_FREEBIND, one) < 0) {
|
||||
+ stat = apr_get_netos_error();
|
||||
+ ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02182)
|
||||
+ "make_sock: apr_socket_opt_set: "
|
||||
+ "error setting APR_SO_FREEBIND");
|
||||
+ apr_socket_close(s);
|
||||
+ return stat;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
if (do_bind_listen) {
|
||||
#if APR_HAVE_IPV6
|
||||
if (server->bind_addr->family == APR_INET6) {
|
||||
@@ -956,6 +972,7 @@ AP_DECLARE(void) ap_listen_pre_config(void)
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
|
||||
int argc, char *const argv[])
|
||||
{
|
||||
@@ -1016,6 +1033,14 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
|
||||
return alloc_listener(cmd->server->process, host, port, proto, NULL);
|
||||
}
|
||||
|
||||
+AP_DECLARE_NONSTD(const char *) ap_set_freelistener(cmd_parms *cmd, void *dummy,
|
||||
+ int argc,
|
||||
+ char *const argv[])
|
||||
+{
|
||||
+ ap_listenfreebind = 1;
|
||||
+ return ap_set_listener(cmd, dummy, argc, argv);
|
||||
+}
|
||||
+
|
||||
AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,
|
||||
void *dummy,
|
||||
const char *arg)
|
||||
diff --git a/docs/manual/mod/mpm_common.html.en b/docs/manual/mod/mpm_common.html.en
|
||||
index 5d688e4..eb66c19 100644
|
||||
--- a/docs/manual/mod/mpm_common.html.en
|
||||
+++ b/docs/manual/mod/mpm_common.html.en
|
||||
@@ -42,6 +42,7 @@ more than one multi-processing module (MPM)</td></tr>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#enableexceptionhook">EnableExceptionHook</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#gracefulshutdowntimeout">GracefulShutdownTimeout</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#listen">Listen</a></li>
|
||||
+<li><img alt="" src="../images/down.gif" /> <a href="#listenfree">ListenFree</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#listenbacklog">ListenBackLog</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#listencoresbucketsratio">ListenCoresBucketsRatio</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#maxconnectionsperchild">MaxConnectionsPerChild</a></li>
|
||||
@@ -233,6 +234,31 @@ discussion of the <code>Address already in use</code> error message,
|
||||
including other causes.</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
+
|
||||
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
+<div class="directive-section"><h2><a name="ListenFree" id="ListenFree">ListenFree</a> <a name="listenfree" id="listenfree">Directive</a></h2>
|
||||
+<table class="directive">
|
||||
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>IP addresses and ports that the server
|
||||
+listens to. Doesn't require IP address to be up</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>ListenFree [<var>IP-address</var>:]<var>portnumber</var> [<var>protocol</var>]</code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>MPM</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td><code class="module"><a href="../mod/event.html">event</a></code>, <code class="module"><a href="../mod/worker.html">worker</a></code>, <code class="module"><a href="../mod/prefork.html">prefork</a></code>, <code class="module"><a href="../mod/mpm_winnt.html">mpm_winnt</a></code>, <code class="module"><a href="../mod/mpm_netware.html">mpm_netware</a></code>, <code class="module"><a href="../mod/mpmt_os2.html">mpmt_os2</a></code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>This directive is currently available only in Red Hat Enterprise Linux</td></tr>
|
||||
+</table>
|
||||
+ <p>The <code class="directive">ListenFree</code> directive is
|
||||
+ identical to the <code class="directive">Listen</code> directive.
|
||||
+ The only difference is in the usage of the IP_FREEBIND socket
|
||||
+ option, which is enabled by default with <code class="directive">ListenFree</code>.
|
||||
+ If IP_FREEBIND is enabled, it allows httpd to bind to an IP
|
||||
+ address that is nonlocal or does not (yet) exist. This allows httpd to
|
||||
+ listen on a socket without requiring the underlying network interface
|
||||
+ or the specified dynamic IP address to be up at the time when httpd
|
||||
+ is trying to bind to it.
|
||||
+ </p>
|
||||
+</div>
|
||||
+
|
||||
+
|
||||
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
<div class="directive-section"><h2><a name="ListenBackLog" id="ListenBackLog">ListenBackLog</a> <a name="listenbacklog" id="listenbacklog">Directive</a></h2>
|
||||
<table class="directive">
|
||||
|
46
httpd-2.4.35-full-release.patch
Normal file
46
httpd-2.4.35-full-release.patch
Normal file
@ -0,0 +1,46 @@
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index cb8e463..daf76b3 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -3430,6 +3430,7 @@ enum server_token_type {
|
||||
SrvTk_MINIMAL, /* eg: Apache/2.0.41 */
|
||||
SrvTk_OS, /* eg: Apache/2.0.41 (UNIX) */
|
||||
SrvTk_FULL, /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
|
||||
+ SrvTk_FULL_RELEASE, /* eg: Apache/2.0.41 (UNIX) (Release 32.el7) PHP/4.2.2 FooBar/1.2b */
|
||||
SrvTk_PRODUCT_ONLY /* eg: Apache */
|
||||
};
|
||||
static enum server_token_type ap_server_tokens = SrvTk_FULL;
|
||||
@@ -3506,7 +3507,10 @@ static void set_banner(apr_pool_t *pconf)
|
||||
else if (ap_server_tokens == SrvTk_MAJOR) {
|
||||
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
|
||||
}
|
||||
- else {
|
||||
+ else if (ap_server_tokens == SrvTk_FULL_RELEASE) {
|
||||
+ ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ") (Release @RELEASE@)");
|
||||
+ }
|
||||
+ else {
|
||||
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
|
||||
}
|
||||
|
||||
@@ -3514,7 +3518,7 @@ static void set_banner(apr_pool_t *pconf)
|
||||
* Lock the server_banner string if we're not displaying
|
||||
* the full set of tokens
|
||||
*/
|
||||
- if (ap_server_tokens != SrvTk_FULL) {
|
||||
+ if (ap_server_tokens != SrvTk_FULL && ap_server_tokens != SrvTk_FULL_RELEASE) {
|
||||
banner_locked++;
|
||||
}
|
||||
server_description = AP_SERVER_BASEVERSION " (" PLATFORM ")";
|
||||
@@ -3547,8 +3551,11 @@ static const char *set_serv_tokens(cmd_parms *cmd, void *dummy,
|
||||
else if (!strcasecmp(arg, "Full")) {
|
||||
ap_server_tokens = SrvTk_FULL;
|
||||
}
|
||||
+ else if (!strcasecmp(arg, "Full-Release")) {
|
||||
+ ap_server_tokens = SrvTk_FULL_RELEASE;
|
||||
+ }
|
||||
else {
|
||||
- return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', or 'Full'";
|
||||
+ return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', 'Full' or 'Full-Release'";
|
||||
}
|
||||
|
||||
return NULL;
|
15
httpd-2.4.35-ocsp-wrong-ctx.patch
Normal file
15
httpd-2.4.35-ocsp-wrong-ctx.patch
Normal file
@ -0,0 +1,15 @@
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index a5e86e4..6611610 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1823,8 +1823,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
|
||||
/*
|
||||
* Perform OCSP-based revocation checks
|
||||
*/
|
||||
- if (ok && ((sc->server->ocsp_mask & SSL_OCSPCHECK_CHAIN) ||
|
||||
- (errdepth == 0 && (sc->server->ocsp_mask & SSL_OCSPCHECK_LEAF)))) {
|
||||
+ if (ok && ((mctx->ocsp_mask & SSL_OCSPCHECK_CHAIN) ||
|
||||
+ (errdepth == 0 && (mctx->ocsp_mask & SSL_OCSPCHECK_LEAF)))) {
|
||||
/* If there was an optional verification error, it's not
|
||||
* possible to perform OCSP validation since the issuer may be
|
||||
* missing/untrusted. Fail in that case. */
|
16
httpd-2.4.35-r1633085.patch
Normal file
16
httpd-2.4.35-r1633085.patch
Normal file
@ -0,0 +1,16 @@
|
||||
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
|
||||
index d52d5e3..8a57659 100644
|
||||
--- a/modules/ssl/ssl_engine_io.c
|
||||
+++ b/modules/ssl/ssl_engine_io.c
|
||||
@@ -1415,6 +1415,11 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
|
||||
"\"SSLVerifyClient optional_no_ca\" "
|
||||
"configuration");
|
||||
ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server);
|
||||
+
|
||||
+ /* on session resumption ssl_callback_SSLVerify()
|
||||
+ * will not be called, therefore we have to set it here
|
||||
+ */
|
||||
+ sslconn->verify_info = "GENEROUS";
|
||||
}
|
||||
else {
|
||||
const char *error = sslconn->verify_error ?
|
140
httpd-2.4.35-r1738878.patch
Normal file
140
httpd-2.4.35-r1738878.patch
Normal file
@ -0,0 +1,140 @@
|
||||
diff --git a/modules/proxy/ajp.h b/modules/proxy/ajp.h
|
||||
index c119a7e..267150a 100644
|
||||
--- a/modules/proxy/ajp.h
|
||||
+++ b/modules/proxy/ajp.h
|
||||
@@ -413,12 +413,14 @@ apr_status_t ajp_ilink_receive(apr_socket_t *sock, ajp_msg_t *msg);
|
||||
* @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.
|
||||
diff --git a/modules/proxy/ajp_header.c b/modules/proxy/ajp_header.c
|
||||
index 67353a7..680a8f3 100644
|
||||
--- a/modules/proxy/ajp_header.c
|
||||
+++ b/modules/proxy/ajp_header.c
|
||||
@@ -213,7 +213,8 @@ AJPV13_REQUEST/AJPV14_REQUEST=
|
||||
|
||||
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 @@ static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
|
||||
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 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg,
|
||||
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 @@ apr_status_t ajp_send_header(apr_socket_t *sock,
|
||||
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");
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index 69a35ce..800ede1 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -327,6 +327,12 @@ static const char *set_worker_param(apr_pool_t *p,
|
||||
worker->s->response_field_size = (s ? s : HUGE_STRING_LEN);
|
||||
worker->s->response_field_size_set = 1;
|
||||
}
|
||||
+ 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 (set_worker_hc_param_f) {
|
||||
return set_worker_hc_param_f(p, s, worker, key, val, NULL);
|
||||
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
|
||||
index aabd09f..3419023 100644
|
||||
--- a/modules/proxy/mod_proxy.h
|
||||
+++ b/modules/proxy/mod_proxy.h
|
||||
@@ -357,6 +357,7 @@ PROXY_WORKER_HC_FAIL )
|
||||
#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
|
||||
|
||||
@@ -450,6 +451,7 @@ typedef struct {
|
||||
hcmethod_t method; /* method to use for health check */
|
||||
apr_interval_time_t interval;
|
||||
char upgrade[PROXY_WORKER_MAX_SCHEME_SIZE];/* upgrade protocol used by mod_proxy_wstunnel */
|
||||
+ char secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */
|
||||
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;
|
||||
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
|
||||
index 73716af..6faabea 100644
|
||||
--- a/modules/proxy/mod_proxy_ajp.c
|
||||
+++ b/modules/proxy/mod_proxy_ajp.c
|
||||
@@ -193,6 +193,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
|
||||
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 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
|
||||
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)
|
96
httpd-2.4.35-r1825120.patch
Normal file
96
httpd-2.4.35-r1825120.patch
Normal file
@ -0,0 +1,96 @@
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index 19cb611..79d5219 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -2070,70 +2070,18 @@ int ssl_proxy_section_post_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
return OK;
|
||||
}
|
||||
|
||||
-static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a,
|
||||
- const X509_NAME * const *b)
|
||||
-{
|
||||
- return(X509_NAME_cmp(*a, *b));
|
||||
-}
|
||||
-
|
||||
-static void ssl_init_PushCAList(STACK_OF(X509_NAME) *ca_list,
|
||||
- server_rec *s, apr_pool_t *ptemp,
|
||||
- const char *file)
|
||||
-{
|
||||
- int n;
|
||||
- STACK_OF(X509_NAME) *sk;
|
||||
-
|
||||
- sk = (STACK_OF(X509_NAME) *)
|
||||
- SSL_load_client_CA_file(file);
|
||||
-
|
||||
- if (!sk) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- for (n = 0; n < sk_X509_NAME_num(sk); n++) {
|
||||
- X509_NAME *name = sk_X509_NAME_value(sk, n);
|
||||
-
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02209)
|
||||
- "CA certificate: %s",
|
||||
- modssl_X509_NAME_to_string(ptemp, name, 0));
|
||||
-
|
||||
- /*
|
||||
- * note that SSL_load_client_CA_file() checks for duplicates,
|
||||
- * but since we call it multiple times when reading a directory
|
||||
- * we must also check for duplicates ourselves.
|
||||
- */
|
||||
-
|
||||
- if (sk_X509_NAME_find(ca_list, name) < 0) {
|
||||
- /* this will be freed when ca_list is */
|
||||
- sk_X509_NAME_push(ca_list, name);
|
||||
- }
|
||||
- else {
|
||||
- /* need to free this ourselves, else it will leak */
|
||||
- X509_NAME_free(name);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- sk_X509_NAME_free(sk);
|
||||
-}
|
||||
-
|
||||
STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s,
|
||||
apr_pool_t *ptemp,
|
||||
const char *ca_file,
|
||||
const char *ca_path)
|
||||
{
|
||||
- STACK_OF(X509_NAME) *ca_list;
|
||||
-
|
||||
- /*
|
||||
- * Start with a empty stack/list where new
|
||||
- * entries get added in sorted order.
|
||||
- */
|
||||
- ca_list = sk_X509_NAME_new(ssl_init_FindCAList_X509NameCmp);
|
||||
+ STACK_OF(X509_NAME) *ca_list = sk_X509_NAME_new_null();;
|
||||
|
||||
/*
|
||||
* Process CA certificate bundle file
|
||||
*/
|
||||
if (ca_file) {
|
||||
- ssl_init_PushCAList(ca_list, s, ptemp, ca_file);
|
||||
+ SSL_add_file_cert_subjects_to_stack(ca_list, ca_file);
|
||||
/*
|
||||
* If ca_list is still empty after trying to load ca_file
|
||||
* then the file failed to load, and users should hear about that.
|
||||
@@ -2168,17 +2116,12 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s,
|
||||
continue; /* don't try to load directories */
|
||||
}
|
||||
file = apr_pstrcat(ptemp, ca_path, "/", direntry.name, NULL);
|
||||
- ssl_init_PushCAList(ca_list, s, ptemp, file);
|
||||
+ SSL_add_file_cert_subjects_to_stack(ca_list, file);
|
||||
}
|
||||
|
||||
apr_dir_close(dir);
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Cleanup
|
||||
- */
|
||||
- (void) sk_X509_NAME_set_cmp_func(ca_list, NULL);
|
||||
-
|
||||
return ca_list;
|
||||
}
|
||||
|
708
httpd-2.4.35-r1830819+.patch
Normal file
708
httpd-2.4.35-r1830819+.patch
Normal file
@ -0,0 +1,708 @@
|
||||
# ./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
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1835615
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
|
||||
index 43397f9..ff8f429 100644
|
||||
--- httpd-2.4.35/modules/ssl/ssl_engine_config.c.r1830819+
|
||||
+++ httpd-2.4.35/modules/ssl/ssl_engine_config.c
|
||||
@@ -899,7 +899,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;
|
||||
}
|
||||
|
||||
@@ -915,7 +917,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.35/modules/ssl/ssl_engine_init.c.r1830819+
|
||||
+++ httpd-2.4.35/modules/ssl/ssl_engine_init.c
|
||||
@@ -1186,12 +1186,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)
|
||||
@@ -1220,12 +1226,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();
|
||||
@@ -1312,8 +1352,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",
|
||||
@@ -1325,10 +1366,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.35/modules/ssl/ssl_engine_pphrase.c.r1830819+
|
||||
+++ httpd-2.4.35/modules/ssl/ssl_engine_pphrase.c
|
||||
@@ -143,9 +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;
|
||||
- BOOL bReadable;
|
||||
int nPassPhrase = (*pphrases)->nelts;
|
||||
int nPassPhraseRetry = 0;
|
||||
apr_time_t pkey_mtime = 0;
|
||||
@@ -222,16 +219,12 @@
|
||||
* is not empty. */
|
||||
ERR_clear_error();
|
||||
|
||||
- bReadable = ((pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file,
|
||||
- NULL, ssl_pphrase_Handle_CB, &ppcb_arg)) != NULL ?
|
||||
- TRUE : FALSE);
|
||||
-
|
||||
- /*
|
||||
- * when the private key file now was readable,
|
||||
- * it's fine and we go out of the loop
|
||||
- */
|
||||
- if (bReadable)
|
||||
- break;
|
||||
+ 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. */
|
||||
+ if (pPrivateKey != NULL)
|
||||
+ break;
|
||||
|
||||
/*
|
||||
* when we have more remembered pass phrases
|
||||
@@ -356,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;
|
||||
}
|
||||
|
||||
@@ -619,3 +605,303 @@
|
||||
*/
|
||||
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)
|
||||
+{
|
||||
+ const char *c, *scheme;
|
||||
+ 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;
|
||||
+
|
||||
+ c = ap_strchr_c(keyid, ':');
|
||||
+ if (!c || c == keyid) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
|
||||
+ "Init: Unrecognized private key identifier `%s'",
|
||||
+ keyid);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ scheme = apr_pstrmemdup(p, keyid, c - keyid);
|
||||
+ if (!(e = ENGINE_by_id(scheme))) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
|
||||
+ "Init: Failed to load engine for private key %s",
|
||||
+ keyid);
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ if (!ENGINE_init(e)) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10149)
|
||||
+ "Init: Failed to initialize engine %s for private key %s",
|
||||
+ scheme, keyid);
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
|
||||
+ "Init: Initialized engine %s for private key %s",
|
||||
+ scheme, keyid);
|
||||
+
|
||||
+ 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_finish(e);
|
||||
+ ENGINE_free(e);
|
||||
+
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+#endif
|
||||
--- httpd-2.4.35/modules/ssl/ssl_private.h.r1830819+
|
||||
+++ httpd-2.4.35/modules/ssl/ssl_private.h
|
||||
@@ -986,21 +986,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 *);
|
||||
@@ -1088,6 +1095,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.35/modules/ssl/ssl_util.c.r1830819+
|
||||
+++ httpd-2.4.35/modules/ssl/ssl_util.c
|
||||
@@ -175,45 +175,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,
|
||||
@@ -463,3 +455,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.35/modules/ssl/ssl_util_ssl.c.r1830819+
|
||||
+++ httpd-2.4.35/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.35/modules/ssl/ssl_util_ssl.h.r1830819+
|
||||
+++ httpd-2.4.35/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,
|
22
httpd-2.4.35-r1842888.patch
Normal file
22
httpd-2.4.35-r1842888.patch
Normal file
@ -0,0 +1,22 @@
|
||||
diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
|
||||
index d218bab..9f86b09 100644
|
||||
--- a/modules/filters/mod_deflate.c
|
||||
+++ b/modules/filters/mod_deflate.c
|
||||
@@ -864,7 +864,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
|
||||
|
||||
if (c->note_output_name) {
|
||||
apr_table_setn(r->notes, c->note_output_name,
|
||||
- (ctx->stream.total_in > 0)
|
||||
+ (ctx->stream.total_out > 0)
|
||||
? apr_off_t_toa(r->pool,
|
||||
ctx->stream.total_out)
|
||||
: "-");
|
||||
@@ -1336,8 +1336,6 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
|
||||
ctx->stream.next_in = (unsigned char *)data;
|
||||
ctx->stream.avail_in = (int)len;
|
||||
|
||||
- zRC = Z_OK;
|
||||
-
|
||||
if (!ctx->validation_buffer) {
|
||||
while (ctx->stream.avail_in != 0) {
|
||||
if (ctx->stream.avail_out == 0) {
|
65
httpd-2.4.35-selinux.patch
Normal file
65
httpd-2.4.35-selinux.patch
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
Log the SELinux context at startup.
|
||||
|
||||
Upstream-Status: unlikely to be any interest in this upstream
|
||||
|
||||
diff --git a/configure.in b/configure.in
|
||||
index eedba50..a208b53 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -484,6 +484,11 @@ getloadavg
|
||||
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 <unistd.h>
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index ec74029..cb8e463 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -59,6 +59,10 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
+#ifdef HAVE_SELINUX
|
||||
+#include <selinux/selinux.h>
|
||||
+#endif
|
||||
+
|
||||
/* LimitRequestBody handling */
|
||||
#define AP_LIMIT_REQ_BODY_UNSET ((apr_off_t) -1)
|
||||
#define AP_DEFAULT_LIMIT_REQ_BODY ((apr_off_t) 0)
|
||||
@@ -4971,6 +4975,28 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
31
httpd-2.4.35-sslciphdefault.patch
Normal file
31
httpd-2.4.35-sslciphdefault.patch
Normal file
@ -0,0 +1,31 @@
|
||||
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
|
||||
index 4cfd2d0..6ac55bd 100644
|
||||
--- a/modules/ssl/ssl_engine_config.c
|
||||
+++ b/modules/ssl/ssl_engine_config.c
|
||||
@@ -776,9 +776,11 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
|
||||
}
|
||||
|
||||
if (!strcmp("SSL", arg1)) {
|
||||
- /* always disable null and export ciphers */
|
||||
- arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
if (cmd->path) {
|
||||
+ /* Disable null and export ciphers by default, except for PROFILE=
|
||||
+ * configs where the parser doesn't cope. */
|
||||
+ if (strncmp(arg2, "PROFILE=", 8) != 0)
|
||||
+ arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
dc->szCipherSuite = arg2;
|
||||
}
|
||||
else {
|
||||
@@ -1542,8 +1544,10 @@ const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
|
||||
}
|
||||
|
||||
if (!strcmp("SSL", arg1)) {
|
||||
- /* always disable null and export ciphers */
|
||||
- arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
+ /* Disable null and export ciphers by default, except for PROFILE=
|
||||
+ * configs where the parser doesn't cope. */
|
||||
+ if (strncmp(arg2, "PROFILE=", 8) != 0)
|
||||
+ arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
dc->proxy->auth.cipher_suite = arg2;
|
||||
return NULL;
|
||||
}
|
245
httpd-2.4.35-systemd.patch
Normal file
245
httpd-2.4.35-systemd.patch
Normal file
@ -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 <stdint.h>
|
||||
+#include <ap_config.h>
|
||||
+#include "ap_mpm.h"
|
||||
+#include <http_core.h>
|
||||
+#include <httpd.h>
|
||||
+#include <http_log.h>
|
||||
+#include <apr_version.h>
|
||||
+#include <apr_pools.h>
|
||||
+#include <apr_strings.h>
|
||||
+#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 <unistd.h>
|
||||
+#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,
|
||||
+};
|
39
httpd-2.4.37-CVE-2018-17199.patch
Normal file
39
httpd-2.4.37-CVE-2018-17199.patch
Normal file
@ -0,0 +1,39 @@
|
||||
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
|
||||
index 10e6396..7ee477c 100644
|
||||
--- a/modules/session/mod_session.c
|
||||
+++ b/modules/session/mod_session.c
|
||||
@@ -126,20 +126,23 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
|
||||
|
||||
/* found a session that hasn't expired? */
|
||||
now = apr_time_now();
|
||||
+
|
||||
if (zz) {
|
||||
- if (zz->expiry && zz->expiry < now) {
|
||||
+ /* load the session attibutes */
|
||||
+ rv = ap_run_session_decode(r, zz);
|
||||
+
|
||||
+ /* having a session we cannot decode is just as good as having
|
||||
+ none at all */
|
||||
+ if (OK != rv) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
|
||||
+ "error while decoding the session, "
|
||||
+ "session not loaded: %s", r->uri);
|
||||
zz = NULL;
|
||||
}
|
||||
- else {
|
||||
- /* having a session we cannot decode is just as good as having
|
||||
- none at all */
|
||||
- rv = ap_run_session_decode(r, zz);
|
||||
- if (OK != rv) {
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
|
||||
- "error while decoding the session, "
|
||||
- "session not loaded: %s", r->uri);
|
||||
- zz = NULL;
|
||||
- }
|
||||
+
|
||||
+ /* invalidate session if session is expired */
|
||||
+ if (zz && zz->expiry && zz->expiry < now) {
|
||||
+ zz = NULL;
|
||||
}
|
||||
}
|
||||
|
207
httpd-2.4.37-CVE-2019-0211.patch
Normal file
207
httpd-2.4.37-CVE-2019-0211.patch
Normal file
@ -0,0 +1,207 @@
|
||||
diff --git a/include/scoreboard.h b/include/scoreboard.h
|
||||
index 9376da2..92d198d 100644
|
||||
--- a/include/scoreboard.h
|
||||
+++ b/include/scoreboard.h
|
||||
@@ -148,7 +148,9 @@ struct process_score {
|
||||
apr_uint32_t lingering_close; /* async connections in lingering close */
|
||||
apr_uint32_t keep_alive; /* async connections in keep alive */
|
||||
apr_uint32_t suspended; /* connections suspended by some module */
|
||||
- int bucket; /* Listener bucket used by this child */
|
||||
+ int bucket; /* Listener bucket used by this child; this field is DEPRECATED
|
||||
+ * and no longer updated by the MPMs (i.e. always zero).
|
||||
+ */
|
||||
};
|
||||
|
||||
/* Scoreboard is now in 'local' memory, since it isn't updated once created,
|
||||
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
|
||||
index ffe8a23..048ae61 100644
|
||||
--- a/server/mpm/event/event.c
|
||||
+++ b/server/mpm/event/event.c
|
||||
@@ -2695,7 +2695,6 @@ static int make_child(server_rec * s, int slot, int bucket)
|
||||
|
||||
ap_scoreboard_image->parent[slot].quiescing = 0;
|
||||
ap_scoreboard_image->parent[slot].not_accepting = 0;
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
event_note_child_started(slot, pid);
|
||||
active_daemons++;
|
||||
retained->total_daemons++;
|
||||
@@ -2734,6 +2733,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
* that threads_per_child is always > 0 */
|
||||
int status = SERVER_DEAD;
|
||||
int child_threads_active = 0;
|
||||
+ int bucket = i % num_buckets;
|
||||
|
||||
if (i >= retained->max_daemons_limit &&
|
||||
free_length == retained->idle_spawn_rate[child_bucket]) {
|
||||
@@ -2757,7 +2757,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
*/
|
||||
if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
|
||||
&& ps->generation == retained->mpm->my_generation
|
||||
- && ps->bucket == child_bucket)
|
||||
+ && bucket == child_bucket)
|
||||
{
|
||||
++idle_thread_count;
|
||||
}
|
||||
@@ -2768,7 +2768,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
last_non_dead = i;
|
||||
}
|
||||
active_thread_count += child_threads_active;
|
||||
- if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
|
||||
+ if (!ps->pid
|
||||
+ && bucket == child_bucket
|
||||
+ && free_length < retained->idle_spawn_rate[child_bucket])
|
||||
free_slots[free_length++] = i;
|
||||
else if (child_threads_active == threads_per_child)
|
||||
had_healthy_child = 1;
|
||||
@@ -2951,13 +2953,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
retained->total_daemons--;
|
||||
if (processed_status == APEXIT_CHILDSICK) {
|
||||
/* resource shortage, minimize the fork rate */
|
||||
- retained->idle_spawn_rate[ps->bucket] = 1;
|
||||
+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
|
||||
}
|
||||
else if (remaining_children_to_start) {
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot, ps->bucket);
|
||||
+ make_child(ap_server_conf, child_slot,
|
||||
+ child_slot % num_buckets);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
}
|
||||
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
|
||||
index 8efda72..7c00625 100644
|
||||
--- a/server/mpm/prefork/prefork.c
|
||||
+++ b/server/mpm/prefork/prefork.c
|
||||
@@ -637,8 +637,9 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
}
|
||||
|
||||
|
||||
-static int make_child(server_rec *s, int slot, int bucket)
|
||||
+static int make_child(server_rec *s, int slot)
|
||||
{
|
||||
+ int bucket = slot % retained->mpm->num_buckets;
|
||||
int pid;
|
||||
|
||||
if (slot + 1 > retained->max_daemons_limit) {
|
||||
@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
child_main(slot, bucket);
|
||||
}
|
||||
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
prefork_note_child_started(slot, pid);
|
||||
|
||||
return 0;
|
||||
@@ -732,7 +732,7 @@ static void startup_children(int number_to_start)
|
||||
if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
|
||||
continue;
|
||||
}
|
||||
- if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
|
||||
+ if (make_child(ap_server_conf, i) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -741,8 +741,6 @@ static void startup_children(int number_to_start)
|
||||
|
||||
static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
{
|
||||
- static int bucket_make_child_record = -1;
|
||||
- static int bucket_kill_child_record = -1;
|
||||
int i;
|
||||
int idle_count;
|
||||
worker_score *ws;
|
||||
@@ -789,6 +787,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
}
|
||||
retained->max_daemons_limit = last_non_dead + 1;
|
||||
if (idle_count > ap_daemons_max_free) {
|
||||
+ static int bucket_kill_child_record = -1;
|
||||
/* kill off one child... we use the pod because that'll cause it to
|
||||
* shut down gracefully, in case it happened to pick up a request
|
||||
* while we were counting
|
||||
@@ -819,10 +818,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
idle_count, total_non_dead);
|
||||
}
|
||||
for (i = 0; i < free_length; ++i) {
|
||||
- bucket_make_child_record++;
|
||||
- bucket_make_child_record %= retained->mpm->num_buckets;
|
||||
- make_child(ap_server_conf, free_slots[i],
|
||||
- bucket_make_child_record);
|
||||
+ make_child(ap_server_conf, free_slots[i]);
|
||||
}
|
||||
/* the next time around we want to spawn twice as many if this
|
||||
* wasn't good enough, but not if we've just done a graceful
|
||||
@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
|
||||
if (one_process) {
|
||||
AP_MONCONTROL(1);
|
||||
- make_child(ap_server_conf, 0, 0);
|
||||
+ make_child(ap_server_conf, 0);
|
||||
/* NOTREACHED */
|
||||
ap_assert(0);
|
||||
return !OK;
|
||||
@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot,
|
||||
- ap_get_scoreboard_process(child_slot)->bucket);
|
||||
+ make_child(ap_server_conf, child_slot);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
#if APR_HAS_OTHER_CHILD
|
||||
diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
|
||||
index 8012fe2..a927942 100644
|
||||
--- a/server/mpm/worker/worker.c
|
||||
+++ b/server/mpm/worker/worker.c
|
||||
@@ -1339,7 +1339,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
worker_note_child_lost_slot(slot, pid);
|
||||
}
|
||||
ap_scoreboard_image->parent[slot].quiescing = 0;
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
worker_note_child_started(slot, pid);
|
||||
return 0;
|
||||
}
|
||||
@@ -1388,6 +1387,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
int any_dead_threads = 0;
|
||||
int all_dead_threads = 1;
|
||||
int child_threads_active = 0;
|
||||
+ int bucket = i % num_buckets;
|
||||
|
||||
if (i >= retained->max_daemons_limit &&
|
||||
totally_free_length == retained->idle_spawn_rate[child_bucket]) {
|
||||
@@ -1420,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
if (status <= SERVER_READY &&
|
||||
!ps->quiescing &&
|
||||
ps->generation == retained->mpm->my_generation &&
|
||||
- ps->bucket == child_bucket) {
|
||||
+ bucket == child_bucket) {
|
||||
++idle_thread_count;
|
||||
}
|
||||
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
|
||||
@@ -1430,6 +1430,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
}
|
||||
active_thread_count += child_threads_active;
|
||||
if (any_dead_threads
|
||||
+ && bucket == child_bucket
|
||||
&& totally_free_length < retained->idle_spawn_rate[child_bucket]
|
||||
&& free_length < MAX_SPAWN_RATE / num_buckets
|
||||
&& (!ps->pid /* no process in the slot */
|
||||
@@ -1615,14 +1616,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
ps->quiescing = 0;
|
||||
if (processed_status == APEXIT_CHILDSICK) {
|
||||
/* resource shortage, minimize the fork rate */
|
||||
- retained->idle_spawn_rate[ps->bucket] = 1;
|
||||
+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
|
||||
}
|
||||
else if (remaining_children_to_start
|
||||
&& child_slot < ap_daemons_limit) {
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot, ps->bucket);
|
||||
+ make_child(ap_server_conf, child_slot,
|
||||
+ child_slot % num_buckets);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
}
|
20
httpd-2.4.37-CVE-2019-0215.patch
Normal file
20
httpd-2.4.37-CVE-2019-0215.patch
Normal file
@ -0,0 +1,20 @@
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index de0ffb0..e6a9f67 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1154,6 +1154,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server);
|
||||
apr_table_setn(r->notes, "error-notes",
|
||||
"Reason: Cannot perform Post-Handshake Authentication.<br />");
|
||||
+ SSL_set_verify(ssl, vmode_inplace, NULL);
|
||||
return HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
@@ -1175,6 +1176,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
* Finally check for acceptable renegotiation results
|
||||
*/
|
||||
if (OK != (rc = ssl_check_post_client_verify(r, sc, dc, sslconn, ssl))) {
|
||||
+ SSL_set_verify(ssl, vmode_inplace, NULL);
|
||||
return rc;
|
||||
}
|
||||
}
|
111
httpd-2.4.37-CVE-2019-0217.patch
Normal file
111
httpd-2.4.37-CVE-2019-0217.patch
Normal file
@ -0,0 +1,111 @@
|
||||
--- a/modules/aaa/mod_auth_digest.c 2019/03/12 09:24:19 1855297
|
||||
+++ b/modules/aaa/mod_auth_digest.c 2019/03/12 09:24:26 1855298
|
||||
@@ -92,7 +92,6 @@
|
||||
int check_nc;
|
||||
const char *algorithm;
|
||||
char *uri_list;
|
||||
- const char *ha1;
|
||||
} digest_config_rec;
|
||||
|
||||
|
||||
@@ -153,6 +152,7 @@
|
||||
apr_time_t nonce_time;
|
||||
enum hdr_sts auth_hdr_sts;
|
||||
int needed_auth;
|
||||
+ const char *ha1;
|
||||
client_entry *client;
|
||||
} digest_header_rec;
|
||||
|
||||
@@ -1304,7 +1304,7 @@
|
||||
*/
|
||||
|
||||
static authn_status get_hash(request_rec *r, const char *user,
|
||||
- digest_config_rec *conf)
|
||||
+ digest_config_rec *conf, const char **rethash)
|
||||
{
|
||||
authn_status auth_result;
|
||||
char *password;
|
||||
@@ -1356,7 +1356,7 @@
|
||||
} while (current_provider);
|
||||
|
||||
if (auth_result == AUTH_USER_FOUND) {
|
||||
- conf->ha1 = password;
|
||||
+ *rethash = password;
|
||||
}
|
||||
|
||||
return auth_result;
|
||||
@@ -1483,25 +1483,24 @@
|
||||
|
||||
/* RFC-2069 */
|
||||
static const char *old_digest(const request_rec *r,
|
||||
- const digest_header_rec *resp, const char *ha1)
|
||||
+ const digest_header_rec *resp)
|
||||
{
|
||||
const char *ha2;
|
||||
|
||||
ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":",
|
||||
resp->uri, NULL));
|
||||
return ap_md5(r->pool,
|
||||
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,
|
||||
- ":", ha2, NULL));
|
||||
+ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":",
|
||||
+ resp->nonce, ":", ha2, NULL));
|
||||
}
|
||||
|
||||
/* RFC-2617 */
|
||||
static const char *new_digest(const request_rec *r,
|
||||
- digest_header_rec *resp,
|
||||
- const digest_config_rec *conf)
|
||||
+ digest_header_rec *resp)
|
||||
{
|
||||
const char *ha1, *ha2, *a2;
|
||||
|
||||
- ha1 = conf->ha1;
|
||||
+ ha1 = resp->ha1;
|
||||
|
||||
a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
|
||||
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
|
||||
@@ -1514,7 +1513,6 @@
|
||||
NULL));
|
||||
}
|
||||
|
||||
-
|
||||
static void copy_uri_components(apr_uri_t *dst,
|
||||
apr_uri_t *src, request_rec *r) {
|
||||
if (src->scheme && src->scheme[0] != '\0') {
|
||||
@@ -1759,7 +1757,7 @@
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
- return_code = get_hash(r, r->user, conf);
|
||||
+ return_code = get_hash(r, r->user, conf, &resp->ha1);
|
||||
|
||||
if (return_code == AUTH_USER_NOT_FOUND) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790)
|
||||
@@ -1789,7 +1787,7 @@
|
||||
|
||||
if (resp->message_qop == NULL) {
|
||||
/* old (rfc-2069) style digest */
|
||||
- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
|
||||
+ if (strcmp(resp->digest, old_digest(r, resp))) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792)
|
||||
"user %s: password mismatch: %s", r->user,
|
||||
r->uri);
|
||||
@@ -1819,7 +1817,7 @@
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
- exp_digest = new_digest(r, resp, conf);
|
||||
+ exp_digest = new_digest(r, resp);
|
||||
if (!exp_digest) {
|
||||
/* we failed to allocate a client struct */
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
@@ -1903,7 +1901,7 @@
|
||||
|
||||
/* calculate rspauth attribute
|
||||
*/
|
||||
- ha1 = conf->ha1;
|
||||
+ ha1 = resp->ha1;
|
||||
|
||||
a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
|
||||
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
|
235
httpd-2.4.37-CVE-2019-0220.patch
Normal file
235
httpd-2.4.37-CVE-2019-0220.patch
Normal file
@ -0,0 +1,235 @@
|
||||
diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en
|
||||
index 0a24bc8..20d1e5a 100644
|
||||
--- a/docs/manual/mod/core.html.en
|
||||
+++ b/docs/manual/mod/core.html.en
|
||||
@@ -97,6 +97,7 @@ available</td></tr>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangeoverlaps">MaxRangeOverlaps</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangereversals">MaxRangeReversals</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#maxranges">MaxRanges</a></li>
|
||||
+<li><img alt="" src="../images/down.gif" /> <a href="#mergeslashes">MergeSlashes</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#mergetrailers">MergeTrailers</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#mutex">Mutex</a></li>
|
||||
<li><img alt="" src="../images/down.gif" /> <a href="#namevirtualhost">NameVirtualHost</a></li>
|
||||
@@ -3465,6 +3466,30 @@ resource </td></tr>
|
||||
|
||||
</div>
|
||||
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
+<div class="directive-section"><h2><a name="MergeSlashes" id="MergeSlashes">MergeSlashes</a> <a name="mergeslashes" id="mergeslashes">Directive</a></h2>
|
||||
+<table class="directive">
|
||||
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Controls whether the server merges consecutive slashes in URLs. </td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>MergeSlashes ON | OFF</code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>MergeSlashes ON</code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available in Apache HTTP Server 2.4.6 in Red Hat Enterprise Linux 7</td></tr>
|
||||
+</table>
|
||||
+ <p>By default, the server merges (or collapses) multiple consecutive slash
|
||||
+ ('/') characters in the path component of the request URL.</p>
|
||||
+
|
||||
+ <p>When mapping URL's to the filesystem, these multiple slashes are not
|
||||
+ significant. However, URL's handled other ways, such as by CGI or proxy,
|
||||
+ might prefer to retain the significance of multiple consecutive slashes.
|
||||
+ In these cases <code class="directive">MergeSlashes</code> can be set to
|
||||
+ <em>OFF</em> to retain the multiple consecutive slashes. In these
|
||||
+ configurations, regular expressions used in the configuration file that match
|
||||
+ the path component of the URL (<code class="directive">LocationMatch</code>,
|
||||
+ <code class="directive">RewriteRule</code>, ...) need to take into account multiple
|
||||
+ consecutive slashes.</p>
|
||||
+</div>
|
||||
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
<div class="directive-section"><h2><a name="MergeTrailers" id="MergeTrailers">MergeTrailers</a> <a name="mergetrailers" id="mergetrailers">Directive</a></h2>
|
||||
<table class="directive">
|
||||
<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Determines whether trailers are merged into headers</td></tr>
|
||||
--- a/include/http_core.h 2019/03/18 08:49:19 1855736
|
||||
+++ b/include/http_core.h 2019/03/18 08:49:59 1855737
|
||||
@@ -740,7 +740,7 @@
|
||||
#define AP_HTTP_METHODS_LENIENT 1
|
||||
#define AP_HTTP_METHODS_REGISTERED 2
|
||||
char http_methods;
|
||||
-
|
||||
+ unsigned int merge_slashes;
|
||||
} core_server_config;
|
||||
|
||||
/* for AddOutputFiltersByType in core.c */
|
||||
diff --git a/include/httpd.h b/include/httpd.h
|
||||
index 65392f8..99f7f04 100644
|
||||
--- a/include/httpd.h
|
||||
+++ b/include/httpd.h
|
||||
@@ -1697,11 +1697,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
|
||||
AP_DECLARE(int) ap_unescape_urlencoded(char *query);
|
||||
|
||||
/**
|
||||
- * Convert all double slashes to single slashes
|
||||
- * @param name The string to convert
|
||||
+ * Convert all double slashes to single slashes, except where significant
|
||||
+ * to the filesystem on the current platform.
|
||||
+ * @param name The string to convert, assumed to be a filesystem path
|
||||
*/
|
||||
AP_DECLARE(void) ap_no2slash(char *name);
|
||||
|
||||
+/**
|
||||
+ * Convert all double slashes to single slashes, except where significant
|
||||
+ * to the filesystem on the current platform.
|
||||
+ * @param name The string to convert
|
||||
+ * @param is_fs_path if set to 0, the significance of any double-slashes is
|
||||
+ * ignored.
|
||||
+ */
|
||||
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path);
|
||||
+
|
||||
/**
|
||||
* Remove all ./ and xx/../ substrings from a file name. Also remove
|
||||
* any leading ../ or /../ substrings.
|
||||
diff --git a/server/request.c b/server/request.c
|
||||
index dbe3e07..d5c558a 100644
|
||||
--- a/server/request.c
|
||||
+++ b/server/request.c
|
||||
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
int file_req = (r->main && r->filename);
|
||||
int access_status;
|
||||
core_dir_config *d;
|
||||
+ core_server_config *sconf =
|
||||
+ ap_get_core_module_config(r->server->module_config);
|
||||
|
||||
/* Ignore embedded %2F's in path for proxy requests */
|
||||
if (!r->proxyreq && r->parsed_uri.path) {
|
||||
@@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
}
|
||||
|
||||
ap_getparents(r->uri); /* OK --- shrinking transformations... */
|
||||
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
|
||||
+ ap_no2slash(r->uri);
|
||||
+ if (r->parsed_uri.path) {
|
||||
+ ap_no2slash(r->parsed_uri.path);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* All file subrequests are a huge pain... they cannot bubble through the
|
||||
* next several steps. Only file subrequests are allowed an empty uri,
|
||||
@@ -1411,20 +1419,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
|
||||
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
|
||||
cached = (cache->cached != NULL);
|
||||
-
|
||||
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple
|
||||
- * slashes. Location matches multiple slashes with a single slash,
|
||||
- * LocationMatch doesn't. An exception, for backwards brokenness is
|
||||
- * absoluteURIs... in which case neither match multiple slashes.
|
||||
- */
|
||||
- if (r->uri[0] != '/') {
|
||||
- entry_uri = r->uri;
|
||||
- }
|
||||
- else {
|
||||
- char *uri = apr_pstrdup(r->pool, r->uri);
|
||||
- ap_no2slash(uri);
|
||||
- entry_uri = uri;
|
||||
- }
|
||||
+ entry_uri = r->uri;
|
||||
|
||||
/* If we have an cache->cached location that matches r->uri,
|
||||
* and the vhost's list of locations hasn't changed, we can skip
|
||||
@@ -1491,7 +1486,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
|
||||
}
|
||||
|
||||
- if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
|
||||
+ if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1501,7 +1496,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
apr_table_setn(r->subprocess_env,
|
||||
((const char **)entry_core->refs->elts)[i],
|
||||
apr_pstrndup(r->pool,
|
||||
- r->uri + pmatch[i].rm_so,
|
||||
+ entry_uri + pmatch[i].rm_so,
|
||||
pmatch[i].rm_eo - pmatch[i].rm_so));
|
||||
}
|
||||
}
|
||||
diff --git a/server/util.c b/server/util.c
|
||||
index fd7a0a1..e0c558c 100644
|
||||
--- a/server/util.c
|
||||
+++ b/server/util.c
|
||||
@@ -561,16 +561,20 @@ AP_DECLARE(void) ap_getparents(char *name)
|
||||
name[l] = '\0';
|
||||
}
|
||||
}
|
||||
-
|
||||
-AP_DECLARE(void) ap_no2slash(char *name)
|
||||
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
|
||||
{
|
||||
+
|
||||
char *d, *s;
|
||||
|
||||
+ if (!*name) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
s = d = name;
|
||||
|
||||
#ifdef HAVE_UNC_PATHS
|
||||
/* Check for UNC names. Leave leading two slashes. */
|
||||
- if (s[0] == '/' && s[1] == '/')
|
||||
+ if (is_fs_path && s[0] == '/' && s[1] == '/')
|
||||
*d++ = *s++;
|
||||
#endif
|
||||
|
||||
@@ -587,6 +591,10 @@ AP_DECLARE(void) ap_no2slash(char *name)
|
||||
*d = '\0';
|
||||
}
|
||||
|
||||
+AP_DECLARE(void) ap_no2slash(char *name)
|
||||
+{
|
||||
+ ap_no2slash_ex(name, 1);
|
||||
+}
|
||||
|
||||
/*
|
||||
* copy at most n leading directories of s into d
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index b5ab429..a31f1e4 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -493,6 +493,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
|
||||
*/
|
||||
|
||||
conf->trace_enable = AP_TRACE_UNSET;
|
||||
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET;
|
||||
|
||||
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
|
||||
conf->protocols_honor_order = -1;
|
||||
@@ -561,7 +562,9 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
|
||||
conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
|
||||
base->protocols_honor_order :
|
||||
virt->protocols_honor_order);
|
||||
-
|
||||
+
|
||||
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
|
||||
+
|
||||
return conf;
|
||||
}
|
||||
|
||||
@@ -1872,6 +1875,13 @@ static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag)
|
||||
+{
|
||||
+ core_server_config *conf =
|
||||
+ ap_get_core_module_config(cmd->server->module_config);
|
||||
+ return ap_set_flag_slot(cmd, conf, flag);
|
||||
+}
|
||||
+
|
||||
static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
|
||||
{
|
||||
core_dir_config *d = d_;
|
||||
@@ -4598,6 +4608,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON
|
||||
"'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"),
|
||||
AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
|
||||
"Registers non-standard HTTP methods"),
|
||||
+AP_INIT_FLAG("MergeSlashes", set_core_server_flag,
|
||||
+ (void *)APR_OFFSETOF(core_server_config, merge_slashes),
|
||||
+ RSRC_CONF,
|
||||
+ "Controls whether consecutive slashes in the URI path are merged"),
|
||||
{ NULL }
|
||||
};
|
||||
|
192
httpd-2.4.37-CVE-2019-10092.patch
Normal file
192
httpd-2.4.37-CVE-2019-10092.patch
Normal file
@ -0,0 +1,192 @@
|
||||
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
|
||||
index e419eb6..dcafa9c 100644
|
||||
--- a/modules/http/http_protocol.c
|
||||
+++ b/modules/http/http_protocol.c
|
||||
@@ -1132,13 +1132,10 @@ static const char *get_canned_error_string(int status,
|
||||
"\">here</a>.</p>\n",
|
||||
NULL));
|
||||
case HTTP_USE_PROXY:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>This resource is only accessible "
|
||||
- "through the proxy\n",
|
||||
- ap_escape_html(r->pool, location),
|
||||
- "<br />\nYou will need to configure "
|
||||
- "your client to use that proxy.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>This resource is only accessible "
|
||||
+ "through the proxy\n"
|
||||
+ "<br />\nYou will need to configure "
|
||||
+ "your client to use that proxy.</p>\n");
|
||||
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
|
||||
case HTTP_UNAUTHORIZED:
|
||||
return("<p>This server could not verify that you\n"
|
||||
@@ -1154,34 +1151,20 @@ static const char *get_canned_error_string(int status,
|
||||
"error-notes",
|
||||
"</p>\n"));
|
||||
case HTTP_FORBIDDEN:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>You don't have permission to access ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "\non this server.<br />\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
+ return(add_optional_notes(r, "<p>You don't have permission to access this resource.", "error-notes", "</p>\n"));
|
||||
case HTTP_NOT_FOUND:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The requested URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " was not found on this server.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The requested URL was not found on this server.</p>\n");
|
||||
case HTTP_METHOD_NOT_ALLOWED:
|
||||
return(apr_pstrcat(p,
|
||||
"<p>The requested method ",
|
||||
ap_escape_html(r->pool, r->method),
|
||||
- " is not allowed for the URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- ".</p>\n",
|
||||
+ " is not allowed for this URL.</p>\n",
|
||||
NULL));
|
||||
case HTTP_NOT_ACCEPTABLE:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>An appropriate representation of the "
|
||||
- "requested resource ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " could not be found on this server.</p>\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "variant-list", ""));
|
||||
+ return(add_optional_notes(r,
|
||||
+ "<p>An appropriate representation of the requested resource "
|
||||
+ "could not be found on this server.</p>\n",
|
||||
+ "variant-list", ""));
|
||||
case HTTP_MULTIPLE_CHOICES:
|
||||
return(add_optional_notes(r, "", "variant-list", ""));
|
||||
case HTTP_LENGTH_REQUIRED:
|
||||
@@ -1192,18 +1175,13 @@ static const char *get_canned_error_string(int status,
|
||||
NULL);
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_PRECONDITION_FAILED:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The precondition on the request "
|
||||
- "for the URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " evaluated to false.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The precondition on the request "
|
||||
+ "for this URL evaluated to false.</p>\n");
|
||||
case HTTP_NOT_IMPLEMENTED:
|
||||
s1 = apr_pstrcat(p,
|
||||
"<p>",
|
||||
- ap_escape_html(r->pool, r->method), " to ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " not supported.<br />\n",
|
||||
+ ap_escape_html(r->pool, r->method), " ",
|
||||
+ " not supported for current URL.<br />\n",
|
||||
NULL);
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_BAD_GATEWAY:
|
||||
@@ -1211,29 +1189,19 @@ static const char *get_canned_error_string(int status,
|
||||
"response from an upstream server.<br />" CRLF;
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_VARIANT_ALSO_VARIES:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>A variant for the requested "
|
||||
- "resource\n<pre>\n",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "\n</pre>\nis itself a negotiable resource. "
|
||||
- "This indicates a configuration error.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>A variant for the requested "
|
||||
+ "resource\n<pre>\n"
|
||||
+ "\n</pre>\nis itself a negotiable resource. "
|
||||
+ "This indicates a configuration error.</p>\n");
|
||||
case HTTP_REQUEST_TIME_OUT:
|
||||
return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
|
||||
case HTTP_GONE:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The requested resource<br />",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "<br />\nis no longer available on this server "
|
||||
- "and there is no forwarding address.\n"
|
||||
- "Please remove all references to this "
|
||||
- "resource.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The requested resource is no longer available on this server"
|
||||
+ " and there is no forwarding address.\n"
|
||||
+ "Please remove all references to this resource.</p>\n");
|
||||
case HTTP_REQUEST_ENTITY_TOO_LARGE:
|
||||
return(apr_pstrcat(p,
|
||||
- "The requested resource<br />",
|
||||
- ap_escape_html(r->pool, r->uri), "<br />\n",
|
||||
- "does not allow request data with ",
|
||||
+ "The requested resource does not allow request data with ",
|
||||
ap_escape_html(r->pool, r->method),
|
||||
" requests, or the amount of data provided in\n"
|
||||
"the request exceeds the capacity limit.\n",
|
||||
@@ -1317,11 +1285,9 @@ static const char *get_canned_error_string(int status,
|
||||
"the Server Name Indication (SNI) in use for this\n"
|
||||
"connection.</p>\n");
|
||||
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>Access to ", ap_escape_html(r->pool, r->uri),
|
||||
- "\nhas been denied for legal reasons.<br />\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
+ return(add_optional_notes(r,
|
||||
+ "<p>Access to this URL has been denied for legal reasons.<br />\n",
|
||||
+ "error-notes", "</p>\n"));
|
||||
default: /* HTTP_INTERNAL_SERVER_ERROR */
|
||||
/*
|
||||
* This comparison to expose error-notes could be modified to
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index 800ede1..de48735 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -1055,9 +1055,10 @@ static int proxy_handler(request_rec *r)
|
||||
char *end;
|
||||
maxfwd = apr_strtoi64(str, &end, 10);
|
||||
if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
|
||||
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
- apr_psprintf(r->pool,
|
||||
- "Max-Forwards value '%s' could not be parsed", str));
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ "Max-Forwards value '%s' could not be parsed", str);
|
||||
+ return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
+ "Max-Forwards request header could not be parsed");
|
||||
}
|
||||
else if (maxfwd == 0) {
|
||||
switch (r->method_number) {
|
||||
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
|
||||
index 4a10987..8f6f853 100644
|
||||
--- a/modules/proxy/mod_proxy_ftp.c
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c
|
||||
@@ -1024,8 +1024,9 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
/* We break the URL into host, port, path-search */
|
||||
if (r->parsed_uri.hostname == NULL) {
|
||||
if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {
|
||||
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
- apr_psprintf(p, "URI cannot be parsed: %s", url));
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ "URI cannot be parsed: %s", url);
|
||||
+ return ap_proxyerror(r, HTTP_BAD_REQUEST, "URI cannot be parsed");
|
||||
}
|
||||
connectname = uri.hostname;
|
||||
connectport = uri.port;
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 6501c68..0bbfa59 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -368,12 +368,9 @@ PROXY_DECLARE(char *)
|
||||
|
||||
PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
|
||||
{
|
||||
- const char *uri = ap_escape_html(r->pool, r->uri);
|
||||
apr_table_setn(r->notes, "error-notes",
|
||||
apr_pstrcat(r->pool,
|
||||
- "The proxy server could not handle the request <em><a href=\"",
|
||||
- uri, "\">", ap_escape_html(r->pool, r->method), " ", uri,
|
||||
- "</a></em>.<p>\n"
|
||||
+ "The proxy server could not handle the request<p>"
|
||||
"Reason: <strong>", ap_escape_html(r->pool, message),
|
||||
"</strong></p>",
|
||||
NULL));
|
66
httpd-2.4.37-CVE-2019-10097.patch
Normal file
66
httpd-2.4.37-CVE-2019-10097.patch
Normal file
@ -0,0 +1,66 @@
|
||||
diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c
|
||||
index 4572ce1..a0cbc0f 100644
|
||||
--- a/modules/metadata/mod_remoteip.c
|
||||
+++ b/modules/metadata/mod_remoteip.c
|
||||
@@ -987,15 +987,13 @@ static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c,
|
||||
return HDR_ERROR;
|
||||
#endif
|
||||
default:
|
||||
- /* unsupported protocol, keep local connection address */
|
||||
- return HDR_DONE;
|
||||
+ /* unsupported protocol */
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183)
|
||||
+ "RemoteIPProxyProtocol: unsupported protocol %.2hx",
|
||||
+ (unsigned short)hdr->v2.fam);
|
||||
+ return HDR_ERROR;
|
||||
}
|
||||
break; /* we got a sockaddr now */
|
||||
-
|
||||
- case 0x00: /* LOCAL command */
|
||||
- /* keep local connection address for LOCAL */
|
||||
- return HDR_DONE;
|
||||
-
|
||||
default:
|
||||
/* not a supported command */
|
||||
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03507)
|
||||
@@ -1087,11 +1085,24 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
|
||||
/* try to read a header's worth of data */
|
||||
while (!ctx->done) {
|
||||
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
||||
- ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block,
|
||||
- ctx->need - ctx->rcvd);
|
||||
+ apr_off_t got, want = ctx->need - ctx->rcvd;
|
||||
+
|
||||
+ ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want);
|
||||
if (ret != APR_SUCCESS) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184)
|
||||
+ "failed reading input");
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ ret = apr_brigade_length(ctx->bb, 1, &got);
|
||||
+ if (ret || got > want) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185)
|
||||
+ "RemoteIPProxyProtocol header too long, "
|
||||
+ "got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT,
|
||||
+ got, want);
|
||||
+ f->c->aborted = 1;
|
||||
+ return APR_ECONNABORTED;
|
||||
+ }
|
||||
}
|
||||
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
||||
return block == APR_NONBLOCK_READ ? APR_SUCCESS : APR_EOF;
|
||||
@@ -1139,6 +1150,13 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
|
||||
if (ctx->rcvd >= MIN_V2_HDR_LEN) {
|
||||
ctx->need = MIN_V2_HDR_LEN +
|
||||
remoteip_get_v2_len((proxy_header *) ctx->header);
|
||||
+ if (ctx->need > sizeof(proxy_v2)) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186)
|
||||
+ "RemoteIPProxyProtocol protocol header length too long");
|
||||
+ f->c->aborted = 1;
|
||||
+ apr_brigade_destroy(ctx->bb);
|
||||
+ return APR_ECONNABORTED;
|
||||
+ }
|
||||
}
|
||||
if (ctx->rcvd >= ctx->need) {
|
||||
psts = remoteip_process_v2_header(f->c, conn_conf,
|
91
httpd-2.4.37-CVE-2019-10098.patch
Normal file
91
httpd-2.4.37-CVE-2019-10098.patch
Normal file
@ -0,0 +1,91 @@
|
||||
diff --git a/include/ap_regex.h b/include/ap_regex.h
|
||||
index 7d8df79..7af2f99 100644
|
||||
--- a/include/ap_regex.h
|
||||
+++ b/include/ap_regex.h
|
||||
@@ -84,7 +84,11 @@ extern "C" {
|
||||
|
||||
#define AP_REG_DOLLAR_ENDONLY 0x200 /* '$' matches at end of subject string only */
|
||||
|
||||
-#define AP_REG_MATCH "MATCH_" /** suggested prefix for ap_regname */
|
||||
+#define AP_REG_NO_DEFAULT 0x400 /**< Don't implicitely add AP_REG_DEFAULT options */
|
||||
+
|
||||
+#define AP_REG_MATCH "MATCH_" /**< suggested prefix for ap_regname */
|
||||
+
|
||||
+#define AP_REG_DEFAULT (AP_REG_DOTALL|AP_REG_DOLLAR_ENDONLY)
|
||||
|
||||
/* Error values: */
|
||||
enum {
|
||||
diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c
|
||||
index b7d5296..e976c51 100644
|
||||
--- a/modules/filters/mod_substitute.c
|
||||
+++ b/modules/filters/mod_substitute.c
|
||||
@@ -667,8 +667,10 @@ static const char *set_pattern(cmd_parms *cmd, void *cfg, const char *line)
|
||||
|
||||
/* first see if we can compile the regex */
|
||||
if (!is_pattern) {
|
||||
- r = ap_pregcomp(cmd->pool, from, AP_REG_EXTENDED |
|
||||
- (ignore_case ? AP_REG_ICASE : 0));
|
||||
+ int flags = AP_REG_NO_DEFAULT
|
||||
+ | (ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY)
|
||||
+ | (ignore_case ? AP_REG_ICASE : 0);
|
||||
+ r = ap_pregcomp(cmd->pool, from, flags);
|
||||
if (!r)
|
||||
return "Substitute could not compile regex";
|
||||
}
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index 76432ce..6d00777 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -4973,7 +4973,7 @@ static int core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptem
|
||||
init_config_defines(pconf);
|
||||
apr_pool_cleanup_register(pconf, NULL, reset_config, apr_pool_cleanup_null);
|
||||
|
||||
- ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY);
|
||||
+ ap_regcomp_set_default_cflags(AP_REG_DEFAULT);
|
||||
|
||||
mpm_common_pre_config(pconf);
|
||||
|
||||
diff --git a/server/util_pcre.c b/server/util_pcre.c
|
||||
index f2cb1bb..2a665c8 100644
|
||||
--- a/server/util_pcre.c
|
||||
+++ b/server/util_pcre.c
|
||||
@@ -120,7 +120,7 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg)
|
||||
* Compile a regular expression *
|
||||
*************************************************/
|
||||
|
||||
-static int default_cflags = AP_REG_DOLLAR_ENDONLY;
|
||||
+static int default_cflags = AP_REG_DEFAULT;
|
||||
|
||||
AP_DECLARE(int) ap_regcomp_get_default_cflags(void)
|
||||
{
|
||||
@@ -168,7 +168,8 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags)
|
||||
int errcode = 0;
|
||||
int options = PCRE_DUPNAMES;
|
||||
|
||||
- cflags |= default_cflags;
|
||||
+ if ((cflags & AP_REG_NO_DEFAULT) == 0)
|
||||
+ cflags |= default_cflags;
|
||||
if ((cflags & AP_REG_ICASE) != 0)
|
||||
options |= PCRE_CASELESS;
|
||||
if ((cflags & AP_REG_NEWLINE) != 0)
|
||||
diff --git a/server/util_regex.c b/server/util_regex.c
|
||||
index 2a30d68..5405f8d 100644
|
||||
--- a/server/util_regex.c
|
||||
+++ b/server/util_regex.c
|
||||
@@ -94,6 +94,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool,
|
||||
}
|
||||
|
||||
/* anything after the current delimiter is flags */
|
||||
+ ret->flags = ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY;
|
||||
while (*++endp) {
|
||||
switch (*endp) {
|
||||
case 'i': ret->flags |= AP_REG_ICASE; break;
|
||||
@@ -106,7 +107,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool,
|
||||
default: break; /* we should probably be stricter here */
|
||||
}
|
||||
}
|
||||
- if (ap_regcomp(&ret->rx, rxstr, ret->flags) == 0) {
|
||||
+ if (ap_regcomp(&ret->rx, rxstr, AP_REG_NO_DEFAULT | ret->flags) == 0) {
|
||||
apr_pool_cleanup_register(pool, &ret->rx, rxplus_cleanup,
|
||||
apr_pool_cleanup_null);
|
||||
}
|
36
httpd-2.4.37-CVE-2020-11984.patch
Normal file
36
httpd-2.4.37-CVE-2020-11984.patch
Normal file
@ -0,0 +1,36 @@
|
||||
--- a/modules/proxy/mod_proxy_uwsgi.c 2020/07/24 09:31:46 1880250
|
||||
+++ b/modules/proxy/mod_proxy_uwsgi.c 2020/07/24 09:35:25 1880251
|
||||
@@ -136,7 +136,7 @@
|
||||
int j;
|
||||
|
||||
apr_size_t headerlen = 4;
|
||||
- apr_uint16_t pktsize, keylen, vallen;
|
||||
+ apr_size_t pktsize, keylen, vallen;
|
||||
const char *script_name;
|
||||
const char *path_info;
|
||||
const char *auth;
|
||||
@@ -178,6 +178,15 @@
|
||||
headerlen += 2 + strlen(env[j].key) + 2 + strlen(env[j].val);
|
||||
}
|
||||
|
||||
+ pktsize = headerlen - 4;
|
||||
+ if (pktsize > APR_UINT16_MAX) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10259)
|
||||
+ "can't send headers to %s:%u: packet size too "
|
||||
+ "large (%" APR_SIZE_T_FMT ")",
|
||||
+ conn->hostname, conn->port, pktsize);
|
||||
+ return HTTP_INTERNAL_SERVER_ERROR;
|
||||
+ }
|
||||
+
|
||||
ptr = buf = apr_palloc(r->pool, headerlen);
|
||||
|
||||
ptr += 4;
|
||||
@@ -196,8 +205,6 @@
|
||||
ptr += vallen;
|
||||
}
|
||||
|
||||
- pktsize = headerlen - 4;
|
||||
-
|
||||
buf[0] = 0;
|
||||
buf[1] = (apr_byte_t) (pktsize & 0xff);
|
||||
buf[2] = (apr_byte_t) ((pktsize >> 8) & 0xff);
|
68
httpd-2.4.37-CVE-2020-1934.patch
Normal file
68
httpd-2.4.37-CVE-2020-1934.patch
Normal file
@ -0,0 +1,68 @@
|
||||
--- a/modules/proxy/mod_proxy_ftp.c 2020/02/07 17:01:07 1873744
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c 2020/02/07 17:04:45 1873745
|
||||
@@ -218,7 +218,7 @@
|
||||
* (EBCDIC) machines either.
|
||||
*/
|
||||
static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb,
|
||||
- char *buff, apr_size_t bufflen, int *eos)
|
||||
+ char *buff, apr_size_t bufflen, int *eos, apr_size_t *outlen)
|
||||
{
|
||||
apr_bucket *e;
|
||||
apr_status_t rv;
|
||||
@@ -230,6 +230,7 @@
|
||||
/* start with an empty string */
|
||||
buff[0] = 0;
|
||||
*eos = 0;
|
||||
+ *outlen = 0;
|
||||
|
||||
/* loop through each brigade */
|
||||
while (!found) {
|
||||
@@ -273,6 +274,7 @@
|
||||
if (len > 0) {
|
||||
memcpy(pos, response, len);
|
||||
pos += len;
|
||||
+ *outlen += len;
|
||||
}
|
||||
}
|
||||
apr_bucket_delete(e);
|
||||
@@ -385,28 +387,36 @@
|
||||
char buff[5];
|
||||
char *mb = msgbuf, *me = &msgbuf[msglen];
|
||||
apr_status_t rv;
|
||||
+ apr_size_t nread;
|
||||
+
|
||||
int eos;
|
||||
|
||||
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
|
||||
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(03233)
|
||||
"<%s", response);
|
||||
*/
|
||||
+ if (nread < 4) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(10229) "Malformed FTP response '%s'", response);
|
||||
+ *mb = '\0';
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
|
||||
- !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
|
||||
+ !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
|
||||
status = 0;
|
||||
else
|
||||
status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0';
|
||||
|
||||
mb = apr_cpystrn(mb, response + 4, me - mb);
|
||||
|
||||
- if (response[3] == '-') {
|
||||
+ if (response[3] == '-') { /* multi-line reply "123-foo\nbar\n123 baz" */
|
||||
memcpy(buff, response, 3);
|
||||
buff[3] = ' ';
|
||||
do {
|
||||
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
|
||||
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
|
||||
return -1;
|
||||
}
|
||||
mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
|
21
httpd-2.4.37-CVE-2020-35452.patch
Normal file
21
httpd-2.4.37-CVE-2020-35452.patch
Normal file
@ -0,0 +1,21 @@
|
||||
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
|
||||
index b760941..0825b1b 100644
|
||||
--- a/modules/aaa/mod_auth_digest.c
|
||||
+++ b/modules/aaa/mod_auth_digest.c
|
||||
@@ -1422,9 +1422,14 @@ static int check_nonce(request_rec *r, digest_header_rec *resp,
|
||||
time_rec nonce_time;
|
||||
char tmp, hash[NONCE_HASH_LEN+1];
|
||||
|
||||
- if (strlen(resp->nonce) != NONCE_LEN) {
|
||||
+ /* Since the time part of the nonce is a base64 encoding of an
|
||||
+ * apr_time_t (8 bytes), it should end with a '=', fail early otherwise.
|
||||
+ */
|
||||
+ if (strlen(resp->nonce) != NONCE_LEN
|
||||
+ || resp->nonce[NONCE_TIME_LEN - 1] != '=') {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01775)
|
||||
- "invalid nonce %s received - length is not %d",
|
||||
+ "invalid nonce '%s' received - length is not %d "
|
||||
+ "or time encoding is incorrect",
|
||||
resp->nonce, NONCE_LEN);
|
||||
note_digest_auth_failure(r, conf, resp, 1);
|
||||
return HTTP_UNAUTHORIZED;
|
14
httpd-2.4.37-CVE-2021-26690.patch
Normal file
14
httpd-2.4.37-CVE-2021-26690.patch
Normal file
@ -0,0 +1,14 @@
|
||||
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
|
||||
index 7ee477c..049255d 100644
|
||||
--- a/modules/session/mod_session.c
|
||||
+++ b/modules/session/mod_session.c
|
||||
@@ -404,8 +404,8 @@ static apr_status_t session_identity_decode(request_rec * r, session_rec * z)
|
||||
char *plast = NULL;
|
||||
const char *psep = "=";
|
||||
char *key = apr_strtok(pair, psep, &plast);
|
||||
- char *val = apr_strtok(NULL, psep, &plast);
|
||||
if (key && *key) {
|
||||
+ char *val = apr_strtok(NULL, sep, &plast);
|
||||
if (!val || !*val) {
|
||||
apr_table_unset(z->entries, key);
|
||||
}
|
13
httpd-2.4.37-CVE-2021-26691.patch
Normal file
13
httpd-2.4.37-CVE-2021-26691.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
|
||||
index 049255d..af70f6b 100644
|
||||
--- a/modules/session/mod_session.c
|
||||
+++ b/modules/session/mod_session.c
|
||||
@@ -317,7 +317,7 @@ static apr_status_t ap_session_set(request_rec * r, session_rec * z,
|
||||
static int identity_count(void *v, const char *key, const char *val)
|
||||
{
|
||||
int *count = v;
|
||||
- *count += strlen(key) * 3 + strlen(val) * 3 + 1;
|
||||
+ *count += strlen(key) * 3 + strlen(val) * 3 + 2;
|
||||
return 1;
|
||||
}
|
||||
|
44
httpd-2.4.37-CVE-2021-30641.patch
Normal file
44
httpd-2.4.37-CVE-2021-30641.patch
Normal file
@ -0,0 +1,44 @@
|
||||
diff --git a/server/request.c b/server/request.c
|
||||
index d5c558a..18625af 100644
|
||||
--- a/server/request.c
|
||||
+++ b/server/request.c
|
||||
@@ -1419,7 +1419,20 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
|
||||
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
|
||||
cached = (cache->cached != NULL);
|
||||
- entry_uri = r->uri;
|
||||
+
|
||||
+ /*
|
||||
+ * When merge_slashes is set to AP_CORE_CONFIG_OFF the slashes in r->uri
|
||||
+ * have not been merged. But for Location walks we always go with merged
|
||||
+ * slashes no matter what merge_slashes is set to.
|
||||
+ */
|
||||
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
|
||||
+ entry_uri = r->uri;
|
||||
+ }
|
||||
+ else {
|
||||
+ char *uri = apr_pstrdup(r->pool, r->uri);
|
||||
+ ap_no2slash(uri);
|
||||
+ entry_uri = uri;
|
||||
+ }
|
||||
|
||||
/* If we have an cache->cached location that matches r->uri,
|
||||
* and the vhost's list of locations hasn't changed, we can skip
|
||||
@@ -1486,7 +1499,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
|
||||
}
|
||||
|
||||
- if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
|
||||
+ if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1496,7 +1509,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
apr_table_setn(r->subprocess_env,
|
||||
((const char **)entry_core->refs->elts)[i],
|
||||
apr_pstrndup(r->pool,
|
||||
- entry_uri + pmatch[i].rm_so,
|
||||
+ r->uri + pmatch[i].rm_so,
|
||||
pmatch[i].rm_eo - pmatch[i].rm_so));
|
||||
}
|
||||
}
|
706
httpd-2.4.37-CVE-2021-33193.patch
Normal file
706
httpd-2.4.37-CVE-2021-33193.patch
Normal file
@ -0,0 +1,706 @@
|
||||
diff --git a/include/http_core.h b/include/http_core.h
|
||||
index 8e10988..3ba8069 100644
|
||||
--- a/include/http_core.h
|
||||
+++ b/include/http_core.h
|
||||
@@ -741,6 +741,7 @@ typedef struct {
|
||||
#define AP_HTTP_METHODS_REGISTERED 2
|
||||
char http_methods;
|
||||
unsigned int merge_slashes;
|
||||
+ unsigned int strict_host_check;
|
||||
} core_server_config;
|
||||
|
||||
/* for AddOutputFiltersByType in core.c */
|
||||
@@ -769,6 +770,11 @@ AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto);
|
||||
typedef struct core_output_filter_ctx core_output_filter_ctx_t;
|
||||
typedef struct core_filter_ctx core_ctx_t;
|
||||
|
||||
+struct core_filter_ctx {
|
||||
+ apr_bucket_brigade *b;
|
||||
+ apr_bucket_brigade *tmpbb;
|
||||
+};
|
||||
+
|
||||
typedef struct core_net_rec {
|
||||
/** Connection to the client */
|
||||
apr_socket_t *client_socket;
|
||||
diff --git a/include/http_protocol.h b/include/http_protocol.h
|
||||
index 11c7b2d..e7abdd9 100644
|
||||
--- a/include/http_protocol.h
|
||||
+++ b/include/http_protocol.h
|
||||
@@ -53,6 +53,13 @@ AP_DECLARE_DATA extern ap_filter_rec_t *ap_old_write_func;
|
||||
* or control the ones that eventually do.
|
||||
*/
|
||||
|
||||
+/**
|
||||
+ * Read an empty request and set reasonable defaults.
|
||||
+ * @param c The current connection
|
||||
+ * @return The new request_rec
|
||||
+ */
|
||||
+AP_DECLARE(request_rec *) ap_create_request(conn_rec *c);
|
||||
+
|
||||
/**
|
||||
* Read a request and fill in the fields.
|
||||
* @param c The current connection
|
||||
@@ -60,6 +67,20 @@ AP_DECLARE_DATA extern ap_filter_rec_t *ap_old_write_func;
|
||||
*/
|
||||
request_rec *ap_read_request(conn_rec *c);
|
||||
|
||||
+/**
|
||||
+ * Parse and validate the request line.
|
||||
+ * @param r The current request
|
||||
+ * @return 1 on success, 0 on failure
|
||||
+ */
|
||||
+AP_DECLARE(int) ap_parse_request_line(request_rec *r);
|
||||
+
|
||||
+/**
|
||||
+ * Validate the request header and select vhost.
|
||||
+ * @param r The current request
|
||||
+ * @return 1 on success, 0 on failure
|
||||
+ */
|
||||
+AP_DECLARE(int) ap_check_request_header(request_rec *r);
|
||||
+
|
||||
/**
|
||||
* Read the mime-encoded headers.
|
||||
* @param r The current request
|
||||
diff --git a/include/http_vhost.h b/include/http_vhost.h
|
||||
index 473c9c7..d2d9c97 100644
|
||||
--- a/include/http_vhost.h
|
||||
+++ b/include/http_vhost.h
|
||||
@@ -99,6 +99,19 @@ AP_DECLARE(void) ap_update_vhost_given_ip(conn_rec *conn);
|
||||
*/
|
||||
AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r);
|
||||
|
||||
+/**
|
||||
+ * Updates r->server with the best name-based virtual host match, within
|
||||
+ * the chain of matching virtual hosts selected by ap_update_vhost_given_ip.
|
||||
+ * @param r The current request
|
||||
+ * @param require_match 1 to return an HTTP error if the requested hostname is
|
||||
+ * not explicitly matched to a VirtualHost.
|
||||
+ * @return return HTTP_OK unless require_match was specified and the requested
|
||||
+ * hostname did not match any ServerName, ServerAlias, or VirtualHost
|
||||
+ * address-spec.
|
||||
+ */
|
||||
+AP_DECLARE(int) ap_update_vhost_from_headers_ex(request_rec *r, int require_match);
|
||||
+
|
||||
+
|
||||
/**
|
||||
* Match the host in the header with the hostname of the server for this
|
||||
* request.
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index 84e80f2..23abf57 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -498,6 +498,8 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
|
||||
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
|
||||
conf->protocols_honor_order = -1;
|
||||
|
||||
+ conf->strict_host_check= AP_CORE_CONFIG_UNSET;
|
||||
+
|
||||
return (void *)conf;
|
||||
}
|
||||
|
||||
@@ -565,6 +567,12 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
|
||||
|
||||
AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
|
||||
|
||||
+ conf->strict_host_check = (virt->strict_host_check != AP_CORE_CONFIG_UNSET)
|
||||
+ ? virt->strict_host_check
|
||||
+ : base->strict_host_check;
|
||||
+
|
||||
+ AP_CORE_MERGE_FLAG(strict_host_check, conf, base, virt);
|
||||
+
|
||||
return conf;
|
||||
}
|
||||
|
||||
@@ -4546,7 +4554,10 @@ AP_INIT_TAKE2("CGIVar", set_cgi_var, NULL, OR_FILEINFO,
|
||||
AP_INIT_FLAG("QualifyRedirectURL", set_qualify_redirect_url, NULL, OR_FILEINFO,
|
||||
"Controls whether HTTP authorization headers, normally hidden, will "
|
||||
"be passed to scripts"),
|
||||
-
|
||||
+AP_INIT_FLAG("StrictHostCheck", set_core_server_flag,
|
||||
+ (void *)APR_OFFSETOF(core_server_config, strict_host_check),
|
||||
+ RSRC_CONF,
|
||||
+ "Controls whether a hostname match is required"),
|
||||
AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower,
|
||||
(void *)APR_OFFSETOF(core_dir_config, mime_type), OR_FILEINFO,
|
||||
"a mime type that overrides other configured type"),
|
||||
@@ -5581,4 +5592,3 @@ AP_DECLARE_MODULE(core) = {
|
||||
core_cmds, /* command apr_table_t */
|
||||
register_hooks /* register hooks */
|
||||
};
|
||||
-
|
||||
diff --git a/server/core_filters.c b/server/core_filters.c
|
||||
index a6c2bd6..e08801f 100644
|
||||
--- a/server/core_filters.c
|
||||
+++ b/server/core_filters.c
|
||||
@@ -84,11 +84,6 @@ struct core_output_filter_ctx {
|
||||
apr_size_t bytes_written;
|
||||
};
|
||||
|
||||
-struct core_filter_ctx {
|
||||
- apr_bucket_brigade *b;
|
||||
- apr_bucket_brigade *tmpbb;
|
||||
-};
|
||||
-
|
||||
|
||||
apr_status_t ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
||||
ap_input_mode_t mode, apr_read_type_e block,
|
||||
diff --git a/server/protocol.c b/server/protocol.c
|
||||
index 8d1fdd2..430d91e 100644
|
||||
--- a/server/protocol.c
|
||||
+++ b/server/protocol.c
|
||||
@@ -609,8 +609,15 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri)
|
||||
}
|
||||
|
||||
r->args = r->parsed_uri.query;
|
||||
- r->uri = r->parsed_uri.path ? r->parsed_uri.path
|
||||
- : apr_pstrdup(r->pool, "/");
|
||||
+ if (r->parsed_uri.path) {
|
||||
+ r->uri = r->parsed_uri.path;
|
||||
+ }
|
||||
+ else if (r->method_number == M_OPTIONS) {
|
||||
+ r->uri = apr_pstrdup(r->pool, "*");
|
||||
+ }
|
||||
+ else {
|
||||
+ r->uri = apr_pstrdup(r->pool, "/");
|
||||
+ }
|
||||
|
||||
#if defined(OS2) || defined(WIN32)
|
||||
/* Handle path translations for OS/2 and plug security hole.
|
||||
@@ -645,13 +652,6 @@ static int field_name_len(const char *field)
|
||||
|
||||
static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
|
||||
{
|
||||
- enum {
|
||||
- rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace,
|
||||
- rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext,
|
||||
- rrl_badmethod09, rrl_reject09
|
||||
- } deferred_error = rrl_none;
|
||||
- char *ll;
|
||||
- char *uri;
|
||||
apr_size_t len;
|
||||
int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES;
|
||||
core_server_config *conf = ap_get_core_module_config(r->server->module_config);
|
||||
@@ -711,6 +711,20 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
|
||||
}
|
||||
|
||||
r->request_time = apr_time_now();
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+AP_DECLARE(int) ap_parse_request_line(request_rec *r)
|
||||
+{
|
||||
+ core_server_config *conf = ap_get_core_module_config(r->server->module_config);
|
||||
+ int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
|
||||
+ enum {
|
||||
+ rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace,
|
||||
+ rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext,
|
||||
+ rrl_badmethod09, rrl_reject09
|
||||
+ } deferred_error = rrl_none;
|
||||
+ apr_size_t len = 0;
|
||||
+ char *uri, *ll;
|
||||
|
||||
r->method = r->the_request;
|
||||
|
||||
@@ -742,7 +756,6 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
|
||||
if (deferred_error == rrl_none)
|
||||
deferred_error = rrl_missinguri;
|
||||
r->protocol = uri = "";
|
||||
- len = 0;
|
||||
goto rrl_done;
|
||||
}
|
||||
else if (strict && ll[0] && apr_isspace(ll[1])
|
||||
@@ -773,7 +786,6 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
|
||||
/* Verify URI terminated with a single SP, or mark as specific error */
|
||||
if (!ll) {
|
||||
r->protocol = "";
|
||||
- len = 0;
|
||||
goto rrl_done;
|
||||
}
|
||||
else if (strict && ll[0] && apr_isspace(ll[1])
|
||||
@@ -866,6 +878,14 @@ rrl_done:
|
||||
r->header_only = 1;
|
||||
|
||||
ap_parse_uri(r, uri);
|
||||
+ if (r->status == HTTP_OK
|
||||
+ && (r->parsed_uri.path != NULL)
|
||||
+ && (r->parsed_uri.path[0] != '/')
|
||||
+ && (r->method_number != M_OPTIONS
|
||||
+ || strcmp(r->parsed_uri.path, "*") != 0)) {
|
||||
+ /* Invalid request-target per RFC 7230 section 5.3 */
|
||||
+ r->status = HTTP_BAD_REQUEST;
|
||||
+ }
|
||||
|
||||
/* With the request understood, we can consider HTTP/0.9 specific errors */
|
||||
if (r->proto_num == HTTP_VERSION(0, 9) && deferred_error == rrl_none) {
|
||||
@@ -973,6 +993,79 @@ rrl_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+AP_DECLARE(int) ap_check_request_header(request_rec *r)
|
||||
+{
|
||||
+ core_server_config *conf;
|
||||
+ int strict_host_check;
|
||||
+ const char *expect;
|
||||
+ int access_status;
|
||||
+
|
||||
+ conf = ap_get_core_module_config(r->server->module_config);
|
||||
+
|
||||
+ /* update what we think the virtual host is based on the headers we've
|
||||
+ * now read. may update status.
|
||||
+ */
|
||||
+ strict_host_check = (conf->strict_host_check == AP_CORE_CONFIG_ON);
|
||||
+ access_status = ap_update_vhost_from_headers_ex(r, strict_host_check);
|
||||
+ if (strict_host_check && access_status != HTTP_OK) {
|
||||
+ if (r->server == ap_server_conf) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10156)
|
||||
+ "Requested hostname '%s' did not match any ServerName/ServerAlias "
|
||||
+ "in the global server configuration ", r->hostname);
|
||||
+ }
|
||||
+ else {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10157)
|
||||
+ "Requested hostname '%s' did not match any ServerName/ServerAlias "
|
||||
+ "in the matching virtual host (default vhost for "
|
||||
+ "current connection is %s:%u)",
|
||||
+ r->hostname, r->server->defn_name, r->server->defn_line_number);
|
||||
+ }
|
||||
+ r->status = access_status;
|
||||
+ }
|
||||
+ if (r->status != HTTP_OK) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1)))
|
||||
+ || ((r->proto_num == HTTP_VERSION(1, 1))
|
||||
+ && !apr_table_get(r->headers_in, "Host"))) {
|
||||
+ /*
|
||||
+ * Client sent us an HTTP/1.1 or later request without telling us the
|
||||
+ * hostname, either with a full URL or a Host: header. We therefore
|
||||
+ * need to (as per the 1.1 spec) send an error. As a special case,
|
||||
+ * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
|
||||
+ * a Host: header, and the server MUST respond with 400 if it doesn't.
|
||||
+ */
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569)
|
||||
+ "client sent HTTP/1.1 request without hostname "
|
||||
+ "(see RFC2616 section 14.23): %s", r->uri);
|
||||
+ r->status = HTTP_BAD_REQUEST;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL)
|
||||
+ && (expect[0] != '\0')) {
|
||||
+ /*
|
||||
+ * The Expect header field was added to HTTP/1.1 after RFC 2068
|
||||
+ * as a means to signal when a 100 response is desired and,
|
||||
+ * unfortunately, to signal a poor man's mandatory extension that
|
||||
+ * the server must understand or return 417 Expectation Failed.
|
||||
+ */
|
||||
+ if (ap_cstr_casecmp(expect, "100-continue") == 0) {
|
||||
+ r->expecting_100 = 1;
|
||||
+ }
|
||||
+ else {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570)
|
||||
+ "client sent an unrecognized expectation value "
|
||||
+ "of Expect: %s", expect);
|
||||
+ r->status = HTTP_EXPECTATION_FAILED;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int table_do_fn_check_lengths(void *r_, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
@@ -1256,16 +1349,10 @@ AP_DECLARE(void) ap_get_mime_headers(request_rec *r)
|
||||
apr_brigade_destroy(tmp_bb);
|
||||
}
|
||||
|
||||
-request_rec *ap_read_request(conn_rec *conn)
|
||||
+AP_DECLARE(request_rec *) ap_create_request(conn_rec *conn)
|
||||
{
|
||||
request_rec *r;
|
||||
apr_pool_t *p;
|
||||
- const char *expect;
|
||||
- int access_status;
|
||||
- apr_bucket_brigade *tmp_bb;
|
||||
- apr_socket_t *csd;
|
||||
- apr_interval_time_t cur_timeout;
|
||||
-
|
||||
|
||||
apr_pool_create(&p, conn->pool);
|
||||
apr_pool_tag(p, "request");
|
||||
@@ -1304,6 +1391,7 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
r->read_body = REQUEST_NO_BODY;
|
||||
|
||||
r->status = HTTP_OK; /* Until further notice */
|
||||
+ r->header_only = 0;
|
||||
r->the_request = NULL;
|
||||
|
||||
/* Begin by presuming any module can make its own path_info assumptions,
|
||||
@@ -1314,12 +1402,33 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
r->useragent_addr = conn->client_addr;
|
||||
r->useragent_ip = conn->client_ip;
|
||||
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+/* Apply the server's timeout/config to the connection/request. */
|
||||
+static void apply_server_config(request_rec *r)
|
||||
+{
|
||||
+ apr_socket_t *csd;
|
||||
+
|
||||
+ csd = ap_get_conn_socket(r->connection);
|
||||
+ apr_socket_timeout_set(csd, r->server->timeout);
|
||||
+
|
||||
+ r->per_dir_config = r->server->lookup_defaults;
|
||||
+}
|
||||
+
|
||||
+request_rec *ap_read_request(conn_rec *conn)
|
||||
+{
|
||||
+ int access_status;
|
||||
+ apr_bucket_brigade *tmp_bb;
|
||||
+
|
||||
+ request_rec *r = ap_create_request(conn);
|
||||
tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
||||
|
||||
ap_run_pre_read_request(r, conn);
|
||||
|
||||
/* Get the request... */
|
||||
- if (!read_request_line(r, tmp_bb)) {
|
||||
+ if (!read_request_line(r, tmp_bb) || !ap_parse_request_line(r)) {
|
||||
+ apr_brigade_cleanup(tmp_bb);
|
||||
switch (r->status) {
|
||||
case HTTP_REQUEST_URI_TOO_LARGE:
|
||||
case HTTP_BAD_REQUEST:
|
||||
@@ -1335,49 +1444,38 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
"request failed: malformed request line");
|
||||
}
|
||||
access_status = r->status;
|
||||
- r->status = HTTP_OK;
|
||||
- ap_die(access_status, r);
|
||||
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
|
||||
- ap_run_log_transaction(r);
|
||||
- r = NULL;
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
- goto traceout;
|
||||
+ goto die_unusable_input;
|
||||
+
|
||||
case HTTP_REQUEST_TIME_OUT:
|
||||
+ /* Just log, no further action on this connection. */
|
||||
ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL);
|
||||
if (!r->connection->keepalives)
|
||||
ap_run_log_transaction(r);
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
- goto traceout;
|
||||
- default:
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
- r = NULL;
|
||||
- goto traceout;
|
||||
+ break;
|
||||
}
|
||||
+ /* Not worth dying with. */
|
||||
+ conn->keepalive = AP_CONN_CLOSE;
|
||||
+ apr_pool_destroy(r->pool);
|
||||
+ goto ignore;
|
||||
}
|
||||
+ apr_brigade_cleanup(tmp_bb);
|
||||
|
||||
/* We may have been in keep_alive_timeout mode, so toggle back
|
||||
* to the normal timeout mode as we fetch the header lines,
|
||||
* as necessary.
|
||||
*/
|
||||
- csd = ap_get_conn_socket(conn);
|
||||
- apr_socket_timeout_get(csd, &cur_timeout);
|
||||
- if (cur_timeout != conn->base_server->timeout) {
|
||||
- apr_socket_timeout_set(csd, conn->base_server->timeout);
|
||||
- cur_timeout = conn->base_server->timeout;
|
||||
- }
|
||||
+ apply_server_config(r);
|
||||
|
||||
if (!r->assbackwards) {
|
||||
const char *tenc;
|
||||
|
||||
ap_get_mime_headers_core(r, tmp_bb);
|
||||
+ apr_brigade_cleanup(tmp_bb);
|
||||
if (r->status != HTTP_OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00567)
|
||||
"request failed: error reading the headers");
|
||||
- ap_send_error_response(r, 0);
|
||||
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
|
||||
- ap_run_log_transaction(r);
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
- goto traceout;
|
||||
+ access_status = r->status;
|
||||
+ goto die_unusable_input;
|
||||
}
|
||||
|
||||
tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
|
||||
@@ -1393,13 +1491,8 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539)
|
||||
"client sent unknown Transfer-Encoding "
|
||||
"(%s): %s", tenc, r->uri);
|
||||
- r->status = HTTP_BAD_REQUEST;
|
||||
- conn->keepalive = AP_CONN_CLOSE;
|
||||
- ap_send_error_response(r, 0);
|
||||
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
|
||||
- ap_run_log_transaction(r);
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
- goto traceout;
|
||||
+ access_status = HTTP_BAD_REQUEST;
|
||||
+ goto die_unusable_input;
|
||||
}
|
||||
|
||||
/* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
|
||||
@@ -1412,88 +1505,81 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
}
|
||||
}
|
||||
|
||||
- apr_brigade_destroy(tmp_bb);
|
||||
-
|
||||
- /* update what we think the virtual host is based on the headers we've
|
||||
- * now read. may update status.
|
||||
- */
|
||||
- ap_update_vhost_from_headers(r);
|
||||
- access_status = r->status;
|
||||
-
|
||||
- /* Toggle to the Host:-based vhost's timeout mode to fetch the
|
||||
- * request body and send the response body, if needed.
|
||||
- */
|
||||
- if (cur_timeout != r->server->timeout) {
|
||||
- apr_socket_timeout_set(csd, r->server->timeout);
|
||||
- cur_timeout = r->server->timeout;
|
||||
- }
|
||||
-
|
||||
- /* we may have switched to another server */
|
||||
- r->per_dir_config = r->server->lookup_defaults;
|
||||
-
|
||||
- if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1)))
|
||||
- || ((r->proto_num == HTTP_VERSION(1, 1))
|
||||
- && !apr_table_get(r->headers_in, "Host"))) {
|
||||
- /*
|
||||
- * Client sent us an HTTP/1.1 or later request without telling us the
|
||||
- * hostname, either with a full URL or a Host: header. We therefore
|
||||
- * need to (as per the 1.1 spec) send an error. As a special case,
|
||||
- * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
|
||||
- * a Host: header, and the server MUST respond with 400 if it doesn't.
|
||||
- */
|
||||
- access_status = HTTP_BAD_REQUEST;
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569)
|
||||
- "client sent HTTP/1.1 request without hostname "
|
||||
- "(see RFC2616 section 14.23): %s", r->uri);
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Add the HTTP_IN filter here to ensure that ap_discard_request_body
|
||||
* called by ap_die and by ap_send_error_response works correctly on
|
||||
* status codes that do not cause the connection to be dropped and
|
||||
* in situations where the connection should be kept alive.
|
||||
*/
|
||||
-
|
||||
ap_add_input_filter_handle(ap_http_input_filter_handle,
|
||||
NULL, r, r->connection);
|
||||
|
||||
- if (access_status != HTTP_OK
|
||||
- || (access_status = ap_run_post_read_request(r))) {
|
||||
- ap_die(access_status, r);
|
||||
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
|
||||
- ap_run_log_transaction(r);
|
||||
- r = NULL;
|
||||
- goto traceout;
|
||||
+ /* Validate Host/Expect headers and select vhost. */
|
||||
+ if (!ap_check_request_header(r)) {
|
||||
+ /* we may have switched to another server still */
|
||||
+ apply_server_config(r);
|
||||
+ access_status = r->status;
|
||||
+ goto die_before_hooks;
|
||||
}
|
||||
|
||||
- if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL)
|
||||
- && (expect[0] != '\0')) {
|
||||
- /*
|
||||
- * The Expect header field was added to HTTP/1.1 after RFC 2068
|
||||
- * as a means to signal when a 100 response is desired and,
|
||||
- * unfortunately, to signal a poor man's mandatory extension that
|
||||
- * the server must understand or return 417 Expectation Failed.
|
||||
- */
|
||||
- if (strcasecmp(expect, "100-continue") == 0) {
|
||||
- r->expecting_100 = 1;
|
||||
- }
|
||||
- else {
|
||||
- r->status = HTTP_EXPECTATION_FAILED;
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570)
|
||||
- "client sent an unrecognized expectation value of "
|
||||
- "Expect: %s", expect);
|
||||
- ap_send_error_response(r, 0);
|
||||
- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
|
||||
- ap_run_log_transaction(r);
|
||||
- goto traceout;
|
||||
- }
|
||||
+ /* we may have switched to another server */
|
||||
+ apply_server_config(r);
|
||||
+
|
||||
+ if ((access_status = ap_run_post_read_request(r))) {
|
||||
+ goto die;
|
||||
}
|
||||
|
||||
- AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method, (char *)r->uri, (char *)r->server->defn_name, r->status);
|
||||
+ AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method,
|
||||
+ (char *)r->uri, (char *)r->server->defn_name,
|
||||
+ r->status);
|
||||
+
|
||||
return r;
|
||||
- traceout:
|
||||
+
|
||||
+ /* Everything falls through on failure */
|
||||
+
|
||||
+die_unusable_input:
|
||||
+ /* Input filters are in an undeterminate state, cleanup (including
|
||||
+ * CORE_IN's socket) such that any further attempt to read is EOF.
|
||||
+ */
|
||||
+ {
|
||||
+ ap_filter_t *f = conn->input_filters;
|
||||
+ while (f) {
|
||||
+ if (f->frec == ap_core_input_filter_handle) {
|
||||
+ core_net_rec *net = f->ctx;
|
||||
+ apr_brigade_cleanup(net->in_ctx->b);
|
||||
+ break;
|
||||
+ }
|
||||
+ ap_remove_input_filter(f);
|
||||
+ f = f->next;
|
||||
+ }
|
||||
+ conn->input_filters = r->input_filters = f;
|
||||
+ conn->keepalive = AP_CONN_CLOSE;
|
||||
+ }
|
||||
+
|
||||
+die_before_hooks:
|
||||
+ /* First call to ap_die() (non recursive) */
|
||||
+ r->status = HTTP_OK;
|
||||
+
|
||||
+die:
|
||||
+ ap_die(access_status, r);
|
||||
+
|
||||
+ /* ap_die() sent the response through the output filters, we must now
|
||||
+ * end the request with an EOR bucket for stream/pipeline accounting.
|
||||
+ */
|
||||
+ {
|
||||
+ apr_bucket_brigade *eor_bb;
|
||||
+ eor_bb = apr_brigade_create(conn->pool, conn->bucket_alloc);
|
||||
+ APR_BRIGADE_INSERT_TAIL(eor_bb,
|
||||
+ ap_bucket_eor_create(conn->bucket_alloc, r));
|
||||
+ ap_pass_brigade(conn->output_filters, eor_bb);
|
||||
+ apr_brigade_cleanup(eor_bb);
|
||||
+ }
|
||||
+
|
||||
+ignore:
|
||||
+ r = NULL;
|
||||
+
|
||||
AP_READ_REQUEST_FAILURE((uintptr_t)r);
|
||||
- return r;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
/* if a request with a body creates a subrequest, remove original request's
|
||||
diff --git a/server/vhost.c b/server/vhost.c
|
||||
index b23b2dd..6e233b5 100644
|
||||
--- a/server/vhost.c
|
||||
+++ b/server/vhost.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "http_vhost.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_core.h"
|
||||
+#include "http_main.h"
|
||||
|
||||
#if APR_HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
@@ -973,7 +974,13 @@ AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
|
||||
}
|
||||
|
||||
|
||||
-static void check_hostalias(request_rec *r)
|
||||
+/*
|
||||
+ * Updates r->server from ServerName/ServerAlias. Per the interaction
|
||||
+ * of ip and name-based vhosts, it only looks in the best match from the
|
||||
+ * connection-level ip-based matching.
|
||||
+ * Returns HTTP_BAD_REQUEST if there was no match.
|
||||
+ */
|
||||
+static int update_server_from_aliases(request_rec *r)
|
||||
{
|
||||
/*
|
||||
* Even if the request has a Host: header containing a port we ignore
|
||||
@@ -1050,11 +1057,18 @@ static void check_hostalias(request_rec *r)
|
||||
goto found;
|
||||
}
|
||||
|
||||
- return;
|
||||
+ if (!r->connection->vhost_lookup_data) {
|
||||
+ if (matches_aliases(r->server, host)) {
|
||||
+ s = r->server;
|
||||
+ goto found;
|
||||
+ }
|
||||
+ }
|
||||
+ return HTTP_BAD_REQUEST;
|
||||
|
||||
found:
|
||||
/* s is the first matching server, we're done */
|
||||
r->server = s;
|
||||
+ return HTTP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1071,7 +1085,7 @@ static void check_serverpath(request_rec *r)
|
||||
* This is in conjunction with the ServerPath code in http_core, so we
|
||||
* get the right host attached to a non- Host-sending request.
|
||||
*
|
||||
- * See the comment in check_hostalias about how each vhost can be
|
||||
+ * See the comment in update_server_from_aliases about how each vhost can be
|
||||
* listed multiple times.
|
||||
*/
|
||||
|
||||
@@ -1134,11 +1148,17 @@ static APR_INLINE const char *construct_host_header(request_rec *r,
|
||||
}
|
||||
|
||||
AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
|
||||
+{
|
||||
+ ap_update_vhost_from_headers_ex(r, 0);
|
||||
+}
|
||||
+
|
||||
+AP_DECLARE(int) ap_update_vhost_from_headers_ex(request_rec *r, int require_match)
|
||||
{
|
||||
core_server_config *conf = ap_get_core_module_config(r->server->module_config);
|
||||
const char *host_header = apr_table_get(r->headers_in, "Host");
|
||||
int is_v6literal = 0;
|
||||
int have_hostname_from_url = 0;
|
||||
+ int rc = HTTP_OK;
|
||||
|
||||
if (r->hostname) {
|
||||
/*
|
||||
@@ -1151,8 +1171,8 @@ AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
|
||||
else if (host_header != NULL) {
|
||||
is_v6literal = fix_hostname(r, host_header, conf->http_conformance);
|
||||
}
|
||||
- if (r->status != HTTP_OK)
|
||||
- return;
|
||||
+ if (!require_match && r->status != HTTP_OK)
|
||||
+ return HTTP_OK;
|
||||
|
||||
if (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE) {
|
||||
/*
|
||||
@@ -1173,10 +1193,16 @@ AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
|
||||
/* check if we tucked away a name_chain */
|
||||
if (r->connection->vhost_lookup_data) {
|
||||
if (r->hostname)
|
||||
- check_hostalias(r);
|
||||
+ rc = update_server_from_aliases(r);
|
||||
else
|
||||
check_serverpath(r);
|
||||
}
|
||||
+ else if (require_match && r->hostname) {
|
||||
+ /* check the base server config */
|
||||
+ rc = update_server_from_aliases(r);
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/**
|
13
httpd-2.4.37-CVE-2021-34798.patch
Normal file
13
httpd-2.4.37-CVE-2021-34798.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/server/scoreboard.c b/server/scoreboard.c
|
||||
index 23e3d70..7b01bdf 100644
|
||||
--- a/server/scoreboard.c
|
||||
+++ b/server/scoreboard.c
|
||||
@@ -376,7 +376,7 @@ AP_DECLARE(void) ap_increment_counts(ap_sb_handle_t *sb, request_rec *r)
|
||||
if (pfn_ap_logio_get_last_bytes != NULL) {
|
||||
bytes = pfn_ap_logio_get_last_bytes(r->connection);
|
||||
}
|
||||
- else if (r->method_number == M_GET && r->method[0] == 'H') {
|
||||
+ else if (r->method_number == M_GET && r->method && r->method[0] == 'H') {
|
||||
bytes = 0;
|
||||
}
|
||||
else {
|
45
httpd-2.4.37-CVE-2021-36160.patch
Normal file
45
httpd-2.4.37-CVE-2021-36160.patch
Normal file
@ -0,0 +1,45 @@
|
||||
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
|
||||
index 792d35e..9dcbed1 100644
|
||||
--- a/modules/proxy/mod_proxy_uwsgi.c
|
||||
+++ b/modules/proxy/mod_proxy_uwsgi.c
|
||||
@@ -453,11 +453,8 @@ static int uwsgi_handler(request_rec *r, proxy_worker * worker,
|
||||
const char *proxyname, apr_port_t proxyport)
|
||||
{
|
||||
int status;
|
||||
- int delta = 0;
|
||||
- int decode_status;
|
||||
proxy_conn_rec *backend = NULL;
|
||||
apr_pool_t *p = r->pool;
|
||||
- size_t w_len;
|
||||
char server_portstr[32];
|
||||
char *u_path_info;
|
||||
apr_uri_t *uri;
|
||||
@@ -469,23 +466,14 @@ static int uwsgi_handler(request_rec *r, proxy_worker * worker,
|
||||
|
||||
uri = apr_palloc(r->pool, sizeof(*uri));
|
||||
|
||||
- /* ADD PATH_INFO */
|
||||
-#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
- w_len = strlen(worker->s->name);
|
||||
-#else
|
||||
- w_len = strlen(worker->name);
|
||||
-#endif
|
||||
- u_path_info = r->filename + 6 + w_len;
|
||||
- if (u_path_info[0] != '/') {
|
||||
- delta = 1;
|
||||
- }
|
||||
- decode_status = ap_unescape_url(url + w_len - delta);
|
||||
- if (decode_status) {
|
||||
+ /* ADD PATH_INFO (unescaped) */
|
||||
+ u_path_info = ap_strchr(url + sizeof(UWSGI_SCHEME) + 2, '/');
|
||||
+ if (!u_path_info || ap_unescape_url(u_path_info) != OK) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10100)
|
||||
- "unable to decode uri: %s", url + w_len - delta);
|
||||
+ "unable to decode uwsgi uri: %s", url);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
- apr_table_add(r->subprocess_env, "PATH_INFO", url + w_len - delta);
|
||||
+ apr_table_add(r->subprocess_env, "PATH_INFO", u_path_info);
|
||||
|
||||
|
||||
/* Create space for state information */
|
21
httpd-2.4.37-CVE-2021-39275.patch
Normal file
21
httpd-2.4.37-CVE-2021-39275.patch
Normal file
@ -0,0 +1,21 @@
|
||||
diff --git a/server/util.c b/server/util.c
|
||||
index e0c558c..2a5dd04 100644
|
||||
--- a/server/util.c
|
||||
+++ b/server/util.c
|
||||
@@ -2460,13 +2460,12 @@ AP_DECLARE(char *) ap_escape_quotes(apr_pool_t *p, const char *instring)
|
||||
* in front of every " that doesn't already have one.
|
||||
*/
|
||||
while (*inchr != '\0') {
|
||||
- if ((*inchr == '\\') && (inchr[1] != '\0')) {
|
||||
- *outchr++ = *inchr++;
|
||||
- *outchr++ = *inchr++;
|
||||
- }
|
||||
if (*inchr == '"') {
|
||||
*outchr++ = '\\';
|
||||
}
|
||||
+ if ((*inchr == '\\') && (inchr[1] != '\0')) {
|
||||
+ *outchr++ = *inchr++;
|
||||
+ }
|
||||
if (*inchr != '\0') {
|
||||
*outchr++ = *inchr++;
|
||||
}
|
126
httpd-2.4.37-CVE-2021-40438.patch
Normal file
126
httpd-2.4.37-CVE-2021-40438.patch
Normal file
@ -0,0 +1,126 @@
|
||||
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
|
||||
index fb897a9..38dbb24 100644
|
||||
--- a/modules/mappers/mod_rewrite.c
|
||||
+++ b/modules/mappers/mod_rewrite.c
|
||||
@@ -619,6 +619,13 @@ static unsigned is_absolute_uri(char *uri, int *supportsqs)
|
||||
return 6;
|
||||
}
|
||||
break;
|
||||
+
|
||||
+ case 'u':
|
||||
+ case 'U':
|
||||
+ if (!ap_cstr_casecmpn(uri, "nix:", 4)) { /* unix: */
|
||||
+ *sqs = 1;
|
||||
+ return (uri[4] == '/' && uri[5] == '/') ? 7 : 5;
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index f383996..6a9ef55 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -1717,7 +1717,8 @@ PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url)
|
||||
* the UDS path... ignore it
|
||||
*/
|
||||
if (!strncasecmp(url, "unix:", 5) &&
|
||||
- ((ptr = ap_strchr_c(url, '|')) != NULL)) {
|
||||
+ ((ptr = ap_strchr_c(url + 5, '|')) != NULL)) {
|
||||
+
|
||||
/* move past the 'unix:...|' UDS path info */
|
||||
const char *ret, *c;
|
||||
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 7714b6c..3dd570c 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -2084,33 +2084,45 @@ static int ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worke
|
||||
* were passed a UDS url (eg: from mod_proxy) and adjust uds_path
|
||||
* as required.
|
||||
*/
|
||||
-static void fix_uds_filename(request_rec *r, char **url)
|
||||
+static int fix_uds_filename(request_rec *r, char **url)
|
||||
{
|
||||
- char *ptr, *ptr2;
|
||||
- if (!r || !r->filename) return;
|
||||
+ char *uds_url = r->filename + 6, *origin_url;
|
||||
|
||||
if (!strncmp(r->filename, "proxy:", 6) &&
|
||||
- (ptr2 = ap_strcasestr(r->filename, "unix:")) &&
|
||||
- (ptr = ap_strchr(ptr2, '|'))) {
|
||||
+ !ap_cstr_casecmpn(uds_url, "unix:", 5) &&
|
||||
+ (origin_url = ap_strchr(uds_url + 5, '|'))) {
|
||||
+ char *uds_path = NULL;
|
||||
+ apr_size_t url_len;
|
||||
apr_uri_t urisock;
|
||||
apr_status_t rv;
|
||||
- *ptr = '\0';
|
||||
- rv = apr_uri_parse(r->pool, ptr2, &urisock);
|
||||
- if (rv == APR_SUCCESS) {
|
||||
- char *rurl = ptr+1;
|
||||
- char *sockpath = ap_runtime_dir_relative(r->pool, urisock.path);
|
||||
- apr_table_setn(r->notes, "uds_path", sockpath);
|
||||
- *url = apr_pstrdup(r->pool, rurl); /* so we get the scheme for the uds */
|
||||
- /* r->filename starts w/ "proxy:", so add after that */
|
||||
- memmove(r->filename+6, rurl, strlen(rurl)+1);
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
|
||||
- "*: rewrite of url due to UDS(%s): %s (%s)",
|
||||
- sockpath, *url, r->filename);
|
||||
- }
|
||||
- else {
|
||||
- *ptr = '|';
|
||||
- }
|
||||
- }
|
||||
+
|
||||
+ *origin_url = '\0';
|
||||
+ rv = apr_uri_parse(r->pool, uds_url, &urisock);
|
||||
+ *origin_url++ = '|';
|
||||
+
|
||||
+ if (rv == APR_SUCCESS && urisock.path && (!urisock.hostname
|
||||
+ || !urisock.hostname[0])) {
|
||||
+ uds_path = ap_runtime_dir_relative(r->pool, urisock.path);
|
||||
+ }
|
||||
+
|
||||
+ if (!uds_path) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10292)
|
||||
+ "Invalid proxy UDS filename (%s)", r->filename);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ apr_table_setn(r->notes, "uds_path", uds_path);
|
||||
+
|
||||
+ /* Remove the UDS path from *url and r->filename */
|
||||
+ url_len = strlen(origin_url);
|
||||
+ *url = apr_pstrmemdup(r->pool, origin_url, url_len);
|
||||
+ memcpy(uds_url, *url, url_len + 1);
|
||||
+
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
|
||||
+ "*: rewrite of url due to UDS(%s): %s (%s)",
|
||||
+ uds_path, *url, r->filename);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
|
||||
@@ -2128,7 +2140,9 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
|
||||
"%s: found worker %s for %s",
|
||||
(*worker)->s->scheme, (*worker)->s->name, *url);
|
||||
*balancer = NULL;
|
||||
- fix_uds_filename(r, url);
|
||||
+ if (!fix_uds_filename(r, url)) {
|
||||
+ return HTTP_INTERNAL_SERVER_ERROR;
|
||||
+ }
|
||||
access_status = OK;
|
||||
}
|
||||
else if (r->proxyreq == PROXYREQ_PROXY) {
|
||||
@@ -2159,7 +2173,9 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
|
||||
* regarding the Connection header in the request.
|
||||
*/
|
||||
apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
|
||||
- fix_uds_filename(r, url);
|
||||
+ if (!fix_uds_filename(r, url)) {
|
||||
+ return HTTP_INTERNAL_SERVER_ERROR;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
315
httpd-2.4.37-CVE-2021-44224.patch
Normal file
315
httpd-2.4.37-CVE-2021-44224.patch
Normal file
@ -0,0 +1,315 @@
|
||||
diff --git a/include/http_protocol.h b/include/http_protocol.h
|
||||
index e7abdd9..e1572dc 100644
|
||||
--- a/include/http_protocol.h
|
||||
+++ b/include/http_protocol.h
|
||||
@@ -96,6 +96,13 @@ AP_DECLARE(void) ap_get_mime_headers(request_rec *r);
|
||||
AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r,
|
||||
apr_bucket_brigade *bb);
|
||||
|
||||
+/**
|
||||
+ * Run post_read_request hook and validate.
|
||||
+ * @param r The current request
|
||||
+ * @return OK or HTTP_...
|
||||
+ */
|
||||
+AP_DECLARE(int) ap_post_read_request(request_rec *r);
|
||||
+
|
||||
/* Finish up stuff after a request */
|
||||
|
||||
/**
|
||||
diff --git a/modules/http/http_request.c b/modules/http/http_request.c
|
||||
index 9e7c4db..e873aab 100644
|
||||
--- a/modules/http/http_request.c
|
||||
+++ b/modules/http/http_request.c
|
||||
@@ -681,7 +681,7 @@ static request_rec *internal_internal_redirect(const char *new_uri,
|
||||
* to do their thing on internal redirects as well. Perhaps this is a
|
||||
* misnamed function.
|
||||
*/
|
||||
- if ((access_status = ap_run_post_read_request(new))) {
|
||||
+ if ((access_status = ap_post_read_request(new))) {
|
||||
ap_die(access_status, new);
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index 6a9ef55..a6df1b8 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -584,11 +584,12 @@ static int proxy_detect(request_rec *r)
|
||||
|
||||
if (conf->req && r->parsed_uri.scheme) {
|
||||
/* but it might be something vhosted */
|
||||
- if (!(r->parsed_uri.hostname
|
||||
- && !strcasecmp(r->parsed_uri.scheme, ap_http_scheme(r))
|
||||
- && ap_matches_request_vhost(r, r->parsed_uri.hostname,
|
||||
- (apr_port_t)(r->parsed_uri.port_str ? r->parsed_uri.port
|
||||
- : ap_default_port(r))))) {
|
||||
+ if (!r->parsed_uri.hostname
|
||||
+ || ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r)) != 0
|
||||
+ || !ap_matches_request_vhost(r, r->parsed_uri.hostname,
|
||||
+ (apr_port_t)(r->parsed_uri.port_str
|
||||
+ ? r->parsed_uri.port
|
||||
+ : ap_default_port(r)))) {
|
||||
r->proxyreq = PROXYREQ_PROXY;
|
||||
r->uri = r->unparsed_uri;
|
||||
r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
|
||||
@@ -1750,6 +1751,7 @@ static const char *
|
||||
struct proxy_alias *new;
|
||||
char *f = cmd->path;
|
||||
char *r = NULL;
|
||||
+ const char *real;
|
||||
char *word;
|
||||
apr_table_t *params = apr_table_make(cmd->pool, 5);
|
||||
const apr_array_header_t *arr;
|
||||
@@ -1815,6 +1817,10 @@ static const char *
|
||||
if (r == NULL) {
|
||||
return "ProxyPass|ProxyPassMatch needs a path when not defined in a location";
|
||||
}
|
||||
+ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, r))) {
|
||||
+ return "ProxyPass|ProxyPassMatch uses an invalid \"unix:\" URL";
|
||||
+ }
|
||||
+
|
||||
|
||||
/* if per directory, save away the single alias */
|
||||
if (cmd->path) {
|
||||
@@ -1831,7 +1837,7 @@ static const char *
|
||||
}
|
||||
|
||||
new->fake = apr_pstrdup(cmd->pool, f);
|
||||
- new->real = apr_pstrdup(cmd->pool, ap_proxy_de_socketfy(cmd->pool, r));
|
||||
+ new->real = apr_pstrdup(cmd->pool, real);
|
||||
new->flags = flags;
|
||||
if (use_regex) {
|
||||
new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
|
||||
@@ -2316,6 +2322,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
proxy_worker *worker;
|
||||
char *path = cmd->path;
|
||||
char *name = NULL;
|
||||
+ const char *real;
|
||||
char *word;
|
||||
apr_table_t *params = apr_table_make(cmd->pool, 5);
|
||||
const apr_array_header_t *arr;
|
||||
@@ -2356,6 +2363,9 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
return "BalancerMember must define balancer name when outside <Proxy > section";
|
||||
if (!name)
|
||||
return "BalancerMember must define remote proxy server";
|
||||
+ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) {
|
||||
+ return "BalancerMember uses an invalid \"unix:\" URL";
|
||||
+ }
|
||||
|
||||
ap_str_tolower(path); /* lowercase scheme://hostname */
|
||||
|
||||
@@ -2368,7 +2378,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
}
|
||||
|
||||
/* Try to find existing worker */
|
||||
- worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, ap_proxy_de_socketfy(cmd->temp_pool, name));
|
||||
+ worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, real);
|
||||
if (!worker) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147)
|
||||
"Defining worker '%s' for balancer '%s'",
|
||||
@@ -2457,7 +2467,13 @@ static const char *
|
||||
}
|
||||
}
|
||||
else {
|
||||
- worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->temp_pool, name));
|
||||
+ const char *real;
|
||||
+
|
||||
+ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) {
|
||||
+ return "ProxySet uses an invalid \"unix:\" URL";
|
||||
+ }
|
||||
+
|
||||
+ worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, real);
|
||||
if (!worker) {
|
||||
if (in_proxy_section) {
|
||||
err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
|
||||
@@ -2599,8 +2615,14 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
|
||||
}
|
||||
}
|
||||
else {
|
||||
+ const char *real;
|
||||
+
|
||||
+ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, conf->p))) {
|
||||
+ return "<Proxy/ProxyMatch > uses an invalid \"unix:\" URL";
|
||||
+ }
|
||||
+
|
||||
worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf,
|
||||
- ap_proxy_de_socketfy(cmd->temp_pool, (char*)conf->p));
|
||||
+ real);
|
||||
if (!worker) {
|
||||
err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
|
||||
sconf, conf->p, 0);
|
||||
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
|
||||
index fbbd508..dca6f69 100644
|
||||
--- a/modules/proxy/mod_proxy.h
|
||||
+++ b/modules/proxy/mod_proxy.h
|
||||
@@ -713,6 +713,8 @@ typedef __declspec(dllimport) const char *
|
||||
proxy_dir_conf *, const char *);
|
||||
#endif
|
||||
|
||||
+#define AP_PROXY_WORKER_NO_UDS (1u << 3)
|
||||
+
|
||||
|
||||
/* Connection pool API */
|
||||
/**
|
||||
@@ -725,6 +727,24 @@ typedef __declspec(dllimport) const char *
|
||||
PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
|
||||
proxy_worker *worker);
|
||||
|
||||
+
|
||||
+/**
|
||||
+ * Get the worker from proxy configuration, looking for either PREFIXED or
|
||||
+ * MATCHED or both types of workers according to given mask
|
||||
+ * @param p memory pool used for finding worker
|
||||
+ * @param balancer the balancer that the worker belongs to
|
||||
+ * @param conf current proxy server configuration
|
||||
+ * @param url url to find the worker from
|
||||
+ * @param mask bitmask of AP_PROXY_WORKER_IS_*
|
||||
+ * @return proxy_worker or NULL if not found
|
||||
+ */
|
||||
+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
|
||||
+ proxy_balancer *balancer,
|
||||
+ proxy_server_conf *conf,
|
||||
+ const char *url,
|
||||
+ unsigned int mask);
|
||||
+
|
||||
+
|
||||
/**
|
||||
* Get the worker from proxy configuration
|
||||
* @param p memory pool used for finding worker
|
||||
@@ -737,6 +757,8 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
|
||||
proxy_balancer *balancer,
|
||||
proxy_server_conf *conf,
|
||||
const char *url);
|
||||
+
|
||||
+
|
||||
/**
|
||||
* Define and Allocate space for the worker to proxy configuration
|
||||
* @param p memory pool to allocate worker from
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 032e0c4..3d5b220 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -1643,10 +1643,11 @@ PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
|
||||
return apr_pstrcat(p, "unix:", worker->s->uds_path, "|", worker->s->name, NULL);
|
||||
}
|
||||
|
||||
-PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
|
||||
- proxy_balancer *balancer,
|
||||
- proxy_server_conf *conf,
|
||||
- const char *url)
|
||||
+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
|
||||
+ proxy_balancer *balancer,
|
||||
+ proxy_server_conf *conf,
|
||||
+ const char *url,
|
||||
+ unsigned int mask)
|
||||
{
|
||||
proxy_worker *worker;
|
||||
proxy_worker *max_worker = NULL;
|
||||
@@ -1662,7 +1663,12 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- url = ap_proxy_de_socketfy(p, url);
|
||||
+ if (!(mask & AP_PROXY_WORKER_NO_UDS)) {
|
||||
+ url = ap_proxy_de_socketfy(p, url);
|
||||
+ if (!url) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
c = ap_strchr_c(url, ':');
|
||||
if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
|
||||
@@ -1727,6 +1733,14 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
|
||||
return max_worker;
|
||||
}
|
||||
|
||||
+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
|
||||
+ proxy_balancer *balancer,
|
||||
+ proxy_server_conf *conf,
|
||||
+ const char *url)
|
||||
+{
|
||||
+ return ap_proxy_get_worker_ex(p, balancer, conf, url, 0);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* To create a worker from scratch first we define the
|
||||
* specifics of the worker; this is all local data.
|
||||
@@ -2134,22 +2148,22 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
|
||||
|
||||
access_status = proxy_run_pre_request(worker, balancer, r, conf, url);
|
||||
if (access_status == DECLINED && *balancer == NULL) {
|
||||
- *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url);
|
||||
+ const int forward = (r->proxyreq == PROXYREQ_PROXY);
|
||||
+ *worker = ap_proxy_get_worker_ex(r->pool, NULL, conf, *url,
|
||||
+ forward ? AP_PROXY_WORKER_NO_UDS : 0);
|
||||
if (*worker) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
|
||||
"%s: found worker %s for %s",
|
||||
(*worker)->s->scheme, (*worker)->s->name, *url);
|
||||
- *balancer = NULL;
|
||||
- if (!fix_uds_filename(r, url)) {
|
||||
+ if (!forward && !fix_uds_filename(r, url)) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
access_status = OK;
|
||||
}
|
||||
- else if (r->proxyreq == PROXYREQ_PROXY) {
|
||||
+ else if (forward) {
|
||||
if (conf->forward) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
|
||||
"*: found forward proxy worker for %s", *url);
|
||||
- *balancer = NULL;
|
||||
*worker = conf->forward;
|
||||
access_status = OK;
|
||||
/*
|
||||
@@ -2163,8 +2177,8 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
|
||||
else if (r->proxyreq == PROXYREQ_REVERSE) {
|
||||
if (conf->reverse) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
|
||||
- "*: using default reverse proxy worker for %s (no keepalive)", *url);
|
||||
- *balancer = NULL;
|
||||
+ "*: using default reverse proxy worker for %s "
|
||||
+ "(no keepalive)", *url);
|
||||
*worker = conf->reverse;
|
||||
access_status = OK;
|
||||
/*
|
||||
diff --git a/server/protocol.c b/server/protocol.c
|
||||
index 430d91e..a2aa081 100644
|
||||
--- a/server/protocol.c
|
||||
+++ b/server/protocol.c
|
||||
@@ -1525,7 +1525,7 @@ request_rec *ap_read_request(conn_rec *conn)
|
||||
/* we may have switched to another server */
|
||||
apply_server_config(r);
|
||||
|
||||
- if ((access_status = ap_run_post_read_request(r))) {
|
||||
+ if ((access_status = ap_post_read_request(r))) {
|
||||
goto die;
|
||||
}
|
||||
|
||||
@@ -1582,6 +1582,27 @@ ignore:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+AP_DECLARE(int) ap_post_read_request(request_rec *r)
|
||||
+{
|
||||
+ int status;
|
||||
+
|
||||
+ if ((status = ap_run_post_read_request(r))) {
|
||||
+ return status;
|
||||
+ }
|
||||
+
|
||||
+ /* Enforce http(s) only scheme for non-forward-proxy requests */
|
||||
+ if (!r->proxyreq
|
||||
+ && r->parsed_uri.scheme
|
||||
+ && (ap_cstr_casecmpn(r->parsed_uri.scheme, "http", 4) != 0
|
||||
+ || (r->parsed_uri.scheme[4] != '\0'
|
||||
+ && (apr_tolower(r->parsed_uri.scheme[4]) != 's'
|
||||
+ || r->parsed_uri.scheme[5] != '\0')))) {
|
||||
+ return HTTP_BAD_REQUEST;
|
||||
+ }
|
||||
+
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
/* if a request with a body creates a subrequest, remove original request's
|
||||
* input headers which pertain to the body which has already been read.
|
||||
* out-of-line helper function for ap_set_sub_req_protocol.
|
12
httpd-2.4.37-CVE-2021-44790.patch
Normal file
12
httpd-2.4.37-CVE-2021-44790.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c
|
||||
index 77a88b4..1d8be2e 100644
|
||||
--- a/modules/lua/lua_request.c
|
||||
+++ b/modules/lua/lua_request.c
|
||||
@@ -376,6 +376,7 @@ static int req_parsebody(lua_State *L)
|
||||
if (end == NULL) break;
|
||||
key = (char *) apr_pcalloc(r->pool, 256);
|
||||
filename = (char *) apr_pcalloc(r->pool, 256);
|
||||
+ if (end - crlf <= 8) break;
|
||||
vlen = end - crlf - 8;
|
||||
buffer = (char *) apr_pcalloc(r->pool, vlen+1);
|
||||
memcpy(buffer, crlf + 4, vlen);
|
154
httpd-2.4.37-CVE-2022-22720.patch
Normal file
154
httpd-2.4.37-CVE-2022-22720.patch
Normal file
@ -0,0 +1,154 @@
|
||||
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
|
||||
index 9828cdf..6bedcac 100644
|
||||
--- a/modules/http/http_filters.c
|
||||
+++ b/modules/http/http_filters.c
|
||||
@@ -1605,9 +1605,9 @@ AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status)
|
||||
*/
|
||||
AP_DECLARE(int) ap_discard_request_body(request_rec *r)
|
||||
{
|
||||
+ int rc = OK;
|
||||
+ conn_rec *c = r->connection;
|
||||
apr_bucket_brigade *bb;
|
||||
- int seen_eos;
|
||||
- apr_status_t rv;
|
||||
|
||||
/* Sometimes we'll get in a state where the input handling has
|
||||
* detected an error where we want to drop the connection, so if
|
||||
@@ -1616,54 +1616,57 @@ AP_DECLARE(int) ap_discard_request_body(request_rec *r)
|
||||
*
|
||||
* This function is also a no-op on a subrequest.
|
||||
*/
|
||||
- if (r->main || r->connection->keepalive == AP_CONN_CLOSE ||
|
||||
- ap_status_drops_connection(r->status)) {
|
||||
+ if (r->main || c->keepalive == AP_CONN_CLOSE) {
|
||||
+ return OK;
|
||||
+ }
|
||||
+ if (ap_status_drops_connection(r->status)) {
|
||||
+ c->keepalive = AP_CONN_CLOSE;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
||||
- seen_eos = 0;
|
||||
- do {
|
||||
- apr_bucket *bucket;
|
||||
+ for (;;) {
|
||||
+ apr_status_t rv;
|
||||
|
||||
rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
|
||||
APR_BLOCK_READ, HUGE_STRING_LEN);
|
||||
-
|
||||
if (rv != APR_SUCCESS) {
|
||||
- apr_brigade_destroy(bb);
|
||||
- return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
|
||||
+ rc = ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
- for (bucket = APR_BRIGADE_FIRST(bb);
|
||||
- bucket != APR_BRIGADE_SENTINEL(bb);
|
||||
- bucket = APR_BUCKET_NEXT(bucket))
|
||||
- {
|
||||
- const char *data;
|
||||
- apr_size_t len;
|
||||
+ while (!APR_BRIGADE_EMPTY(bb)) {
|
||||
+ apr_bucket *b = APR_BRIGADE_FIRST(bb);
|
||||
|
||||
- if (APR_BUCKET_IS_EOS(bucket)) {
|
||||
- seen_eos = 1;
|
||||
- break;
|
||||
+ if (APR_BUCKET_IS_EOS(b)) {
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
- /* These are metadata buckets. */
|
||||
- if (bucket->length == 0) {
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* We MUST read because in case we have an unknown-length
|
||||
- * bucket or one that morphs, we want to exhaust it.
|
||||
+ /* There is no need to read empty or metadata buckets or
|
||||
+ * buckets of known length, but we MUST read buckets of
|
||||
+ * unknown length in order to exhaust them.
|
||||
*/
|
||||
- rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
|
||||
+ if (b->length == (apr_size_t)-1) {
|
||||
+ apr_size_t len;
|
||||
+ const char *data;
|
||||
+
|
||||
+ rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
|
||||
if (rv != APR_SUCCESS) {
|
||||
- apr_brigade_destroy(bb);
|
||||
- return HTTP_BAD_REQUEST;
|
||||
+ rc = HTTP_BAD_REQUEST;
|
||||
+ goto cleanup;
|
||||
}
|
||||
}
|
||||
- apr_brigade_cleanup(bb);
|
||||
- } while (!seen_eos);
|
||||
|
||||
- return OK;
|
||||
+ apr_bucket_delete(b);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+cleanup:
|
||||
+ apr_brigade_cleanup(bb);
|
||||
+ if (rc != OK) {
|
||||
+ c->keepalive = AP_CONN_CLOSE;
|
||||
+ }
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/* Here we deal with getting the request message body from the client.
|
||||
diff --git a/server/protocol.c b/server/protocol.c
|
||||
index a2aa081..a554970 100644
|
||||
--- a/server/protocol.c
|
||||
+++ b/server/protocol.c
|
||||
@@ -1666,23 +1666,29 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew,
|
||||
rnew->main = (request_rec *) r;
|
||||
}
|
||||
|
||||
-static void end_output_stream(request_rec *r)
|
||||
+static void end_output_stream(request_rec *r, int status)
|
||||
{
|
||||
conn_rec *c = r->connection;
|
||||
apr_bucket_brigade *bb;
|
||||
apr_bucket *b;
|
||||
|
||||
bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
+ if (status != OK) {
|
||||
+ b = ap_bucket_error_create(status, NULL, r->pool, c->bucket_alloc);
|
||||
+ APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
+ }
|
||||
b = apr_bucket_eos_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
+
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
+ apr_brigade_cleanup(bb);
|
||||
}
|
||||
|
||||
AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub)
|
||||
{
|
||||
/* tell the filter chain there is no more content coming */
|
||||
if (!sub->eos_sent) {
|
||||
- end_output_stream(sub);
|
||||
+ end_output_stream(sub, OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1693,11 +1699,11 @@ AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub)
|
||||
*/
|
||||
AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
|
||||
{
|
||||
- (void) ap_discard_request_body(r);
|
||||
+ int status = ap_discard_request_body(r);
|
||||
|
||||
/* tell the filter chain there is no more content coming */
|
||||
if (!r->eos_sent) {
|
||||
- end_output_stream(r);
|
||||
+ end_output_stream(r, status);
|
||||
}
|
||||
}
|
||||
|
225
httpd-2.4.37-balancer-failover.patch
Normal file
225
httpd-2.4.37-balancer-failover.patch
Normal file
@ -0,0 +1,225 @@
|
||||
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
|
||||
index ec1e042..2c0500f 100644
|
||||
--- a/modules/proxy/mod_proxy_http.c
|
||||
+++ b/modules/proxy/mod_proxy_http.c
|
||||
@@ -310,16 +310,18 @@ static int stream_reqbody_read(proxy_http_req_t *req, apr_bucket_brigade *bb,
|
||||
return OK;
|
||||
}
|
||||
|
||||
-static int stream_reqbody(proxy_http_req_t *req, rb_methods rb_method)
|
||||
+static int stream_reqbody(proxy_http_req_t *req)
|
||||
{
|
||||
request_rec *r = req->r;
|
||||
int seen_eos = 0, rv = OK;
|
||||
apr_size_t hdr_len;
|
||||
char chunk_hdr[20]; /* must be here due to transient bucket. */
|
||||
+ conn_rec *origin = req->origin;
|
||||
proxy_conn_rec *p_conn = req->backend;
|
||||
apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
|
||||
apr_bucket_brigade *header_brigade = req->header_brigade;
|
||||
apr_bucket_brigade *input_brigade = req->input_brigade;
|
||||
+ rb_methods rb_method = req->rb_method;
|
||||
apr_off_t bytes, bytes_streamed = 0;
|
||||
apr_bucket *e;
|
||||
|
||||
@@ -333,7 +335,7 @@ static int stream_reqbody(proxy_http_req_t *req, rb_methods rb_method)
|
||||
}
|
||||
|
||||
if (!APR_BRIGADE_EMPTY(input_brigade)) {
|
||||
- /* If this brigade contains EOS, either stop or remove it. */
|
||||
+ /* If this brigade contains EOS, remove it and be done. */
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
|
||||
seen_eos = 1;
|
||||
|
||||
@@ -375,7 +377,8 @@ static int stream_reqbody(proxy_http_req_t *req, rb_methods rb_method)
|
||||
APR_BRIGADE_INSERT_TAIL(input_brigade, e);
|
||||
}
|
||||
}
|
||||
- else if (bytes_streamed > req->cl_val) {
|
||||
+ else if (rb_method == RB_STREAM_CL
|
||||
+ && bytes_streamed > req->cl_val) {
|
||||
/* C-L < bytes streamed?!?
|
||||
* We will error out after the body is completely
|
||||
* consumed, but we can't stream more bytes at the
|
||||
@@ -407,7 +410,7 @@ static int stream_reqbody(proxy_http_req_t *req, rb_methods rb_method)
|
||||
APR_BRIGADE_PREPEND(input_brigade, header_brigade);
|
||||
|
||||
/* Flush here on EOS because we won't stream_reqbody_read() again */
|
||||
- rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin,
|
||||
+ rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin,
|
||||
input_brigade, seen_eos);
|
||||
if (rv != OK) {
|
||||
return rv;
|
||||
@@ -454,10 +457,6 @@ static int spool_reqbody_cl(proxy_http_req_t *req, apr_off_t *bytes_spooled)
|
||||
/* If this brigade contains EOS, either stop or remove it. */
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
|
||||
seen_eos = 1;
|
||||
-
|
||||
- /* We can't pass this EOS to the output_filters. */
|
||||
- e = APR_BRIGADE_LAST(input_brigade);
|
||||
- apr_bucket_delete(e);
|
||||
}
|
||||
|
||||
apr_brigade_length(input_brigade, 1, &bytes);
|
||||
@@ -644,7 +643,18 @@ static int ap_proxy_http_prefetch(proxy_http_req_t *req,
|
||||
*/
|
||||
temp_brigade = apr_brigade_create(p, bucket_alloc);
|
||||
block = req->prefetch_nonblocking ? APR_NONBLOCK_READ : APR_BLOCK_READ;
|
||||
- do {
|
||||
+
|
||||
+ /* Account for saved input, if any. */
|
||||
+ apr_brigade_length(input_brigade, 0, &bytes_read);
|
||||
+
|
||||
+ /* Ensure we don't hit a wall where we have a buffer too small
|
||||
+ * for ap_get_brigade's filters to fetch us another bucket,
|
||||
+ * surrender once we hit 80 bytes less than MAX_MEM_SPOOL
|
||||
+ * (an arbitrary value).
|
||||
+ */
|
||||
+ while (bytes_read < MAX_MEM_SPOOL - 80
|
||||
+ && (APR_BRIGADE_EMPTY(input_brigade)
|
||||
+ || !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade)))) {
|
||||
status = ap_get_brigade(r->input_filters, temp_brigade,
|
||||
AP_MODE_READBYTES, block,
|
||||
MAX_MEM_SPOOL - bytes_read);
|
||||
@@ -686,15 +696,7 @@ static int ap_proxy_http_prefetch(proxy_http_req_t *req,
|
||||
c->client_ip, c->remote_host ? c->remote_host: "");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
-
|
||||
- /* Ensure we don't hit a wall where we have a buffer too small
|
||||
- * for ap_get_brigade's filters to fetch us another bucket,
|
||||
- * surrender once we hit 80 bytes less than MAX_MEM_SPOOL
|
||||
- * (an arbitrary value.)
|
||||
- */
|
||||
- } while ((bytes_read < MAX_MEM_SPOOL - 80)
|
||||
- && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))
|
||||
- && !req->prefetch_nonblocking);
|
||||
+ }
|
||||
|
||||
/* Use chunked request body encoding or send a content-length body?
|
||||
*
|
||||
@@ -838,35 +840,21 @@ static int ap_proxy_http_request(proxy_http_req_t *req)
|
||||
{
|
||||
int rv;
|
||||
request_rec *r = req->r;
|
||||
- apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
|
||||
- apr_bucket_brigade *header_brigade = req->header_brigade;
|
||||
- apr_bucket_brigade *input_brigade = req->input_brigade;
|
||||
|
||||
/* send the request header/body, if any. */
|
||||
switch (req->rb_method) {
|
||||
+ case RB_SPOOL_CL:
|
||||
case RB_STREAM_CL:
|
||||
case RB_STREAM_CHUNKED:
|
||||
if (req->do_100_continue) {
|
||||
- rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
|
||||
- req->origin, header_brigade, 1);
|
||||
+ rv = ap_proxy_pass_brigade(req->bucket_alloc, r, req->backend,
|
||||
+ req->origin, req->header_brigade, 1);
|
||||
}
|
||||
else {
|
||||
- rv = stream_reqbody(req, req->rb_method);
|
||||
+ rv = stream_reqbody(req);
|
||||
}
|
||||
break;
|
||||
|
||||
- case RB_SPOOL_CL:
|
||||
- /* Prefetch has built the header and spooled the whole body;
|
||||
- * if we don't expect 100-continue we can flush both all at once,
|
||||
- * otherwise flush the header only.
|
||||
- */
|
||||
- if (!req->do_100_continue) {
|
||||
- APR_BRIGADE_CONCAT(header_brigade, input_brigade);
|
||||
- }
|
||||
- rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
|
||||
- req->origin, header_brigade, 1);
|
||||
- break;
|
||||
-
|
||||
default:
|
||||
/* shouldn't be possible */
|
||||
rv = HTTP_INTERNAL_SERVER_ERROR;
|
||||
@@ -1577,15 +1565,10 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
|
||||
|
||||
/* Send the request body (fully). */
|
||||
switch(req->rb_method) {
|
||||
+ case RB_SPOOL_CL:
|
||||
case RB_STREAM_CL:
|
||||
case RB_STREAM_CHUNKED:
|
||||
- status = stream_reqbody(req, req->rb_method);
|
||||
- break;
|
||||
- case RB_SPOOL_CL:
|
||||
- /* Prefetch has spooled the whole body, flush it. */
|
||||
- status = ap_proxy_pass_brigade(req->bucket_alloc, r,
|
||||
- backend, origin,
|
||||
- req->input_brigade, 1);
|
||||
+ status = stream_reqbody(req);
|
||||
break;
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
@@ -1940,6 +1923,7 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
const char *u;
|
||||
proxy_http_req_t *req = NULL;
|
||||
proxy_conn_rec *backend = NULL;
|
||||
+ apr_bucket_brigade *input_brigade = NULL;
|
||||
int is_ssl = 0;
|
||||
conn_rec *c = r->connection;
|
||||
proxy_dir_conf *dconf;
|
||||
@@ -2005,8 +1989,20 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
|
||||
dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
|
||||
|
||||
+ /* We possibly reuse input data prefetched in previous call(s), e.g. for a
|
||||
+ * balancer fallback scenario, and in this case the 100 continue settings
|
||||
+ * should be consistent between balancer members. If not, we need to ignore
|
||||
+ * Proxy100Continue on=>off once we tried to prefetch already, otherwise
|
||||
+ * the HTTP_IN filter won't send 100 Continue for us anymore, and we might
|
||||
+ * deadlock with the client waiting for each other. Note that off=>on is
|
||||
+ * not an issue because in this case r->expecting_100 is false (the 100
|
||||
+ * Continue is out already), but we make sure that prefetch will be
|
||||
+ * nonblocking to avoid passing more time there.
|
||||
+ */
|
||||
+ apr_pool_userdata_get((void **)&input_brigade, "proxy-req-input", p);
|
||||
+
|
||||
/* Should we handle end-to-end or ping 100-continue? */
|
||||
- if ((r->expecting_100 && dconf->forward_100_continue)
|
||||
+ if ((r->expecting_100 && (dconf->forward_100_continue || input_brigade))
|
||||
|| PROXY_DO_100_CONTINUE(worker, r)) {
|
||||
/* We need to reset r->expecting_100 or prefetching will cause
|
||||
* ap_http_filter() to send "100 Continue" response by itself. So
|
||||
@@ -2023,7 +2019,8 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
/* Should we block while prefetching the body or try nonblocking and flush
|
||||
* data to the backend ASAP?
|
||||
*/
|
||||
- else if (apr_table_get(r->subprocess_env, "proxy-prefetch-nonblocking")) {
|
||||
+ else if (input_brigade || apr_table_get(r->subprocess_env,
|
||||
+ "proxy-prefetch-nonblocking")) {
|
||||
req->prefetch_nonblocking = 1;
|
||||
}
|
||||
|
||||
@@ -2048,6 +2045,17 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
sizeof(req->server_portstr))))
|
||||
goto cleanup;
|
||||
|
||||
+ /* The header is always (re-)built since it depends on worker settings,
|
||||
+ * but the body can be fetched only once (even partially), so it's saved
|
||||
+ * in between proxy_http_handler() calls should we come back here.
|
||||
+ */
|
||||
+ req->header_brigade = apr_brigade_create(p, req->bucket_alloc);
|
||||
+ if (input_brigade == NULL) {
|
||||
+ input_brigade = apr_brigade_create(p, req->bucket_alloc);
|
||||
+ apr_pool_userdata_setn(input_brigade, "proxy-req-input", NULL, p);
|
||||
+ }
|
||||
+ req->input_brigade = input_brigade;
|
||||
+
|
||||
/* Prefetch (nonlocking) the request body so to increase the chance to get
|
||||
* the whole (or enough) body and determine Content-Length vs chunked or
|
||||
* spooled. By doing this before connecting or reusing the backend, we want
|
||||
@@ -2058,8 +2066,6 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
* to reduce to the minimum the unavoidable local is_socket_connected() vs
|
||||
* remote keepalive race condition.
|
||||
*/
|
||||
- req->input_brigade = apr_brigade_create(p, req->bucket_alloc);
|
||||
- req->header_brigade = apr_brigade_create(p, req->bucket_alloc);
|
||||
if ((status = ap_proxy_http_prefetch(req, uri, locurl)) != OK)
|
||||
goto cleanup;
|
||||
|
42
httpd-2.4.37-fips-segfault.patch
Normal file
42
httpd-2.4.37-fips-segfault.patch
Normal file
@ -0,0 +1,42 @@
|
||||
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
||||
index 37947e7..b50c259 100644
|
||||
--- a/modules/ssl/mod_ssl.c
|
||||
+++ b/modules/ssl/mod_ssl.c
|
||||
@@ -331,9 +331,6 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
|
||||
/*
|
||||
* Try to kill the internals of the SSL library.
|
||||
*/
|
||||
-#ifdef HAVE_FIPS
|
||||
- FIPS_mode_set(0);
|
||||
-#endif
|
||||
/* Corresponds to OBJ_create()s */
|
||||
OBJ_cleanup();
|
||||
/* Corresponds to OPENSSL_load_builtin_modules() */
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index 5063a72..21e41e2 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -183,6 +183,14 @@ int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef HAVE_FIPS
|
||||
+static apr_status_t ssl_fips_cleanup(void *data)
|
||||
+{
|
||||
+ FIPS_mode_set(0);
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Per-module initialization
|
||||
*/
|
||||
@@ -316,6 +324,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
|
||||
if (FIPS_mode_set(1)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01884)
|
||||
"Operating in SSL FIPS mode");
|
||||
+ apr_pool_cleanup_register(p, NULL, ssl_fips_cleanup,
|
||||
+ apr_pool_cleanup_null);
|
||||
}
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed");
|
199
httpd-2.4.37-hcheck-mem-issues.patch
Normal file
199
httpd-2.4.37-hcheck-mem-issues.patch
Normal file
@ -0,0 +1,199 @@
|
||||
diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c
|
||||
index bd89779..d7c0a68 100644
|
||||
--- a/modules/proxy/mod_proxy_hcheck.c
|
||||
+++ b/modules/proxy/mod_proxy_hcheck.c
|
||||
@@ -33,7 +33,6 @@ module AP_MODULE_DECLARE_DATA proxy_hcheck_module;
|
||||
#endif
|
||||
#else
|
||||
#define HC_USE_THREADS 0
|
||||
-typedef void apr_thread_pool_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@@ -73,7 +72,7 @@ typedef struct {
|
||||
proxy_balancer *balancer;
|
||||
proxy_worker *worker;
|
||||
proxy_worker *hc;
|
||||
- apr_time_t now;
|
||||
+ apr_time_t *now;
|
||||
} baton_t;
|
||||
|
||||
static void *hc_create_config(apr_pool_t *p, server_rec *s)
|
||||
@@ -89,7 +88,10 @@ static void *hc_create_config(apr_pool_t *p, server_rec *s)
|
||||
}
|
||||
|
||||
static ap_watchdog_t *watchdog;
|
||||
-static int tpsize = HC_THREADPOOL_SIZE;
|
||||
+#if HC_USE_THREADS
|
||||
+static apr_thread_pool_t *hctp;
|
||||
+static int tpsize;
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* This serves double duty by not only validating (and creating)
|
||||
@@ -825,29 +827,28 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
|
||||
server_rec *s = baton->ctx->s;
|
||||
proxy_worker *worker = baton->worker;
|
||||
proxy_worker *hc = baton->hc;
|
||||
- apr_time_t now = baton->now;
|
||||
+ apr_time_t now;
|
||||
apr_status_t rv;
|
||||
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03256)
|
||||
"%sHealth checking %s", (thread ? "Threaded " : ""),
|
||||
worker->s->name);
|
||||
|
||||
- worker->s->updated = now;
|
||||
if (hc->s->method == TCP) {
|
||||
rv = hc_check_tcp(baton);
|
||||
}
|
||||
else {
|
||||
rv = hc_check_http(baton);
|
||||
}
|
||||
+
|
||||
+ now = apr_time_now();
|
||||
if (rv == APR_ENOTIMPL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(03257)
|
||||
"Somehow tried to use unimplemented hcheck method: %d",
|
||||
(int)hc->s->method);
|
||||
- apr_pool_destroy(baton->ptemp);
|
||||
- return NULL;
|
||||
}
|
||||
/* what state are we in ? */
|
||||
- if (PROXY_WORKER_IS_HCFAILED(worker)) {
|
||||
+ else if (PROXY_WORKER_IS_HCFAILED(worker)) {
|
||||
if (rv == APR_SUCCESS) {
|
||||
worker->s->pcount += 1;
|
||||
if (worker->s->pcount >= worker->s->passes) {
|
||||
@@ -860,7 +861,8 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
|
||||
|
||||
}
|
||||
}
|
||||
- } else {
|
||||
+ }
|
||||
+ else {
|
||||
if (rv != APR_SUCCESS) {
|
||||
worker->s->error_time = now;
|
||||
worker->s->fcount += 1;
|
||||
@@ -873,7 +875,12 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if (baton->now) {
|
||||
+ *baton->now = now;
|
||||
+ }
|
||||
apr_pool_destroy(baton->ptemp);
|
||||
+ worker->s->updated = now;
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -881,12 +888,10 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
- apr_time_t now = apr_time_now();
|
||||
proxy_balancer *balancer;
|
||||
sctx_t *ctx = (sctx_t *)data;
|
||||
server_rec *s = ctx->s;
|
||||
proxy_server_conf *conf;
|
||||
- static apr_thread_pool_t *hctp = NULL;
|
||||
|
||||
switch (state) {
|
||||
case AP_WATCHDOG_STATE_STARTING:
|
||||
@@ -913,7 +918,6 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
|
||||
"Skipping apr_thread_pool_create()");
|
||||
hctp = NULL;
|
||||
}
|
||||
-
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -929,45 +933,53 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
|
||||
ctx->s = s;
|
||||
for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
|
||||
int n;
|
||||
+ apr_time_t now;
|
||||
proxy_worker **workers;
|
||||
proxy_worker *worker;
|
||||
/* Have any new balancers or workers been added dynamically? */
|
||||
ap_proxy_sync_balancer(balancer, s, conf);
|
||||
workers = (proxy_worker **)balancer->workers->elts;
|
||||
+ now = apr_time_now();
|
||||
for (n = 0; n < balancer->workers->nelts; n++) {
|
||||
worker = *workers;
|
||||
if (!PROXY_WORKER_IS(worker, PROXY_WORKER_STOPPED) &&
|
||||
- (worker->s->method != NONE) &&
|
||||
- (now > worker->s->updated + worker->s->interval)) {
|
||||
+ (worker->s->method != NONE) &&
|
||||
+ (worker->s->updated != 0) &&
|
||||
+ (now > worker->s->updated + worker->s->interval)) {
|
||||
baton_t *baton;
|
||||
apr_pool_t *ptemp;
|
||||
+
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
|
||||
"Checking %s worker: %s [%d] (%pp)", balancer->s->name,
|
||||
worker->s->name, worker->s->method, worker);
|
||||
|
||||
if ((rv = hc_init_worker(ctx, worker)) != APR_SUCCESS) {
|
||||
+ worker->s->updated = now;
|
||||
return rv;
|
||||
}
|
||||
- /* This pool must last the lifetime of the (possible) thread */
|
||||
+ worker->s->updated = 0;
|
||||
+
|
||||
+ /* This pool has the lifetime of the check */
|
||||
apr_pool_create(&ptemp, ctx->p);
|
||||
apr_pool_tag(ptemp, "hc_request");
|
||||
- baton = apr_palloc(ptemp, sizeof(baton_t));
|
||||
+ baton = apr_pcalloc(ptemp, sizeof(baton_t));
|
||||
baton->ctx = ctx;
|
||||
- baton->now = now;
|
||||
baton->balancer = balancer;
|
||||
baton->worker = worker;
|
||||
baton->ptemp = ptemp;
|
||||
baton->hc = hc_get_hcworker(ctx, worker, ptemp);
|
||||
-
|
||||
- if (!hctp) {
|
||||
- hc_check(NULL, baton);
|
||||
- }
|
||||
#if HC_USE_THREADS
|
||||
- else {
|
||||
- rv = apr_thread_pool_push(hctp, hc_check, (void *)baton,
|
||||
- APR_THREAD_TASK_PRIORITY_NORMAL, NULL);
|
||||
+ if (hctp) {
|
||||
+ apr_thread_pool_push(hctp, hc_check, (void *)baton,
|
||||
+ APR_THREAD_TASK_PRIORITY_NORMAL,
|
||||
+ NULL);
|
||||
}
|
||||
+ else
|
||||
#endif
|
||||
+ {
|
||||
+ baton->now = &now;
|
||||
+ hc_check(NULL, baton);
|
||||
+ }
|
||||
}
|
||||
workers++;
|
||||
}
|
||||
@@ -986,9 +998,9 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, rv, s, APLOGNO(03315)
|
||||
"apr_thread_pool_destroy() failed");
|
||||
}
|
||||
+ hctp = NULL;
|
||||
}
|
||||
#endif
|
||||
- hctp = NULL;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
@@ -996,7 +1008,10 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
|
||||
static int hc_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
apr_pool_t *ptemp)
|
||||
{
|
||||
+#if HC_USE_THREADS
|
||||
+ hctp = NULL;
|
||||
tpsize = HC_THREADPOOL_SIZE;
|
||||
+#endif
|
||||
return OK;
|
||||
}
|
||||
static int hc_post_config(apr_pool_t *p, apr_pool_t *plog,
|
13
httpd-2.4.37-htcacheclean-dont-break.patch
Normal file
13
httpd-2.4.37-htcacheclean-dont-break.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/support/htcacheclean.c b/support/htcacheclean.c
|
||||
index 8692377..fde34c9 100644
|
||||
--- a/support/htcacheclean.c
|
||||
+++ b/support/htcacheclean.c
|
||||
@@ -557,8 +557,6 @@ static int list_urls(char *path, apr_pool_t *pool, apr_off_t round)
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
- break;
|
||||
}
|
||||
}
|
||||
}
|
87
httpd-2.4.37-logjournal.patch
Normal file
87
httpd-2.4.37-logjournal.patch
Normal file
@ -0,0 +1,87 @@
|
||||
diff --git a/modules/loggers/config.m4 b/modules/loggers/config.m4
|
||||
index 762e773e94..0848d2e377 100644
|
||||
--- a/modules/loggers/config.m4
|
||||
+++ b/modules/loggers/config.m4
|
||||
@@ -5,6 +5,8 @@ dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
|
||||
APACHE_MODPATH_INIT(loggers)
|
||||
|
||||
APACHE_MODULE(log_config, logging configuration. You won't be able to log requests to the server without this module., , , yes)
|
||||
+APR_ADDTO(MOD_LOG_CONFIG_LDADD, [$SYSTEMD_LIBS])
|
||||
+
|
||||
APACHE_MODULE(log_debug, configurable debug logging, , , most)
|
||||
APACHE_MODULE(log_forensic, forensic logging)
|
||||
|
||||
diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c
|
||||
index 996c09cf49..50a056a2f8 100644
|
||||
--- a/modules/loggers/mod_log_config.c
|
||||
+++ b/modules/loggers/mod_log_config.c
|
||||
@@ -172,6 +172,10 @@
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+#include <systemd/sd-journal.h>
|
||||
+#endif
|
||||
+
|
||||
#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
|
||||
|
||||
module AP_MODULE_DECLARE_DATA log_config_module;
|
||||
@@ -1638,6 +1642,25 @@ static apr_status_t ap_default_log_writer( request_rec *r,
|
||||
|
||||
return rv;
|
||||
}
|
||||
+
|
||||
+static apr_status_t wrap_journal_stream(apr_pool_t *p, apr_file_t **outfd,
|
||||
+ int priority)
|
||||
+{
|
||||
+#ifdef HAVE_SYSTEMD
|
||||
+ int fd;
|
||||
+
|
||||
+ fd = sd_journal_stream_fd("httpd", priority, 0);
|
||||
+ if (fd < 0) return fd;
|
||||
+
|
||||
+ /* This is an AF_UNIX socket fd so is more pipe-like than
|
||||
+ * file-like (the fd is neither seekable or readable), and use of
|
||||
+ * apr_os_pipe_put_ex() allows cleanup registration. */
|
||||
+ return apr_os_pipe_put_ex(outfd, &fd, 1, p);
|
||||
+#else
|
||||
+ return APR_ENOTIMPL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
|
||||
const char* name)
|
||||
{
|
||||
@@ -1650,6 +1673,32 @@ static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
|
||||
}
|
||||
return ap_piped_log_write_fd(pl);
|
||||
}
|
||||
+ else if (strncasecmp(name, "journald:", 9) == 0) {
|
||||
+ int priority;
|
||||
+ const char *err = ap_parse_log_level(name + 9, &priority);
|
||||
+ apr_status_t rv;
|
||||
+ apr_file_t *fd;
|
||||
+
|
||||
+ if (err == NULL && priority > LOG_DEBUG) {
|
||||
+ err = "TRACE level debugging not supported with journald";
|
||||
+ }
|
||||
+
|
||||
+ if (err) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
|
||||
+ "invalid journald log priority name %s: %s",
|
||||
+ name, err);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ rv = wrap_journal_stream(p, &fd, priority);
|
||||
+ if (rv) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
|
||||
+ "could not open journald log stream");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return fd;
|
||||
+ }
|
||||
else {
|
||||
const char *fname = ap_server_root_relative(p, name);
|
||||
apr_file_t *fd;
|
544
httpd-2.4.37-mod-md-mod-ssl-hooks.patch
Normal file
544
httpd-2.4.37-mod-md-mod-ssl-hooks.patch
Normal file
@ -0,0 +1,544 @@
|
||||
diff --git a/modules/ssl/mod_ssl.h b/modules/ssl/mod_ssl.h
|
||||
index 24a65a0..a360911 100644
|
||||
--- a/modules/ssl/mod_ssl.h
|
||||
+++ b/modules/ssl/mod_ssl.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "apr_optional.h"
|
||||
+#include "apr_tables.h" /* for apr_array_header_t */
|
||||
|
||||
/* Create a set of SSL_DECLARE(type), SSL_DECLARE_NONSTD(type) and
|
||||
* SSL_DECLARE_DATA with appropriate export and import tags for the platform
|
||||
@@ -86,6 +87,34 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
|
||||
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *,
|
||||
ap_conf_vector_t *,
|
||||
int proxy, int enable));
|
||||
+
|
||||
+/* Check for availability of new hooks */
|
||||
+#define SSL_CERT_HOOKS
|
||||
+#ifdef SSL_CERT_HOOKS
|
||||
+
|
||||
+/** Lets others add certificate and key files to the given server.
|
||||
+ * For each cert a key must also be added.
|
||||
+ * @param cert_file and array of const char* with the path to the certificate chain
|
||||
+ * @param key_file and array of const char* with the path to the private key file
|
||||
+ */
|
||||
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, add_cert_files,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ apr_array_header_t *cert_files,
|
||||
+ apr_array_header_t *key_files))
|
||||
+
|
||||
+/** In case no certificates are available for a server, this
|
||||
+ * lets other modules add a fallback certificate for the time
|
||||
+ * being. Regular requests against this server will be answered
|
||||
+ * with a 503.
|
||||
+ * @param cert_file and array of const char* with the path to the certificate chain
|
||||
+ * @param key_file and array of const char* with the path to the private key file
|
||||
+ */
|
||||
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, add_fallback_cert_files,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ apr_array_header_t *cert_files,
|
||||
+ apr_array_header_t *key_files))
|
||||
+
|
||||
+#endif /* SSL_CERT_HOOKS */
|
||||
|
||||
#endif /* __MOD_SSL_H__ */
|
||||
/** @} */
|
||||
diff --git a/modules/ssl/mod_ssl_openssl.h b/modules/ssl/mod_ssl_openssl.h
|
||||
index 0fa654a..d4f684f 100644
|
||||
--- a/modules/ssl/mod_ssl_openssl.h
|
||||
+++ b/modules/ssl/mod_ssl_openssl.h
|
||||
@@ -69,5 +69,45 @@ APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, pre_handshake,
|
||||
APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, proxy_post_handshake,
|
||||
(conn_rec *c, SSL *ssl))
|
||||
|
||||
+/** On TLS connections that do not relate to a configured virtual host,
|
||||
+ * allow other modules to provide a X509 certificate and EVP_PKEY to
|
||||
+ * be used on the connection. This first hook which does not
|
||||
+ * return DECLINED will determine the outcome. */
|
||||
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, answer_challenge,
|
||||
+ (conn_rec *c, const char *server_name,
|
||||
+ X509 **pcert, EVP_PKEY **pkey))
|
||||
+
|
||||
+/** During post_config phase, ask around if someone wants to provide
|
||||
+ * OCSP stapling status information for the given cert (with the also
|
||||
+ * provided issuer certificate). The first hook which does not
|
||||
+ * return DECLINED promises to take responsibility (and respond
|
||||
+ * in later calls via hook ssl_get_stapling_status).
|
||||
+ * If no hook takes over, mod_ssl's own stapling implementation will
|
||||
+ * be applied (if configured).
|
||||
+ */
|
||||
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, init_stapling_status,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ X509 *cert, X509 *issuer))
|
||||
+
|
||||
+/** Anyone answering positive to ssl_init_stapling_status for a
|
||||
+ * certificate, needs to register here and supply the actual OCSP stapling
|
||||
+ * status data (OCSP_RESP) for a new connection.
|
||||
+ * A hook supplying the response data must return APR_SUCCESS.
|
||||
+ * The data is returned in DER encoded bytes via pder and pderlen. The
|
||||
+ * returned pointer may be NULL, which indicates that data is (currently)
|
||||
+ * unavailable.
|
||||
+ * If DER data is returned, it MUST come from a response with
|
||||
+ * status OCSP_RESPONSE_STATUS_SUCCESSFUL and V_OCSP_CERTSTATUS_GOOD
|
||||
+ * or V_OCSP_CERTSTATUS_REVOKED, not V_OCSP_CERTSTATUS_UNKNOWN. This means
|
||||
+ * errors in OCSP retrieval are to be handled/logged by the hook and
|
||||
+ * are not done by mod_ssl.
|
||||
+ * Any DER bytes returned MUST be allocated via malloc() and ownership
|
||||
+ * passes to mod_ssl. Meaning, the hook must return a malloced copy of
|
||||
+ * the data it has. mod_ssl (or OpenSSL) will free it.
|
||||
+ */
|
||||
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, get_stapling_status,
|
||||
+ (unsigned char **pder, int *pderlen,
|
||||
+ conn_rec *c, server_rec *s, X509 *cert))
|
||||
+
|
||||
#endif /* __MOD_SSL_OPENSSL_H__ */
|
||||
/** @} */
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index 21e41e2..ef631c1 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -36,6 +36,25 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, init_server,
|
||||
(server_rec *s,apr_pool_t *p,int is_proxy,SSL_CTX *ctx),
|
||||
(s,p,is_proxy,ctx), OK, DECLINED)
|
||||
|
||||
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, add_cert_files,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ apr_array_header_t *cert_files, apr_array_header_t *key_files),
|
||||
+ (s, p, cert_files, key_files),
|
||||
+ OK, DECLINED)
|
||||
+
|
||||
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, add_fallback_cert_files,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ apr_array_header_t *cert_files, apr_array_header_t *key_files),
|
||||
+ (s, p, cert_files, key_files),
|
||||
+ OK, DECLINED)
|
||||
+
|
||||
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, answer_challenge,
|
||||
+ (conn_rec *c, const char *server_name,
|
||||
+ X509 **pcert, EVP_PKEY **pkey),
|
||||
+ (c, server_name, pcert, pkey),
|
||||
+ DECLINED, DECLINED)
|
||||
+
|
||||
+
|
||||
/* _________________________________________________________________
|
||||
**
|
||||
** Module Initialization
|
||||
@@ -165,18 +184,18 @@ static void ssl_add_version_components(apr_pool_t *p,
|
||||
modver, AP_SERVER_BASEVERSION, incver);
|
||||
}
|
||||
|
||||
-/**************************************************************************************************/
|
||||
-/* Managed Domains Interface */
|
||||
-
|
||||
-static APR_OPTIONAL_FN_TYPE(md_is_managed) *md_is_managed;
|
||||
-static APR_OPTIONAL_FN_TYPE(md_get_certificate) *md_get_certificate;
|
||||
-static APR_OPTIONAL_FN_TYPE(md_is_challenge) *md_is_challenge;
|
||||
+/* _________________________________________________________________
|
||||
+**
|
||||
+** Let other answer special connection attempts.
|
||||
+** Used in ACME challenge handling by mod_md.
|
||||
+** _________________________________________________________________
|
||||
+*/
|
||||
|
||||
int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
X509 **pcert, EVP_PKEY **pkey)
|
||||
{
|
||||
- if (md_is_challenge) {
|
||||
- return md_is_challenge(c, servername, pcert, pkey);
|
||||
+ if (APR_SUCCESS == ssl_run_answer_challenge(c, servername, pcert, pkey)) {
|
||||
+ return 1;
|
||||
}
|
||||
*pcert = NULL;
|
||||
*pkey = NULL;
|
||||
@@ -231,16 +250,6 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
|
||||
ssl_config_global_create(base_server); /* just to avoid problems */
|
||||
ssl_config_global_fix(mc);
|
||||
|
||||
- /* Initialize our interface to mod_md, if it is loaded
|
||||
- */
|
||||
- md_is_managed = APR_RETRIEVE_OPTIONAL_FN(md_is_managed);
|
||||
- md_get_certificate = APR_RETRIEVE_OPTIONAL_FN(md_get_certificate);
|
||||
- md_is_challenge = APR_RETRIEVE_OPTIONAL_FN(md_is_challenge);
|
||||
- if (!md_is_managed || !md_get_certificate) {
|
||||
- md_is_managed = NULL;
|
||||
- md_get_certificate = NULL;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* try to fix the configuration and open the dedicated SSL
|
||||
* logfile as early as possible
|
||||
@@ -1392,8 +1401,7 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
|
||||
* loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and
|
||||
* later, we defer to the code in ssl_init_server_ctx.
|
||||
*/
|
||||
- if ((mctx->stapling_enabled == TRUE) &&
|
||||
- !ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
|
||||
+ if (!ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567)
|
||||
"Unable to configure certificate %s for stapling",
|
||||
key_id);
|
||||
@@ -1788,11 +1796,13 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
|
||||
apr_array_header_t *pphrases)
|
||||
{
|
||||
apr_status_t rv;
|
||||
+ modssl_pk_server_t *pks;
|
||||
#ifdef HAVE_SSL_CONF_CMD
|
||||
ssl_ctx_param_t *param = (ssl_ctx_param_t *)sc->server->ssl_ctx_param->elts;
|
||||
SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
|
||||
int i;
|
||||
#endif
|
||||
+ int n;
|
||||
|
||||
/*
|
||||
* Check for problematic re-initializations
|
||||
@@ -1804,50 +1814,24 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(10083)
|
||||
- "Init: (%s) mod_md support is %s.", ssl_util_vhostid(p, s),
|
||||
- md_is_managed? "available" : "unavailable");
|
||||
- if (md_is_managed && md_is_managed(s)) {
|
||||
- modssl_pk_server_t *const pks = sc->server->pks;
|
||||
- if (pks->cert_files->nelts > 0 || pks->key_files->nelts > 0) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10084)
|
||||
- "Init: (%s) You configured certificate/key files on this host, but "
|
||||
- "is is covered by a Managed Domain. You need to remove these directives "
|
||||
- "for the Managed Domain to take over.", ssl_util_vhostid(p, s));
|
||||
- }
|
||||
- else {
|
||||
- const char *key_file, *cert_file, *chain_file;
|
||||
-
|
||||
- key_file = cert_file = chain_file = NULL;
|
||||
-
|
||||
- if (md_get_certificate) {
|
||||
- rv = md_get_certificate(s, p, &key_file, &cert_file);
|
||||
- }
|
||||
- else {
|
||||
- rv = APR_ENOTIMPL;
|
||||
- }
|
||||
-
|
||||
- if (key_file && cert_file) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
|
||||
- "%s: installing key=%s, cert=%s, chain=%s",
|
||||
- ssl_util_vhostid(p, s), key_file, cert_file, chain_file);
|
||||
- APR_ARRAY_PUSH(pks->key_files, const char *) = key_file;
|
||||
- APR_ARRAY_PUSH(pks->cert_files, const char *) = cert_file;
|
||||
- sc->server->cert_chain = chain_file;
|
||||
- }
|
||||
-
|
||||
- if (APR_STATUS_IS_EAGAIN(rv)) {
|
||||
- /* Managed Domain not ready yet. This is not a reason to fail the config */
|
||||
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085)
|
||||
- "Init: %s will respond with '503 Service Unavailable' for now. This "
|
||||
- "host is part of a Managed Domain, but no SSL certificate is "
|
||||
- "available (yet).", ssl_util_vhostid(p, s));
|
||||
- pks->service_unavailable = 1;
|
||||
- }
|
||||
- else if (rv != APR_SUCCESS) {
|
||||
- return rv;
|
||||
- }
|
||||
- }
|
||||
+ /* Allow others to provide certificate files */
|
||||
+ pks = sc->server->pks;
|
||||
+ n = pks->cert_files->nelts;
|
||||
+ ssl_run_add_cert_files(s, p, pks->cert_files, pks->key_files);
|
||||
+
|
||||
+ if (n < pks->cert_files->nelts) {
|
||||
+ /* this overrides any old chain configuration */
|
||||
+ sc->server->cert_chain = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (apr_is_empty_array(pks->cert_files) && !sc->server->cert_chain) {
|
||||
+ ssl_run_add_fallback_cert_files(s, p, pks->cert_files, pks->key_files);
|
||||
+
|
||||
+ pks->service_unavailable = 1;
|
||||
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085)
|
||||
+ "Init: %s will respond with '503 Service Unavailable' for now. There "
|
||||
+ "are no SSL certificates configured and no other module contributed any.",
|
||||
+ ssl_util_vhostid(p, s));
|
||||
}
|
||||
|
||||
if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) {
|
||||
@@ -1900,7 +1884,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
|
||||
* (late) point makes sure that we catch both certificates loaded
|
||||
* via SSLCertificateFile and SSLOpenSSLConfCmd Certificate.
|
||||
*/
|
||||
- if (sc->server->stapling_enabled == TRUE) {
|
||||
+ do {
|
||||
X509 *cert;
|
||||
int i = 0;
|
||||
int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx,
|
||||
@@ -1917,7 +1901,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
|
||||
SSL_CERT_SET_NEXT);
|
||||
i++;
|
||||
}
|
||||
- }
|
||||
+ } while(0);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TLS_SESSION_TICKETS
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index e6a9f67..a5e86e4 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -2303,6 +2303,37 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
|
||||
}
|
||||
|
||||
#ifdef HAVE_TLSEXT
|
||||
+
|
||||
+static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
|
||||
+ SSL *ssl, X509 *cert, EVP_PKEY *key)
|
||||
+{
|
||||
+ SSLConnRec *sslcon = myConnConfig(c);
|
||||
+
|
||||
+ sslcon->service_unavailable = 1;
|
||||
+ if ((SSL_use_certificate(ssl, cert) < 1)) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10086)
|
||||
+ "Failed to configure challenge certificate %s",
|
||||
+ servername);
|
||||
+ return APR_EGENERAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!SSL_use_PrivateKey(ssl, key)) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10087)
|
||||
+ "error '%s' using Challenge key: %s",
|
||||
+ ERR_error_string(ERR_peek_last_error(), NULL),
|
||||
+ servername);
|
||||
+ return APR_EGENERAL;
|
||||
+ }
|
||||
+
|
||||
+ if (SSL_check_private_key(ssl) < 1) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10088)
|
||||
+ "Challenge certificate and private key %s "
|
||||
+ "do not match", servername);
|
||||
+ return APR_EGENERAL;
|
||||
+ }
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* This function sets the virtual host from an extended
|
||||
* client hello with a server name indication extension ("SNI", cf. RFC 6066).
|
||||
@@ -2332,30 +2363,12 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
else if (ssl_is_challenge(c, servername, &cert, &key)) {
|
||||
-
|
||||
- sslcon->service_unavailable = 1;
|
||||
- if ((SSL_use_certificate(ssl, cert) < 1)) {
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10086)
|
||||
- "Failed to configure challenge certificate %s",
|
||||
- servername);
|
||||
+ /* With ACMEv1 we can have challenge connections to a unknown domains
|
||||
+ * that need to be answered with a special certificate and will
|
||||
+ * otherwise not answer any requests. */
|
||||
+ if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
-
|
||||
- if (!SSL_use_PrivateKey(ssl, key)) {
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10087)
|
||||
- "error '%s' using Challenge key: %s",
|
||||
- ERR_error_string(ERR_peek_last_error(), NULL),
|
||||
- servername);
|
||||
- return APR_EGENERAL;
|
||||
- }
|
||||
-
|
||||
- if (SSL_check_private_key(ssl) < 1) {
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10088)
|
||||
- "Challenge certificate and private key %s "
|
||||
- "do not match", servername);
|
||||
- return APR_EGENERAL;
|
||||
- }
|
||||
-
|
||||
}
|
||||
else {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
|
||||
@@ -2648,6 +2661,23 @@ int ssl_callback_alpn_select(SSL *ssl,
|
||||
proposed);
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
+
|
||||
+ /* protocol was switched, this could be a challenge protocol such as "acme-tls/1".
|
||||
+ * For that to work, we need to allow overrides to our ssl certificate.
|
||||
+ * However, exclude challenge checks on our best known traffic protocol.
|
||||
+ * (http/1.1 is the default, we never switch to it anyway.)
|
||||
+ */
|
||||
+ if (strcmp("h2", proposed)) {
|
||||
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
+ X509 *cert;
|
||||
+ EVP_PKEY *key;
|
||||
+
|
||||
+ if (ssl_is_challenge(c, servername, &cert, &key)) {
|
||||
+ if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
|
||||
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c
|
||||
index c3e2cfa..4df0a9a 100644
|
||||
--- a/modules/ssl/ssl_util_stapling.c
|
||||
+++ b/modules/ssl/ssl_util_stapling.c
|
||||
@@ -31,12 +31,28 @@
|
||||
#include "ssl_private.h"
|
||||
#include "ap_mpm.h"
|
||||
#include "apr_thread_mutex.h"
|
||||
+#include "mod_ssl_openssl.h"
|
||||
+
|
||||
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, init_stapling_status,
|
||||
+ (server_rec *s, apr_pool_t *p,
|
||||
+ X509 *cert, X509 *issuer),
|
||||
+ (s, p, cert, issuer),
|
||||
+ DECLINED, DECLINED)
|
||||
+
|
||||
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, get_stapling_status,
|
||||
+ (unsigned char **pder, int *pderlen,
|
||||
+ conn_rec *c, server_rec *s, X509 *cert),
|
||||
+ (pder, pderlen, c, s, cert),
|
||||
+ DECLINED, DECLINED)
|
||||
+
|
||||
|
||||
#ifdef HAVE_OCSP_STAPLING
|
||||
|
||||
static int stapling_cache_mutex_on(server_rec *s);
|
||||
static int stapling_cache_mutex_off(server_rec *s);
|
||||
|
||||
+static int stapling_cb(SSL *ssl, void *arg);
|
||||
+
|
||||
/**
|
||||
* Maxiumum OCSP stapling response size. This should be the response for a
|
||||
* single certificate and will typically include the responder certificate chain
|
||||
@@ -119,7 +135,38 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
OCSP_CERTID *cid = NULL;
|
||||
STACK_OF(OPENSSL_STRING) *aia = NULL;
|
||||
|
||||
- if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
|
||||
+ if (x == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!(issuer = stapling_get_issuer(mctx, x))) {
|
||||
+ /* In Apache pre 2.4.40, we use to come here only when mod_ssl stapling
|
||||
+ * was enabled. With the new hooks, we give other modules the chance
|
||||
+ * to provide stapling status. However, we do not want to log ssl errors
|
||||
+ * where we did not do so in the past. */
|
||||
+ if (mctx->stapling_enabled == TRUE) {
|
||||
+ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
|
||||
+ "ssl_stapling_init_cert: can't retrieve issuer "
|
||||
+ "certificate!");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (ssl_run_init_stapling_status(s, p, x, issuer) == APR_SUCCESS) {
|
||||
+ /* Someone's taken over or mod_ssl's own implementation is not enabled */
|
||||
+ if (mctx->stapling_enabled != TRUE) {
|
||||
+ SSL_CTX_set_tlsext_status_cb(mctx->ssl_ctx, stapling_cb);
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO() "OCSP stapling added via hook");
|
||||
+ }
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (mctx->stapling_enabled != TRUE) {
|
||||
+ /* mod_ssl's own implementation is not enabled */
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
|
||||
return 0;
|
||||
|
||||
cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
|
||||
@@ -139,13 +186,6 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (!(issuer = stapling_get_issuer(mctx, x))) {
|
||||
- ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
|
||||
- "ssl_stapling_init_cert: can't retrieve issuer "
|
||||
- "certificate!");
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
cid = OCSP_cert_to_id(NULL, x, issuer);
|
||||
X509_free(issuer);
|
||||
if (!cid) {
|
||||
@@ -182,18 +222,16 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
mctx->sc->vhost_id);
|
||||
|
||||
apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf);
|
||||
-
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static certinfo *stapling_get_certinfo(server_rec *s, modssl_ctx_t *mctx,
|
||||
+static certinfo *stapling_get_certinfo(server_rec *s, X509 *x, modssl_ctx_t *mctx,
|
||||
SSL *ssl)
|
||||
{
|
||||
certinfo *cinf;
|
||||
- X509 *x;
|
||||
UCHAR idx[SHA_DIGEST_LENGTH];
|
||||
- x = SSL_get_certificate(ssl);
|
||||
- if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
|
||||
+ if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
|
||||
return NULL;
|
||||
cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
|
||||
if (cinf && cinf->cid)
|
||||
@@ -750,18 +788,34 @@ static int stapling_cb(SSL *ssl, void *arg)
|
||||
OCSP_RESPONSE *rsp = NULL;
|
||||
int rv;
|
||||
BOOL ok = TRUE;
|
||||
+ X509 *x;
|
||||
+ unsigned char *rspder = NULL;
|
||||
+ int rspderlen;
|
||||
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
|
||||
+ "stapling_cb: OCSP Stapling callback called");
|
||||
+
|
||||
+ x = SSL_get_certificate(ssl);
|
||||
+ if (x == NULL) {
|
||||
+ return SSL_TLSEXT_ERR_NOACK;
|
||||
+ }
|
||||
+
|
||||
+ if (ssl_run_get_stapling_status(&rspder, &rspderlen, conn, s, x) == APR_SUCCESS) {
|
||||
+ /* a hook handles stapling for this certicate and determines the response */
|
||||
+ if (rspder == NULL || rspderlen <= 0) {
|
||||
+ return SSL_TLSEXT_ERR_NOACK;
|
||||
+ }
|
||||
+ SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen);
|
||||
+ return SSL_TLSEXT_ERR_OK;
|
||||
+ }
|
||||
+
|
||||
if (sc->server->stapling_enabled != TRUE) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01950)
|
||||
"stapling_cb: OCSP Stapling disabled");
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
|
||||
- "stapling_cb: OCSP Stapling callback called");
|
||||
-
|
||||
- cinf = stapling_get_certinfo(s, mctx, ssl);
|
||||
- if (cinf == NULL) {
|
||||
+ if ((cinf = stapling_get_certinfo(s, x, mctx, ssl)) == NULL) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
@@ -864,9 +918,10 @@ apr_status_t modssl_init_stapling(server_rec *s, apr_pool_t *p,
|
||||
if (mctx->stapling_responder_timeout == UNSET) {
|
||||
mctx->stapling_responder_timeout = 10 * APR_USEC_PER_SEC;
|
||||
}
|
||||
+
|
||||
SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb);
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized");
|
||||
-
|
||||
+
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
44
httpd-2.4.37-mod-md-perms.patch
Normal file
44
httpd-2.4.37-mod-md-perms.patch
Normal file
@ -0,0 +1,44 @@
|
||||
diff --git a/modules/md/mod_md_os.c b/modules/md/mod_md_os.c
|
||||
index f96d566..8df0248 100644
|
||||
--- a/modules/md/mod_md_os.c
|
||||
+++ b/modules/md/mod_md_os.c
|
||||
@@ -41,14 +41,20 @@
|
||||
|
||||
apr_status_t md_try_chown(const char *fname, unsigned int uid, int gid, apr_pool_t *p)
|
||||
{
|
||||
-#if AP_NEED_SET_MUTEX_PERMS
|
||||
- if (-1 == chown(fname, (uid_t)uid, (gid_t)gid)) {
|
||||
- apr_status_t rv = APR_FROM_OS_ERROR(errno);
|
||||
- if (!APR_STATUS_IS_ENOENT(rv)) {
|
||||
- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, p, APLOGNO(10082)
|
||||
- "Can't change owner of %s", fname);
|
||||
+#if AP_NEED_SET_MUTEX_PERMS && HAVE_UNISTD_H
|
||||
+ /* Since we only switch user when running as root, we only need to chown directories
|
||||
+ * in that case. Otherwise, the server will ignore any "user/group" directives and
|
||||
+ * child processes have the same privileges as the parent.
|
||||
+ */
|
||||
+ if (!geteuid()) {
|
||||
+ if (-1 == chown(fname, (uid_t)uid, (gid_t)gid)) {
|
||||
+ apr_status_t rv = APR_FROM_OS_ERROR(errno);
|
||||
+ if (!APR_STATUS_IS_ENOENT(rv)) {
|
||||
+ ap_log_perror(APLOG_MARK, APLOG_ERR, rv, p, APLOGNO(10082)
|
||||
+ "Can't change owner of %s", fname);
|
||||
+ }
|
||||
+ return rv;
|
||||
}
|
||||
- return rv;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
#else
|
||||
@@ -58,11 +64,7 @@ apr_status_t md_try_chown(const char *fname, unsigned int uid, int gid, apr_pool
|
||||
|
||||
apr_status_t md_make_worker_accessible(const char *fname, apr_pool_t *p)
|
||||
{
|
||||
-#if AP_NEED_SET_MUTEX_PERMS
|
||||
return md_try_chown(fname, ap_unixd_config.user_id, -1, p);
|
||||
-#else
|
||||
- return APR_ENOTIMPL;
|
||||
-#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
24
httpd-2.4.37-mod-mime-magic-strdup.patch
Normal file
24
httpd-2.4.37-mod-mime-magic-strdup.patch
Normal file
@ -0,0 +1,24 @@
|
||||
diff --git a/docs/conf/magic b/docs/conf/magic
|
||||
index 7c56119..bc891d9 100644
|
||||
--- a/docs/conf/magic
|
||||
+++ b/docs/conf/magic
|
||||
@@ -87,7 +87,7 @@
|
||||
# Microsoft WAVE format (*.wav)
|
||||
# [GRR 950115: probably all of the shorts and longs should be leshort/lelong]
|
||||
# Microsoft RIFF
|
||||
-0 string RIFF audio/unknown
|
||||
+0 string RIFF
|
||||
# - WAVE format
|
||||
>8 string WAVE audio/x-wav
|
||||
# MPEG audio.
|
||||
--- a/modules/metadata/mod_mime_magic.c 2013/06/11 07:36:13 1491699
|
||||
+++ b/modules/metadata/mod_mime_magic.c 2013/06/11 07:41:40 1491700
|
||||
@@ -606,7 +606,7 @@
|
||||
/* high overhead for 1 char - just hope they don't do this much */
|
||||
str[0] = c;
|
||||
str[1] = '\0';
|
||||
- return magic_rsl_add(r, str);
|
||||
+ return magic_rsl_add(r, apr_pstrdup(r->pool, str));
|
||||
}
|
||||
|
||||
/* allocate and copy a contiguous string from a result string list */
|
143
httpd-2.4.37-pr37355.patch
Normal file
143
httpd-2.4.37-pr37355.patch
Normal file
@ -0,0 +1,143 @@
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index d13c249..f383996 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -1200,11 +1200,20 @@ static int proxy_handler(request_rec *r)
|
||||
/* handle the scheme */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01142)
|
||||
"Trying to run scheme_handler against proxy");
|
||||
+
|
||||
+ if (ents[i].creds) {
|
||||
+ apr_table_set(r->notes, "proxy-basic-creds", ents[i].creds);
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||
+ "Using proxy auth creds %s", ents[i].creds);
|
||||
+ }
|
||||
+
|
||||
access_status = proxy_run_scheme_handler(r, worker,
|
||||
conf, url,
|
||||
ents[i].hostname,
|
||||
ents[i].port);
|
||||
|
||||
+ if (ents[i].creds) apr_table_unset(r->notes, "proxy-basic-creds");
|
||||
+
|
||||
/* Did the scheme handler process the request? */
|
||||
if (access_status != DECLINED) {
|
||||
const char *cl_a;
|
||||
@@ -1621,8 +1630,8 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
|
||||
return new;
|
||||
}
|
||||
|
||||
-static const char *
|
||||
- add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, int regex)
|
||||
+static const char *add_proxy(cmd_parms *cmd, void *dummy, const char *f1,
|
||||
+ const char *r1, const char *creds, int regex)
|
||||
{
|
||||
server_rec *s = cmd->server;
|
||||
proxy_server_conf *conf =
|
||||
@@ -1680,19 +1689,24 @@ static const char *
|
||||
new->port = port;
|
||||
new->regexp = reg;
|
||||
new->use_regex = regex;
|
||||
+ if (creds) {
|
||||
+ new->creds = apr_pstrcat(cmd->pool, "Basic ",
|
||||
+ ap_pbase64encode(cmd->pool, (char *)creds),
|
||||
+ NULL);
|
||||
+ }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static const char *
|
||||
- add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1)
|
||||
+static const char *add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1,
|
||||
+ const char *r1, const char *creds)
|
||||
{
|
||||
- return add_proxy(cmd, dummy, f1, r1, 0);
|
||||
+ return add_proxy(cmd, dummy, f1, r1, creds, 0);
|
||||
}
|
||||
|
||||
-static const char *
|
||||
- add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1)
|
||||
+static const char *add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1,
|
||||
+ const char *r1, const char *creds)
|
||||
{
|
||||
- return add_proxy(cmd, dummy, f1, r1, 1);
|
||||
+ return add_proxy(cmd, dummy, f1, r1, creds, 1);
|
||||
}
|
||||
|
||||
PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url)
|
||||
@@ -2638,9 +2652,9 @@ static const command_rec proxy_cmds[] =
|
||||
"location, in regular expression syntax"),
|
||||
AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF,
|
||||
"on if the true proxy requests should be accepted"),
|
||||
- AP_INIT_TAKE2("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,
|
||||
+ AP_INIT_TAKE23("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,
|
||||
"a scheme, partial URL or '*' and a proxy server"),
|
||||
- AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
|
||||
+ AP_INIT_TAKE23("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
|
||||
"a regex pattern and a proxy server"),
|
||||
AP_INIT_FLAG("ProxyPassInterpolateEnv", ap_set_flag_slot_char,
|
||||
(void*)APR_OFFSETOF(proxy_dir_conf, interpolate_env),
|
||||
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
|
||||
index 288c5d4..57cc92f 100644
|
||||
--- a/modules/proxy/mod_proxy.h
|
||||
+++ b/modules/proxy/mod_proxy.h
|
||||
@@ -116,6 +116,7 @@ struct proxy_remote {
|
||||
const char *protocol; /* the scheme used to talk to this proxy */
|
||||
const char *hostname; /* the hostname of this proxy */
|
||||
ap_regex_t *regexp; /* compiled regex (if any) for the remote */
|
||||
+ const char *creds; /* auth credentials (if any) for the proxy */
|
||||
int use_regex; /* simple boolean. True if we have a regex pattern */
|
||||
apr_port_t port; /* the port for this proxy */
|
||||
};
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 0759dac..2bfc8f0 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -2446,11 +2446,14 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
|
||||
* So let's make it configurable by env.
|
||||
* The logic here is the same used in mod_proxy_http.
|
||||
*/
|
||||
- proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
|
||||
+ proxy_auth = apr_table_get(r->notes, "proxy-basic-creds");
|
||||
+ if (proxy_auth == NULL)
|
||||
+ proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
|
||||
+
|
||||
if (proxy_auth != NULL &&
|
||||
proxy_auth[0] != '\0' &&
|
||||
- r->user == NULL && /* we haven't yet authenticated */
|
||||
- apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
|
||||
+ (r->user == NULL /* we haven't yet authenticated */
|
||||
+ || apr_table_get(r->subprocess_env, "Proxy-Chain-Auth"))) {
|
||||
forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth);
|
||||
}
|
||||
}
|
||||
@@ -2672,7 +2675,8 @@ static apr_status_t send_http_connect(proxy_conn_rec *backend,
|
||||
nbytes = apr_snprintf(buffer, sizeof(buffer),
|
||||
"CONNECT %s:%d HTTP/1.0" CRLF,
|
||||
forward->target_host, forward->target_port);
|
||||
- /* Add proxy authorization from the initial request if necessary */
|
||||
+ /* Add proxy authorization from the configuration, or initial
|
||||
+ * request if necessary */
|
||||
if (forward->proxy_auth != NULL) {
|
||||
nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes,
|
||||
"Proxy-Authorization: %s" CRLF,
|
||||
@@ -3567,6 +3571,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
|
||||
apr_bucket *e;
|
||||
int do_100_continue;
|
||||
conn_rec *origin = p_conn->connection;
|
||||
+ const char *creds;
|
||||
proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
|
||||
|
||||
/*
|
||||
@@ -3743,6 +3748,11 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
+ creds = apr_table_get(r->notes, "proxy-basic-creds");
|
||||
+ if (creds) {
|
||||
+ apr_table_mergen(r->headers_in, "Proxy-Authorization", creds);
|
||||
+ }
|
||||
+
|
||||
/* send request headers */
|
||||
headers_in_array = apr_table_elts(r->headers_in);
|
||||
headers_in = (const apr_table_entry_t *) headers_in_array->elts;
|
1713
httpd-2.4.37-proxy-continue.patch
Normal file
1713
httpd-2.4.37-proxy-continue.patch
Normal file
File diff suppressed because it is too large
Load Diff
132
httpd-2.4.37-proxy-ws-idle-timeout.patch
Normal file
132
httpd-2.4.37-proxy-ws-idle-timeout.patch
Normal file
@ -0,0 +1,132 @@
|
||||
diff --git a/docs/manual/mod/mod_proxy_wstunnel.html.en b/docs/manual/mod/mod_proxy_wstunnel.html.en
|
||||
index 21ffbe2..16e1628 100644
|
||||
--- a/docs/manual/mod/mod_proxy_wstunnel.html.en
|
||||
+++ b/docs/manual/mod/mod_proxy_wstunnel.html.en
|
||||
@@ -60,14 +60,33 @@ NONE means you bypass the check for the header but still upgrade to WebSocket.
|
||||
ANY means that <code>Upgrade</code> will read in the request headers and use
|
||||
in the response <code>Upgrade</code></p>
|
||||
</div>
|
||||
-<div id="quickview"><a href="https://www.apache.org/foundation/contributing.html" class="badge"><img src="https://www.apache.org/images/SupportApache-small.png" alt="Support Apache!" /></a><h3 class="directives">Directives</h3>
|
||||
-<p>This module provides no
|
||||
- directives.</p>
|
||||
+<div id="quickview"><h3 class="directives">Directives</h3>
|
||||
+<ul id="toc">
|
||||
+<li><img alt="" src="../images/down.gif" /> <a href="#proxywebsocketidletimeout">ProxyWebsocketIdleTimeout</a></li>
|
||||
+</ul>
|
||||
+
|
||||
<h3>Bugfix checklist</h3><ul class="seealso"><li><a href="https://www.apache.org/dist/httpd/CHANGES_2.4">httpd changelog</a></li><li><a href="https://bz.apache.org/bugzilla/buglist.cgi?bug_status=__open__&list_id=144532&product=Apache%20httpd-2&query_format=specific&order=changeddate%20DESC%2Cpriority%2Cbug_severity&component=mod_proxy_wstunnel">Known issues</a></li><li><a href="https://bz.apache.org/bugzilla/enter_bug.cgi?product=Apache%20httpd-2&component=mod_proxy_wstunnel">Report a bug</a></li></ul><h3>See also</h3>
|
||||
<ul class="seealso">
|
||||
<li><code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code></li>
|
||||
<li><a href="#comments_section">Comments</a></li></ul></div>
|
||||
|
||||
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
+<div class="directive-section"><h2><a name="ProxyWebsocketIdleTimeout" id="ProxyWebsocketIdleTimeout">ProxyWebsocketIdleTimeout</a> <a name="proxywebsocketidletimeout" id="proxywebsocketidletimeout">Directive</a> <a title="Permanent link" href="#proxywebsocketidletimeout" class="permalink">¶</a></h2>
|
||||
+<table class="directive">
|
||||
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Sets the maximum amount of time to wait for data on the websockets tunnel</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>ProxyWebsocketIdleTimeout <var>num</var>[ms]</code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>ProxyWebsocketIdleTimeout 0</code></td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Extension</td></tr>
|
||||
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_proxy_wstunnel</td></tr>
|
||||
+</table>
|
||||
+ <p>This directive imposes a maximum amount of time for the tunnel to be
|
||||
+ left open while idle. The timeout is considered in seconds by default, but
|
||||
+ it is possible to increase the time resolution to milliseconds
|
||||
+ adding the <em>ms</em> suffix.</p>
|
||||
+
|
||||
+</div>
|
||||
+
|
||||
</div>
|
||||
<div class="bottomlang">
|
||||
<p><span>Available Languages: </span><a href="../en/mod/mod_proxy_wstunnel.html" title="English"> en </a> |
|
||||
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
|
||||
index 4aadbab..ca3ed3a 100644
|
||||
--- a/modules/proxy/mod_proxy_wstunnel.c
|
||||
+++ b/modules/proxy/mod_proxy_wstunnel.c
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
module AP_MODULE_DECLARE_DATA proxy_wstunnel_module;
|
||||
|
||||
+typedef struct {
|
||||
+ apr_time_t idle_timeout;
|
||||
+} proxyws_dir_conf;
|
||||
+
|
||||
/*
|
||||
* Canonicalise http-like URLs.
|
||||
* scheme is the scheme for the URL
|
||||
@@ -108,6 +112,8 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
|
||||
conn_rec *c = r->connection;
|
||||
apr_socket_t *sock = conn->sock;
|
||||
conn_rec *backconn = conn->connection;
|
||||
+ proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
|
||||
+ &proxy_wstunnel_module);
|
||||
char *buf;
|
||||
apr_bucket_brigade *header_brigade;
|
||||
apr_bucket *e;
|
||||
@@ -185,10 +191,13 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
|
||||
c->keepalive = AP_CONN_CLOSE;
|
||||
|
||||
do { /* Loop until done (one side closes the connection, or an error) */
|
||||
- rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled);
|
||||
+ rv = apr_pollset_poll(pollset, dconf->idle_timeout, &pollcnt, &signalled);
|
||||
if (rv != APR_SUCCESS) {
|
||||
if (APR_STATUS_IS_EINTR(rv)) {
|
||||
continue;
|
||||
+ } else if(APR_STATUS_IS_TIMEUP(rv)){
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "RH: the connection has timed out");
|
||||
+ return HTTP_REQUEST_TIME_OUT;
|
||||
}
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02444) "error apr_poll()");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
@@ -366,6 +375,38 @@ cleanup:
|
||||
return status;
|
||||
}
|
||||
|
||||
+static const char * proxyws_set_idle(cmd_parms *cmd, void *conf, const char *val)
|
||||
+{
|
||||
+ proxyws_dir_conf *dconf = conf;
|
||||
+ if (ap_timeout_parameter_parse(val, &(dconf->idle_timeout), "s") != APR_SUCCESS)
|
||||
+ return "ProxyWebsocketIdleTimeout timeout has wrong format";
|
||||
+
|
||||
+ if (dconf->idle_timeout < 0)
|
||||
+ return "ProxyWebsocketIdleTimeout timeout has to be a non-negative number";
|
||||
+
|
||||
+ if (!dconf->idle_timeout) dconf->idle_timeout = -1; /* loop indefinitely */
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy)
|
||||
+{
|
||||
+ proxyws_dir_conf *new =
|
||||
+ (proxyws_dir_conf *) apr_pcalloc(p, sizeof(proxyws_dir_conf));
|
||||
+
|
||||
+ new->idle_timeout = -1; /* no timeout */
|
||||
+
|
||||
+ return (void *) new;
|
||||
+}
|
||||
+
|
||||
+static const command_rec ws_proxy_cmds[] =
|
||||
+{
|
||||
+ AP_INIT_TAKE1("ProxyWebsocketIdleTimeout", proxyws_set_idle, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
+ "timeout for activity in either direction, unlimited by default."),
|
||||
+
|
||||
+ {NULL}
|
||||
+};
|
||||
+
|
||||
static void ap_proxy_http_register_hook(apr_pool_t *p)
|
||||
{
|
||||
proxy_hook_scheme_handler(proxy_wstunnel_handler, NULL, NULL, APR_HOOK_FIRST);
|
||||
@@ -374,10 +415,10 @@ static void ap_proxy_http_register_hook(apr_pool_t *p)
|
||||
|
||||
AP_DECLARE_MODULE(proxy_wstunnel) = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
- NULL, /* create per-directory config structure */
|
||||
+ create_proxyws_dir_config, /* create per-directory config structure */
|
||||
NULL, /* merge per-directory config structures */
|
||||
NULL, /* create per-server config structure */
|
||||
NULL, /* merge per-server config structures */
|
||||
- NULL, /* command apr_table_t */
|
||||
+ ws_proxy_cmds, /* command apr_table_t */
|
||||
ap_proxy_http_register_hook /* register hooks */
|
||||
};
|
1420
httpd-2.4.37-r1828172+.patch
Normal file
1420
httpd-2.4.37-r1828172+.patch
Normal file
File diff suppressed because it is too large
Load Diff
35
httpd-2.4.37-r1840554.patch
Normal file
35
httpd-2.4.37-r1840554.patch
Normal file
@ -0,0 +1,35 @@
|
||||
diff --git a/modules/arch/unix/mod_systemd.c b/modules/arch/unix/mod_systemd.c
|
||||
index 7a82a90..6c244b6 100644
|
||||
--- a/modules/arch/unix/mod_systemd.c
|
||||
+++ b/modules/arch/unix/mod_systemd.c
|
||||
@@ -100,6 +100,21 @@ static int systemd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
return OK;
|
||||
}
|
||||
|
||||
+/* Report the service is ready in post_config, which could be during
|
||||
+ * startup or after a reload. The server could still hit a fatal
|
||||
+ * startup error after this point during ap_run_mpm(), so this is
|
||||
+ * perhaps too early, but by post_config listen() has been called on
|
||||
+ * the TCP ports so new connections will not be rejected. There will
|
||||
+ * always be a possible async failure event simultaneous to the
|
||||
+ * service reporting "ready", so this should be good enough. */
|
||||
+static int systemd_post_config_last(apr_pool_t *p, apr_pool_t *plog,
|
||||
+ apr_pool_t *ptemp, server_rec *main_server)
|
||||
+{
|
||||
+ sd_notify(0, "READY=1\n"
|
||||
+ "STATUS=Configuration loaded.\n");
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
static int systemd_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
|
||||
{
|
||||
int rv;
|
||||
@@ -187,6 +202,8 @@ static void systemd_register_hooks(apr_pool_t *p)
|
||||
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);
|
||||
+ /* Signal service is ready. */
|
||||
+ ap_hook_post_config(systemd_post_config_last, NULL, NULL, APR_HOOK_REALLY_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 */
|
272
httpd-2.4.37-r1842929+.patch
Normal file
272
httpd-2.4.37-r1842929+.patch
Normal file
@ -0,0 +1,272 @@
|
||||
# ./pullrev.sh 1842929 1842931 1852982 1853631 1857731
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1842929
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1842931
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1852982
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1857731
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1853631
|
||||
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 06b8c5a..9eeb5c7 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -213,6 +213,7 @@ install-cgi:
|
||||
install-other:
|
||||
@test -d $(DESTDIR)$(logfiledir) || $(MKINSTALLDIRS) $(DESTDIR)$(logfiledir)
|
||||
@test -d $(DESTDIR)$(runtimedir) || $(MKINSTALLDIRS) $(DESTDIR)$(runtimedir)
|
||||
+ @test -d $(DESTDIR)$(statedir) || $(MKINSTALLDIRS) $(DESTDIR)$(statedir)
|
||||
@for ext in dll x; do \
|
||||
file=apachecore.$$ext; \
|
||||
if test -f $$file; then \
|
||||
diff --git a/acinclude.m4 b/acinclude.m4
|
||||
index 0ad0c13..a8c2804 100644
|
||||
--- a/acinclude.m4
|
||||
+++ b/acinclude.m4
|
||||
@@ -45,6 +45,7 @@ AC_DEFUN([APACHE_GEN_CONFIG_VARS],[
|
||||
APACHE_SUBST(installbuilddir)
|
||||
APACHE_SUBST(runtimedir)
|
||||
APACHE_SUBST(proxycachedir)
|
||||
+ APACHE_SUBST(statedir)
|
||||
APACHE_SUBST(other_targets)
|
||||
APACHE_SUBST(progname)
|
||||
APACHE_SUBST(prefix)
|
||||
@@ -663,6 +664,7 @@ AC_DEFUN([APACHE_EXPORT_ARGUMENTS],[
|
||||
APACHE_SUBST_EXPANDED_ARG(runtimedir)
|
||||
APACHE_SUBST_EXPANDED_ARG(logfiledir)
|
||||
APACHE_SUBST_EXPANDED_ARG(proxycachedir)
|
||||
+ APACHE_SUBST_EXPANDED_ARG(statedir)
|
||||
])
|
||||
|
||||
dnl
|
||||
diff --git a/configure.in b/configure.in
|
||||
index a208b53..de6a8ad 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -41,7 +41,7 @@ dnl Something seems broken here.
|
||||
AC_PREFIX_DEFAULT(/usr/local/apache2)
|
||||
|
||||
dnl Get the layout here, so we can pass the required variables to apr
|
||||
-APR_ENABLE_LAYOUT(Apache, [errordir iconsdir htdocsdir cgidir])
|
||||
+APR_ENABLE_LAYOUT(Apache, [errordir iconsdir htdocsdir cgidir statedir])
|
||||
|
||||
dnl reparse the configure arguments.
|
||||
APR_PARSE_ARGUMENTS
|
||||
diff --git a/include/ap_config_layout.h.in b/include/ap_config_layout.h.in
|
||||
index 2b4a70c..e076f41 100644
|
||||
--- a/include/ap_config_layout.h.in
|
||||
+++ b/include/ap_config_layout.h.in
|
||||
@@ -60,5 +60,7 @@
|
||||
#define DEFAULT_REL_LOGFILEDIR "@rel_logfiledir@"
|
||||
#define DEFAULT_EXP_PROXYCACHEDIR "@exp_proxycachedir@"
|
||||
#define DEFAULT_REL_PROXYCACHEDIR "@rel_proxycachedir@"
|
||||
+#define DEFAULT_EXP_STATEDIR "@exp_statedir@"
|
||||
+#define DEFAULT_REL_STATEDIR "@rel_statedir@"
|
||||
|
||||
#endif /* AP_CONFIG_LAYOUT_H */
|
||||
diff --git a/include/http_config.h b/include/http_config.h
|
||||
index adc5825..effccc1 100644
|
||||
--- a/include/http_config.h
|
||||
+++ b/include/http_config.h
|
||||
@@ -757,6 +757,14 @@ AP_DECLARE(char *) ap_server_root_relative(apr_pool_t *p, const char *fname);
|
||||
*/
|
||||
AP_DECLARE(char *) ap_runtime_dir_relative(apr_pool_t *p, const char *fname);
|
||||
|
||||
+/**
|
||||
+ * Compute the name of a persistent state file (e.g. a database or
|
||||
+ * long-lived cache) relative to the appropriate state directory.
|
||||
+ * Absolute paths are returned as-is. The state directory is
|
||||
+ * configured via the DefaultStateDir directive or at build time.
|
||||
+ */
|
||||
+AP_DECLARE(char *) ap_state_dir_relative(apr_pool_t *p, const char *fname);
|
||||
+
|
||||
/* Finally, the hook for dynamically loading modules in... */
|
||||
|
||||
/**
|
||||
diff --git a/modules/dav/fs/mod_dav_fs.c b/modules/dav/fs/mod_dav_fs.c
|
||||
index addfd7e..2389f8f 100644
|
||||
--- a/modules/dav/fs/mod_dav_fs.c
|
||||
+++ b/modules/dav/fs/mod_dav_fs.c
|
||||
@@ -29,6 +29,10 @@ typedef struct {
|
||||
|
||||
extern module AP_MODULE_DECLARE_DATA dav_fs_module;
|
||||
|
||||
+#ifndef DEFAULT_DAV_LOCKDB
|
||||
+#define DEFAULT_DAV_LOCKDB "davlockdb"
|
||||
+#endif
|
||||
+
|
||||
const char *dav_get_lockdb_path(const request_rec *r)
|
||||
{
|
||||
dav_fs_server_conf *conf;
|
||||
@@ -57,6 +61,24 @@ static void *dav_fs_merge_server_config(apr_pool_t *p,
|
||||
return newconf;
|
||||
}
|
||||
|
||||
+static apr_status_t dav_fs_post_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
+ apr_pool_t *ptemp, server_rec *base_server)
|
||||
+{
|
||||
+ server_rec *s;
|
||||
+
|
||||
+ for (s = base_server; s; s = s->next) {
|
||||
+ dav_fs_server_conf *conf;
|
||||
+
|
||||
+ conf = ap_get_module_config(s->module_config, &dav_fs_module);
|
||||
+
|
||||
+ if (!conf->lockdb_path) {
|
||||
+ conf->lockdb_path = ap_state_dir_relative(p, DEFAULT_DAV_LOCKDB);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Command handler for the DAVLockDB directive, which is TAKE1
|
||||
*/
|
||||
@@ -87,6 +109,8 @@ static const command_rec dav_fs_cmds[] =
|
||||
|
||||
static void register_hooks(apr_pool_t *p)
|
||||
{
|
||||
+ ap_hook_post_config(dav_fs_post_config, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
+
|
||||
dav_hook_gather_propsets(dav_fs_gather_propsets, NULL, NULL,
|
||||
APR_HOOK_MIDDLE);
|
||||
dav_hook_find_liveprop(dav_fs_find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
diff --git a/modules/md/mod_md_config.c b/modules/md/mod_md_config.c
|
||||
index 336a21b..4d50e26 100644
|
||||
--- a/modules/md/mod_md_config.c
|
||||
+++ b/modules/md/mod_md_config.c
|
||||
@@ -54,10 +54,18 @@
|
||||
|
||||
#define DEF_VAL (-1)
|
||||
|
||||
+#ifndef MD_DEFAULT_BASE_DIR
|
||||
+#define MD_DEFAULT_BASE_DIR "md"
|
||||
+#endif
|
||||
+
|
||||
/* Default settings for the global conf */
|
||||
static md_mod_conf_t defmc = {
|
||||
NULL,
|
||||
- "md",
|
||||
+#if 1
|
||||
+ NULL, /* apply default state-dir-relative */
|
||||
+#else
|
||||
+ MD_DEFAULT_BASE_DIR,
|
||||
+#endif
|
||||
NULL,
|
||||
NULL,
|
||||
80,
|
||||
@@ -864,6 +872,12 @@ apr_status_t md_config_post_config(server_rec *s, apr_pool_t *p)
|
||||
if (mc->hsts_max_age > 0) {
|
||||
mc->hsts_header = apr_psprintf(p, "max-age=%d", mc->hsts_max_age);
|
||||
}
|
||||
+
|
||||
+#if 1
|
||||
+ if (mc->base_dir == NULL) {
|
||||
+ mc->base_dir = ap_state_dir_relative(p, MD_DEFAULT_BASE_DIR);
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index bbe52e0..b5ab429 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -133,6 +133,8 @@ AP_DECLARE_DATA int ap_main_state = AP_SQ_MS_INITIAL_STARTUP;
|
||||
AP_DECLARE_DATA int ap_run_mode = AP_SQ_RM_UNKNOWN;
|
||||
AP_DECLARE_DATA int ap_config_generation = 0;
|
||||
|
||||
+static const char *core_state_dir;
|
||||
+
|
||||
static void *create_core_dir_config(apr_pool_t *a, char *dir)
|
||||
{
|
||||
core_dir_config *conf;
|
||||
@@ -1411,12 +1413,15 @@ AP_DECLARE(const char *) ap_resolve_env(apr_pool_t *p, const char * word)
|
||||
return res_buf;
|
||||
}
|
||||
|
||||
-static int reset_config_defines(void *dummy)
|
||||
+/* pconf cleanup - clear global variables set from config here. */
|
||||
+static apr_status_t reset_config(void *dummy)
|
||||
{
|
||||
ap_server_config_defines = saved_server_config_defines;
|
||||
saved_server_config_defines = NULL;
|
||||
server_config_defined_vars = NULL;
|
||||
- return OK;
|
||||
+ core_state_dir = NULL;
|
||||
+
|
||||
+ return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3108,6 +3113,24 @@ static const char *set_runtime_dir(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static const char *set_state_dir(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
+{
|
||||
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
||||
+
|
||||
+ if (err != NULL) {
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if ((apr_filepath_merge((char**)&core_state_dir, NULL,
|
||||
+ ap_server_root_relative(cmd->temp_pool, arg),
|
||||
+ APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS)
|
||||
+ || !ap_is_directory(cmd->temp_pool, core_state_dir)) {
|
||||
+ return "DefaultStateDir must be a valid directory, absolute or relative to ServerRoot";
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
{
|
||||
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT);
|
||||
@@ -4409,6 +4432,8 @@ AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF | EXEC_ON_READ,
|
||||
"Common directory of server-related files (logs, confs, etc.)"),
|
||||
AP_INIT_TAKE1("DefaultRuntimeDir", set_runtime_dir, NULL, RSRC_CONF | EXEC_ON_READ,
|
||||
"Common directory for run-time files (shared memory, locks, etc.)"),
|
||||
+AP_INIT_TAKE1("DefaultStateDir", set_state_dir, NULL, RSRC_CONF | EXEC_ON_READ,
|
||||
+ "Common directory for persistent state (databases, long-lived caches, etc.)"),
|
||||
AP_INIT_TAKE1("ErrorLog", set_server_string_slot,
|
||||
(void *)APR_OFFSETOF(server_rec, error_fname), RSRC_CONF,
|
||||
"The filename of the error log"),
|
||||
@@ -4932,8 +4957,7 @@ static int core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptem
|
||||
|
||||
if (!saved_server_config_defines)
|
||||
init_config_defines(pconf);
|
||||
- apr_pool_cleanup_register(pconf, NULL, reset_config_defines,
|
||||
- apr_pool_cleanup_null);
|
||||
+ apr_pool_cleanup_register(pconf, NULL, reset_config, apr_pool_cleanup_null);
|
||||
|
||||
ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY);
|
||||
|
||||
@@ -5202,6 +5226,27 @@ AP_DECLARE(int) ap_state_query(int query)
|
||||
}
|
||||
}
|
||||
|
||||
+AP_DECLARE(char *) ap_state_dir_relative(apr_pool_t *p, const char *file)
|
||||
+{
|
||||
+ char *newpath = NULL;
|
||||
+ apr_status_t rv;
|
||||
+ const char *state_dir;
|
||||
+
|
||||
+ state_dir = core_state_dir
|
||||
+ ? core_state_dir
|
||||
+ : ap_server_root_relative(p, DEFAULT_REL_STATEDIR);
|
||||
+
|
||||
+ rv = apr_filepath_merge(&newpath, state_dir, file, APR_FILEPATH_TRUENAME, p);
|
||||
+ if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv)
|
||||
+ || APR_STATUS_IS_ENOENT(rv)
|
||||
+ || APR_STATUS_IS_ENOTDIR(rv))) {
|
||||
+ return newpath;
|
||||
+ }
|
||||
+ else {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static apr_random_t *rng = NULL;
|
||||
#if APR_HAS_THREADS
|
||||
static apr_thread_mutex_t *rng_mutex = NULL;
|
48
httpd-2.4.37-r1845768+.patch
Normal file
48
httpd-2.4.37-r1845768+.patch
Normal file
@ -0,0 +1,48 @@
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index 70d151e..e4f5fc8 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -1095,7 +1095,9 @@ static apr_status_t ssl_init_ctx_crl(server_rec *s,
|
||||
/*
|
||||
* Read a file that optionally contains the server certificate in PEM
|
||||
* format, possibly followed by a sequence of CA certificates that
|
||||
- * should be sent to the peer in the SSL Certificate message.
|
||||
+ * should be sent to the peer in the SSL Certificate message. Returns
|
||||
+ * 0 on success, otherwise the OpenSSL error stack contents should be
|
||||
+ * reported.
|
||||
*/
|
||||
static int use_certificate_chain(
|
||||
SSL_CTX *ctx, char *file, int skipfirst, pem_password_cb *cb)
|
||||
@@ -1128,8 +1130,10 @@ static int use_certificate_chain(
|
||||
ctx->extra_certs = NULL;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
/* create new extra chain by loading the certs */
|
||||
n = 0;
|
||||
+ ERR_clear_error();
|
||||
while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
|
||||
if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
|
||||
X509_free(x509);
|
||||
@@ -1190,6 +1194,7 @@ static apr_status_t ssl_init_ctx_cert_chain(server_rec *s,
|
||||
if (n < 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01903)
|
||||
"Failed to configure CA certificate chain!");
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
return ssl_die(s);
|
||||
}
|
||||
|
||||
diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c
|
||||
index b11a6e9..b66e151 100644
|
||||
--- a/modules/ssl/ssl_util_ocsp.c
|
||||
+++ b/modules/ssl/ssl_util_ocsp.c
|
||||
@@ -363,7 +363,9 @@ static STACK_OF(X509) *modssl_read_ocsp_certificates(const char *file)
|
||||
BIO_free(bio);
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
/* create new extra chain by loading the certs */
|
||||
+ ERR_clear_error();
|
||||
while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
|
||||
if (!other_certs) {
|
||||
other_certs = sk_X509_new_null();
|
44
httpd-2.4.37-r1851471.patch
Normal file
44
httpd-2.4.37-r1851471.patch
Normal file
@ -0,0 +1,44 @@
|
||||
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
|
||||
index 0958135..018b667 100644
|
||||
--- a/modules/ssl/ssl_engine_io.c
|
||||
+++ b/modules/ssl/ssl_engine_io.c
|
||||
@@ -200,6 +200,8 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
|
||||
apr_bucket *e;
|
||||
int need_flush;
|
||||
|
||||
+ BIO_clear_retry_flags(bio);
|
||||
+
|
||||
#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
@@ -208,12 +210,6 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
|
||||
}
|
||||
#endif
|
||||
|
||||
- /* when handshaking we'll have a small number of bytes.
|
||||
- * max size SSL will pass us here is about 16k.
|
||||
- * (16413 bytes to be exact)
|
||||
- */
|
||||
- BIO_clear_retry_flags(bio);
|
||||
-
|
||||
/* Use a transient bucket for the output data - any downstream
|
||||
* filter must setaside if necessary. */
|
||||
e = apr_bucket_transient_create(in, inl, outctx->bb->bucket_alloc);
|
||||
@@ -460,6 +456,8 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
+ BIO_clear_retry_flags(bio);
|
||||
+
|
||||
#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
@@ -468,8 +466,6 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
|
||||
}
|
||||
#endif
|
||||
|
||||
- BIO_clear_retry_flags(bio);
|
||||
-
|
||||
if (!inctx->bb) {
|
||||
inctx->rc = APR_EOF;
|
||||
return -1;
|
209
httpd-2.4.37-r1861793+.patch
Normal file
209
httpd-2.4.37-r1861793+.patch
Normal file
@ -0,0 +1,209 @@
|
||||
diff --git a/configure.in b/configure.in
|
||||
index de6a8ad..4ca489d 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -465,6 +465,28 @@ LIBS=""
|
||||
AC_SEARCH_LIBS(crypt, crypt)
|
||||
CRYPT_LIBS="$LIBS"
|
||||
APACHE_SUBST(CRYPT_LIBS)
|
||||
+
|
||||
+if test "$ac_cv_search_crypt" != "no"; then
|
||||
+ # Test crypt() with the SHA-512 test vector from https://akkadia.org/drepper/SHA-crypt.txt
|
||||
+ AC_CACHE_CHECK([whether crypt() supports SHA-2], [ap_cv_crypt_sha2], [
|
||||
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
+#include <crypt.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#define PASSWD_0 "Hello world!"
|
||||
+#define SALT_0 "\$6\$saltstring"
|
||||
+#define EXPECT_0 "\$6\$saltstring\$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu" \
|
||||
+ "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1"
|
||||
+]], [char *result = crypt(PASSWD_0, SALT_0);
|
||||
+ if (!result) return 1;
|
||||
+ if (strcmp(result, EXPECT_0)) return 2;
|
||||
+])], [ap_cv_crypt_sha2=yes], [ap_cv_crypt_sha2=no])])
|
||||
+ if test "$ap_cv_crypt_sha2" = yes; then
|
||||
+ AC_DEFINE([HAVE_CRYPT_SHA2], 1, [Define if crypt() supports SHA-2 hashes])
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
dnl See Comment #Spoon
|
||||
diff --git a/support/htpasswd.c b/support/htpasswd.c
|
||||
index 660a27c..136f62a 100644
|
||||
--- a/support/htpasswd.c
|
||||
+++ b/support/htpasswd.c
|
||||
@@ -98,28 +98,32 @@ static int mkrecord(struct passwd_ctx *ctx, char *user)
|
||||
static void usage(void)
|
||||
{
|
||||
apr_file_printf(errfile, "Usage:" NL
|
||||
- "\thtpasswd [-cimBdpsDv] [-C cost] passwordfile username" NL
|
||||
- "\thtpasswd -b[cmBdpsDv] [-C cost] passwordfile username password" NL
|
||||
+ "\thtpasswd [-cimB25dpsDv] [-C cost] [-r rounds] passwordfile username" NL
|
||||
+ "\thtpasswd -b[cmB25dpsDv] [-C cost] [-r rounds] passwordfile username password" NL
|
||||
NL
|
||||
- "\thtpasswd -n[imBdps] [-C cost] username" NL
|
||||
- "\thtpasswd -nb[mBdps] [-C cost] username password" NL
|
||||
+ "\thtpasswd -n[imB25dps] [-C cost] [-r rounds] username" NL
|
||||
+ "\thtpasswd -nb[mB25dps] [-C cost] [-r rounds] username password" NL
|
||||
" -c Create a new file." NL
|
||||
" -n Don't update file; display results on stdout." NL
|
||||
" -b Use the password from the command line rather than prompting "
|
||||
"for it." NL
|
||||
" -i Read password from stdin without verification (for script usage)." NL
|
||||
" -m Force MD5 encryption of the password (default)." NL
|
||||
- " -B Force bcrypt encryption of the password (very secure)." NL
|
||||
+ " -2 Force SHA-256 crypt() hash of the password (secure)." NL
|
||||
+ " -5 Force SHA-512 crypt() hash of the password (secure)." NL
|
||||
+ " -B Force bcrypt encryption of the password (very secure)." NL
|
||||
" -C Set the computing time used for the bcrypt algorithm" NL
|
||||
" (higher is more secure but slower, default: %d, valid: 4 to 31)." NL
|
||||
+ " -r Set the number of rounds used for the SHA-256, SHA-512 algorithms" NL
|
||||
+ " (higher is more secure but slower, default: 5000)." NL
|
||||
" -d Force CRYPT encryption of the password (8 chars max, insecure)." NL
|
||||
- " -s Force SHA encryption of the password (insecure)." NL
|
||||
+ " -s Force SHA-1 encryption of the password (insecure)." NL
|
||||
" -p Do not encrypt the password (plaintext, insecure)." NL
|
||||
" -D Delete the specified user." NL
|
||||
" -v Verify password for the specified user." NL
|
||||
"On other systems than Windows and NetWare the '-p' flag will "
|
||||
"probably not work." NL
|
||||
- "The SHA algorithm does not use a salt and is less secure than the "
|
||||
+ "The SHA-1 algorithm does not use a salt and is less secure than the "
|
||||
"MD5 algorithm." NL,
|
||||
BCRYPT_DEFAULT_COST
|
||||
);
|
||||
@@ -178,7 +182,7 @@ static void check_args(int argc, const char *const argv[],
|
||||
if (rv != APR_SUCCESS)
|
||||
exit(ERR_SYNTAX);
|
||||
|
||||
- while ((rv = apr_getopt(state, "cnmspdBbDiC:v", &opt, &opt_arg)) == APR_SUCCESS) {
|
||||
+ while ((rv = apr_getopt(state, "cnmspdBbDi25C:r:v", &opt, &opt_arg)) == APR_SUCCESS) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
*mask |= APHTP_NEWFILE;
|
||||
diff --git a/support/passwd_common.c b/support/passwd_common.c
|
||||
index 664e509..d45657c 100644
|
||||
--- a/support/passwd_common.c
|
||||
+++ b/support/passwd_common.c
|
||||
@@ -185,10 +185,15 @@ int mkhash(struct passwd_ctx *ctx)
|
||||
#if CRYPT_ALGO_SUPPORTED
|
||||
char *cbuf;
|
||||
#endif
|
||||
+#ifdef HAVE_CRYPT_SHA2
|
||||
+ const char *setting;
|
||||
+ char method;
|
||||
+#endif
|
||||
|
||||
- if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT) {
|
||||
+ if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT
|
||||
+ && ctx->alg != ALG_CRYPT_SHA256 && ctx->alg != ALG_CRYPT_SHA512 ) {
|
||||
apr_file_printf(errfile,
|
||||
- "Warning: Ignoring -C argument for this algorithm." NL);
|
||||
+ "Warning: Ignoring -C/-r argument for this algorithm." NL);
|
||||
}
|
||||
|
||||
if (ctx->passwd == NULL) {
|
||||
@@ -246,6 +251,34 @@ int mkhash(struct passwd_ctx *ctx)
|
||||
break;
|
||||
#endif /* CRYPT_ALGO_SUPPORTED */
|
||||
|
||||
+#ifdef HAVE_CRYPT_SHA2
|
||||
+ case ALG_CRYPT_SHA256:
|
||||
+ case ALG_CRYPT_SHA512:
|
||||
+ ret = generate_salt(salt, 16, &ctx->errstr, ctx->pool);
|
||||
+ if (ret != 0)
|
||||
+ break;
|
||||
+
|
||||
+ method = ctx->alg == ALG_CRYPT_SHA256 ? '5': '6';
|
||||
+
|
||||
+ if (ctx->cost)
|
||||
+ setting = apr_psprintf(ctx->pool, "$%c$rounds=%d$%s",
|
||||
+ method, ctx->cost, salt);
|
||||
+ else
|
||||
+ setting = apr_psprintf(ctx->pool, "$%c$%s",
|
||||
+ method, salt);
|
||||
+
|
||||
+ cbuf = crypt(pw, setting);
|
||||
+ if (cbuf == NULL) {
|
||||
+ rv = APR_FROM_OS_ERROR(errno);
|
||||
+ ctx->errstr = apr_psprintf(ctx->pool, "crypt() failed: %pm", &rv);
|
||||
+ ret = ERR_PWMISMATCH;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1);
|
||||
+ break;
|
||||
+#endif /* HAVE_CRYPT_SHA2 */
|
||||
+
|
||||
#if BCRYPT_ALGO_SUPPORTED
|
||||
case ALG_BCRYPT:
|
||||
rv = apr_generate_random_bytes((unsigned char*)salt, 16);
|
||||
@@ -294,6 +327,19 @@ int parse_common_options(struct passwd_ctx *ctx, char opt,
|
||||
case 's':
|
||||
ctx->alg = ALG_APSHA;
|
||||
break;
|
||||
+#ifdef HAVE_CRYPT_SHA2
|
||||
+ case '2':
|
||||
+ ctx->alg = ALG_CRYPT_SHA256;
|
||||
+ break;
|
||||
+ case '5':
|
||||
+ ctx->alg = ALG_CRYPT_SHA512;
|
||||
+ break;
|
||||
+#else
|
||||
+ case '2':
|
||||
+ case '5':
|
||||
+ ctx->errstr = "SHA-2 crypt() algorithms are not supported on this platform.";
|
||||
+ return ERR_ALG_NOT_SUPP;
|
||||
+#endif
|
||||
case 'p':
|
||||
ctx->alg = ALG_PLAIN;
|
||||
#if !PLAIN_ALGO_SUPPORTED
|
||||
@@ -324,11 +370,12 @@ int parse_common_options(struct passwd_ctx *ctx, char opt,
|
||||
return ERR_ALG_NOT_SUPP;
|
||||
#endif
|
||||
break;
|
||||
- case 'C': {
|
||||
+ case 'C':
|
||||
+ case 'r': {
|
||||
char *endptr;
|
||||
long num = strtol(opt_arg, &endptr, 10);
|
||||
if (*endptr != '\0' || num <= 0) {
|
||||
- ctx->errstr = "argument to -C must be a positive integer";
|
||||
+ ctx->errstr = "argument to -C/-r must be a positive integer";
|
||||
return ERR_SYNTAX;
|
||||
}
|
||||
ctx->cost = num;
|
||||
diff --git a/support/passwd_common.h b/support/passwd_common.h
|
||||
index 660081e..f1b3cd7 100644
|
||||
--- a/support/passwd_common.h
|
||||
+++ b/support/passwd_common.h
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "apu_version.h"
|
||||
#endif
|
||||
|
||||
+#include "ap_config_auto.h"
|
||||
+
|
||||
#define MAX_STRING_LEN 256
|
||||
|
||||
#define ALG_PLAIN 0
|
||||
@@ -35,6 +37,8 @@
|
||||
#define ALG_APMD5 2
|
||||
#define ALG_APSHA 3
|
||||
#define ALG_BCRYPT 4
|
||||
+#define ALG_CRYPT_SHA256 5
|
||||
+#define ALG_CRYPT_SHA512 6
|
||||
|
||||
#define BCRYPT_DEFAULT_COST 5
|
||||
|
||||
@@ -84,7 +88,7 @@ struct passwd_ctx {
|
||||
apr_size_t out_len;
|
||||
char *passwd;
|
||||
int alg;
|
||||
- int cost;
|
||||
+ int cost; /* cost for bcrypt, rounds for SHA-2 */
|
||||
enum {
|
||||
PW_PROMPT = 0,
|
||||
PW_ARG,
|
108
httpd-2.4.37-r1862410.patch
Normal file
108
httpd-2.4.37-r1862410.patch
Normal file
@ -0,0 +1,108 @@
|
||||
--- a/modules/dav/main/mod_dav.c
|
||||
+++ b/modules/dav/main/mod_dav.c
|
||||
@@ -557,6 +557,7 @@
|
||||
dav_begin_multistatus(bb, r, status, namespaces);
|
||||
|
||||
apr_pool_create(&subpool, r->pool);
|
||||
+ apr_pool_tag(subpool, "mod_dav-multistatus");
|
||||
|
||||
for (; first != NULL; first = first->next) {
|
||||
apr_pool_clear(subpool);
|
||||
@@ -1980,8 +1981,9 @@
|
||||
** Note: we cast to lose the "const". The propdb won't try to change
|
||||
** the resource, however, since we are opening readonly.
|
||||
*/
|
||||
- err = dav_open_propdb(ctx->r, ctx->w.lockdb, wres->resource, 1,
|
||||
- ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
|
||||
+ err = dav_popen_propdb(ctx->scratchpool,
|
||||
+ ctx->r, ctx->w.lockdb, wres->resource, 1,
|
||||
+ ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
|
||||
if (err != NULL) {
|
||||
/* ### do something with err! */
|
||||
|
||||
--- a/modules/dav/main/mod_dav.h
|
||||
+++ b/modules/dav/main/mod_dav.h
|
||||
@@ -1590,6 +1590,16 @@
|
||||
apr_array_header_t *ns_xlate,
|
||||
dav_propdb **propdb);
|
||||
|
||||
+DAV_DECLARE(dav_error *) dav_popen_propdb(
|
||||
+ apr_pool_t *p,
|
||||
+ request_rec *r,
|
||||
+ dav_lockdb *lockdb,
|
||||
+ const dav_resource *resource,
|
||||
+ int ro,
|
||||
+ apr_array_header_t *ns_xlate,
|
||||
+ dav_propdb **propdb);
|
||||
+
|
||||
+
|
||||
DAV_DECLARE(void) dav_close_propdb(dav_propdb *db);
|
||||
|
||||
DAV_DECLARE(dav_get_props_result) dav_get_props(
|
||||
--- a/modules/dav/main/props.c
|
||||
+++ b/modules/dav/main/props.c
|
||||
@@ -323,7 +323,7 @@
|
||||
{
|
||||
/* need to escape the uri that's in the resource struct because during
|
||||
* the property walker it's not encoded. */
|
||||
- const char *e_uri = ap_escape_uri(propdb->resource->pool,
|
||||
+ const char *e_uri = ap_escape_uri(propdb->p,
|
||||
propdb->resource->uri);
|
||||
|
||||
/* perform a "GET" on the resource's URI (note that the resource
|
||||
@@ -524,8 +524,21 @@
|
||||
apr_array_header_t * ns_xlate,
|
||||
dav_propdb **p_propdb)
|
||||
{
|
||||
- dav_propdb *propdb = apr_pcalloc(r->pool, sizeof(*propdb));
|
||||
+ return dav_popen_propdb(r->pool, r, lockdb, resource, ro, ns_xlate, p_propdb);
|
||||
+}
|
||||
|
||||
+DAV_DECLARE(dav_error *)dav_popen_propdb(apr_pool_t *p,
|
||||
+ request_rec *r, dav_lockdb *lockdb,
|
||||
+ const dav_resource *resource,
|
||||
+ int ro,
|
||||
+ apr_array_header_t * ns_xlate,
|
||||
+ dav_propdb **p_propdb)
|
||||
+{
|
||||
+ dav_propdb *propdb = NULL;
|
||||
+
|
||||
+ propdb = apr_pcalloc(p, sizeof(*propdb));
|
||||
+ propdb->p = p;
|
||||
+
|
||||
*p_propdb = NULL;
|
||||
|
||||
#if DAV_DEBUG
|
||||
@@ -537,7 +550,6 @@
|
||||
#endif
|
||||
|
||||
propdb->r = r;
|
||||
- apr_pool_create(&propdb->p, r->pool);
|
||||
propdb->resource = resource;
|
||||
propdb->ns_xlate = ns_xlate;
|
||||
|
||||
@@ -562,10 +574,10 @@
|
||||
(*propdb->db_hooks->close)(propdb->db);
|
||||
}
|
||||
|
||||
- /* Currently, mod_dav's pool usage doesn't allow clearing this pool. */
|
||||
-#if 0
|
||||
- apr_pool_destroy(propdb->p);
|
||||
-#endif
|
||||
+ if (propdb->subreq) {
|
||||
+ ap_destroy_sub_req(propdb->subreq);
|
||||
+ propdb->subreq = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
DAV_DECLARE(dav_get_props_result) dav_get_allprops(dav_propdb *propdb,
|
||||
@@ -739,7 +751,8 @@
|
||||
*/
|
||||
|
||||
if (elem->priv == NULL) {
|
||||
- elem->priv = apr_pcalloc(propdb->p, sizeof(*priv));
|
||||
+ /* elem->priv outlives propdb->p. Hence use the request pool */
|
||||
+ elem->priv = apr_pcalloc(propdb->r->pool, sizeof(*priv));
|
||||
}
|
||||
priv = elem->priv;
|
||||
|
40
httpd-2.4.37-r1864000.patch
Normal file
40
httpd-2.4.37-r1864000.patch
Normal file
@ -0,0 +1,40 @@
|
||||
--- a/modules/proxy/mod_proxy_hcheck.c 2019/07/30 13:01:08 1863999
|
||||
+++ b/modules/proxy/mod_proxy_hcheck.c 2019/07/30 13:01:21 1864000
|
||||
@@ -110,6 +110,10 @@
|
||||
if (!worker && !v) {
|
||||
return "Bad call to set_worker_hc_param()";
|
||||
}
|
||||
+ if (!ctx) {
|
||||
+ ctx = hc_create_config(p, s);
|
||||
+ ap_set_module_config(s->module_config, &proxy_hcheck_module, ctx);
|
||||
+ }
|
||||
temp = (hc_template_t *)v;
|
||||
if (!strcasecmp(key, "hctemplate")) {
|
||||
hc_template_t *template;
|
||||
@@ -1059,6 +1063,8 @@
|
||||
int i;
|
||||
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
|
||||
&proxy_hcheck_module);
|
||||
+ if (!ctx)
|
||||
+ return;
|
||||
if (apr_is_empty_table(ctx->conditions))
|
||||
return;
|
||||
|
||||
@@ -1088,6 +1094,8 @@
|
||||
int i;
|
||||
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
|
||||
&proxy_hcheck_module);
|
||||
+ if (!ctx)
|
||||
+ return;
|
||||
if (apr_is_empty_table(ctx->conditions))
|
||||
return;
|
||||
|
||||
@@ -1111,6 +1119,8 @@
|
||||
int i;
|
||||
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
|
||||
&proxy_hcheck_module);
|
||||
+ if (!ctx)
|
||||
+ return 0;
|
||||
if (apr_is_empty_table(ctx->conditions))
|
||||
return 0;
|
||||
|
117
httpd-2.4.37-r1870095+.patch
Normal file
117
httpd-2.4.37-r1870095+.patch
Normal file
@ -0,0 +1,117 @@
|
||||
# ./pullrev.sh 1870095 1870097
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1870095
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1870097
|
||||
|
||||
--- httpd-2.4.37/modules/ssl/ssl_engine_kernel.c
|
||||
+++ httpd-2.4.37/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -114,6 +114,45 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
+/* If a renegotiation is required for the location, and the request
|
||||
+ * includes a message body (and the client has not requested a "100
|
||||
+ * Continue" response), then the client will be streaming the request
|
||||
+ * body over the wire already. In that case, it is not possible to
|
||||
+ * stop and perform a new SSL handshake immediately; once the SSL
|
||||
+ * library moves to the "accept" state, it will reject the SSL packets
|
||||
+ * which the client is sending for the request body.
|
||||
+ *
|
||||
+ * To allow authentication to complete in the hook, the solution used
|
||||
+ * here is to fill a (bounded) buffer with the request body, and then
|
||||
+ * to reinject that request body later.
|
||||
+ *
|
||||
+ * This function is called to fill the renegotiation buffer for the
|
||||
+ * location as required, or fail. Returns zero on success or HTTP_
|
||||
+ * error code on failure.
|
||||
+ */
|
||||
+static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc)
|
||||
+{
|
||||
+ int rv;
|
||||
+ apr_size_t rsize;
|
||||
+
|
||||
+ /* ### this is HTTP/1.1 specific, special case for protocol? */
|
||||
+ if (r->expecting_100 || !ap_request_has_body(r)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE : dc->nRenegBufferSize;
|
||||
+ if (rsize > 0) {
|
||||
+ /* Fill the I/O buffer with the request body if possible. */
|
||||
+ rv = ssl_io_buffer_fill(r, rsize);
|
||||
+ }
|
||||
+ else {
|
||||
+ /* If the reneg buffer size is set to zero, just fail. */
|
||||
+ rv = HTTP_REQUEST_ENTITY_TOO_LARGE;
|
||||
+ }
|
||||
+
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
#ifdef HAVE_TLSEXT
|
||||
static int ap_array_same_str_set(apr_array_header_t *s1, apr_array_header_t *s2)
|
||||
{
|
||||
@@ -814,41 +853,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
- /* If a renegotiation is now required for this location, and the
|
||||
- * request includes a message body (and the client has not
|
||||
- * requested a "100 Continue" response), then the client will be
|
||||
- * streaming the request body over the wire already. In that
|
||||
- * case, it is not possible to stop and perform a new SSL
|
||||
- * handshake immediately; once the SSL library moves to the
|
||||
- * "accept" state, it will reject the SSL packets which the client
|
||||
- * is sending for the request body.
|
||||
- *
|
||||
- * To allow authentication to complete in this auth hook, the
|
||||
- * solution used here is to fill a (bounded) buffer with the
|
||||
- * request body, and then to reinject that request body later.
|
||||
- */
|
||||
- if (renegotiate && !renegotiate_quick
|
||||
- && !r->expecting_100
|
||||
- && ap_request_has_body(r)) {
|
||||
- int rv;
|
||||
- apr_size_t rsize;
|
||||
-
|
||||
- rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE :
|
||||
- dc->nRenegBufferSize;
|
||||
- if (rsize > 0) {
|
||||
- /* Fill the I/O buffer with the request body if possible. */
|
||||
- rv = ssl_io_buffer_fill(r, rsize);
|
||||
- }
|
||||
- else {
|
||||
- /* If the reneg buffer size is set to zero, just fail. */
|
||||
- rv = HTTP_REQUEST_ENTITY_TOO_LARGE;
|
||||
- }
|
||||
-
|
||||
- if (rv) {
|
||||
+ /* Fill reneg buffer if required. */
|
||||
+ if (renegotiate && !renegotiate_quick) {
|
||||
+ rc = fill_reneg_buffer(r, dc);
|
||||
+ if (rc) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02257)
|
||||
"could not buffer message body to allow "
|
||||
"SSL renegotiation to proceed");
|
||||
- return rv;
|
||||
+ return rc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,6 +1144,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Fill reneg buffer if required. */
|
||||
+ if (change_vmode) {
|
||||
+ rc = fill_reneg_buffer(r, dc);
|
||||
+ if (rc) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10228)
|
||||
+ "could not buffer message body to allow "
|
||||
+ "TLS Post-Handshake Authentication to proceed");
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (change_vmode) {
|
||||
char peekbuf[1];
|
||||
|
636
httpd-2.4.37-r1872790.patch
Normal file
636
httpd-2.4.37-r1872790.patch
Normal file
@ -0,0 +1,636 @@
|
||||
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
|
||||
index 57cc92f..fbbd508 100644
|
||||
--- a/modules/proxy/mod_proxy.h
|
||||
+++ b/modules/proxy/mod_proxy.h
|
||||
@@ -288,12 +288,15 @@ typedef struct {
|
||||
|
||||
/* Connection pool */
|
||||
struct proxy_conn_pool {
|
||||
- apr_pool_t *pool; /* The pool used in constructor and destructor calls */
|
||||
- apr_sockaddr_t *addr; /* Preparsed remote address info */
|
||||
- apr_reslist_t *res; /* Connection resource list */
|
||||
- proxy_conn_rec *conn; /* Single connection for prefork mpm */
|
||||
+ apr_pool_t *pool; /* The pool used in constructor and destructor calls */
|
||||
+ apr_sockaddr_t *addr; /* Preparsed remote address info */
|
||||
+ apr_reslist_t *res; /* Connection resource list */
|
||||
+ proxy_conn_rec *conn; /* Single connection for prefork mpm */
|
||||
+ apr_pool_t *dns_pool; /* The pool used for worker scoped DNS resolutions */
|
||||
};
|
||||
|
||||
+#define AP_VOLATILIZE_T(T, x) (*(T volatile *)&(x))
|
||||
+
|
||||
/* worker status bits */
|
||||
/*
|
||||
* NOTE: Keep up-to-date w/ proxy_wstat_tbl[]
|
||||
@@ -475,7 +478,9 @@ struct proxy_worker {
|
||||
proxy_conn_pool *cp; /* Connection pool to use */
|
||||
proxy_worker_shared *s; /* Shared data */
|
||||
proxy_balancer *balancer; /* which balancer am I in? */
|
||||
+#if APR_HAS_THREADS
|
||||
apr_thread_mutex_t *tmutex; /* Thread lock for updating address cache */
|
||||
+#endif
|
||||
void *context; /* general purpose storage */
|
||||
ap_conf_vector_t *section_config; /* <Proxy>-section wherein defined */
|
||||
};
|
||||
@@ -534,7 +539,9 @@ struct proxy_balancer {
|
||||
apr_time_t wupdated; /* timestamp of last change to workers list */
|
||||
proxy_balancer_method *lbmethod;
|
||||
apr_global_mutex_t *gmutex; /* global lock for updating list of workers */
|
||||
+#if APR_HAS_THREADS
|
||||
apr_thread_mutex_t *tmutex; /* Thread lock for updating shm */
|
||||
+#endif
|
||||
proxy_server_conf *sconf;
|
||||
void *context; /* general purpose storage */
|
||||
proxy_balancer_shared *s; /* Shared data */
|
||||
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
|
||||
index c59f5e9..3a28038 100644
|
||||
--- a/modules/proxy/mod_proxy_balancer.c
|
||||
+++ b/modules/proxy/mod_proxy_balancer.c
|
||||
@@ -346,23 +346,27 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer,
|
||||
proxy_worker *candidate = NULL;
|
||||
apr_status_t rv;
|
||||
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01163)
|
||||
"%s: Lock failed for find_best_worker()",
|
||||
balancer->s->name);
|
||||
return NULL;
|
||||
}
|
||||
+#endif
|
||||
|
||||
candidate = (*balancer->lbmethod->finder)(balancer, r);
|
||||
|
||||
if (candidate)
|
||||
candidate->s->elected++;
|
||||
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01164)
|
||||
"%s: Unlock failed for find_best_worker()",
|
||||
balancer->s->name);
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (candidate == NULL) {
|
||||
/* All the workers are in error state or disabled.
|
||||
@@ -492,11 +496,13 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
|
||||
/* Step 2: Lock the LoadBalancer
|
||||
* XXX: perhaps we need the process lock here
|
||||
*/
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01166)
|
||||
"%s: Lock failed for pre_request", (*balancer)->s->name);
|
||||
return DECLINED;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* Step 3: force recovery */
|
||||
force_recovery(*balancer, r->server);
|
||||
@@ -557,20 +563,24 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01167)
|
||||
"%s: All workers are in error state for route (%s)",
|
||||
(*balancer)->s->name, route);
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01168)
|
||||
"%s: Unlock failed for pre_request",
|
||||
(*balancer)->s->name);
|
||||
}
|
||||
+#endif
|
||||
return HTTP_SERVICE_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01169)
|
||||
"%s: Unlock failed for pre_request",
|
||||
(*balancer)->s->name);
|
||||
}
|
||||
+#endif
|
||||
if (!*worker) {
|
||||
runtime = find_best_worker(*balancer, r);
|
||||
if (!runtime) {
|
||||
@@ -644,12 +654,14 @@ static int proxy_balancer_post_request(proxy_worker *worker,
|
||||
|
||||
apr_status_t rv;
|
||||
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01173)
|
||||
"%s: Lock failed for post_request",
|
||||
balancer->s->name);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (!apr_is_empty_array(balancer->errstatuses)
|
||||
&& !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
|
||||
@@ -681,11 +693,12 @@ static int proxy_balancer_post_request(proxy_worker *worker,
|
||||
worker->s->error_time = apr_time_now();
|
||||
|
||||
}
|
||||
-
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01175)
|
||||
"%s: Unlock failed for post_request", balancer->s->name);
|
||||
}
|
||||
+#endif
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01176)
|
||||
"proxy_balancer_post_request for (%s)", balancer->s->name);
|
||||
|
||||
@@ -945,7 +958,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
PROXY_STRNCPY(balancer->s->sname, sname); /* We know this will succeed */
|
||||
|
||||
balancer->max_workers = balancer->workers->nelts + balancer->growth;
|
||||
-
|
||||
/* Create global mutex */
|
||||
rv = ap_global_mutex_create(&(balancer->gmutex), NULL, balancer_mutex_type,
|
||||
balancer->s->sname, s, pconf, 0);
|
||||
@@ -955,7 +967,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
balancer->s->sname);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
-
|
||||
apr_pool_cleanup_register(pconf, (void *)s, lock_remove,
|
||||
apr_pool_cleanup_null);
|
||||
|
||||
@@ -1135,17 +1146,21 @@ static int balancer_handler(request_rec *r)
|
||||
|
||||
balancer = (proxy_balancer *)conf->balancers->elts;
|
||||
for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01189)
|
||||
"%s: Lock failed for balancer_handler",
|
||||
balancer->s->name);
|
||||
}
|
||||
+#endif
|
||||
ap_proxy_sync_balancer(balancer, r->server, conf);
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01190)
|
||||
"%s: Unlock failed for balancer_handler",
|
||||
balancer->s->name);
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
if (r->args && (r->method_number == M_GET)) {
|
||||
@@ -1359,11 +1374,13 @@ static int balancer_handler(request_rec *r)
|
||||
proxy_worker *nworker;
|
||||
nworker = ap_proxy_get_worker(r->pool, bsel, conf, val);
|
||||
if (!nworker && storage->num_free_slots(bsel->wslot)) {
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_LOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01194)
|
||||
"%s: Lock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
ret = ap_proxy_define_worker(conf->pool, &nworker, bsel, conf, val, 0);
|
||||
if (!ret) {
|
||||
unsigned int index;
|
||||
@@ -1372,53 +1389,76 @@ static int balancer_handler(request_rec *r)
|
||||
if ((rv = storage->grab(bsel->wslot, &index)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01195)
|
||||
"worker slotmem_grab failed");
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01196)
|
||||
"%s: Unlock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
if ((rv = storage->dptr(bsel->wslot, index, (void *)&shm)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01197)
|
||||
"worker slotmem_dptr failed");
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01198)
|
||||
"%s: Unlock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
if ((rv = ap_proxy_share_worker(nworker, shm, index)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01199)
|
||||
"Cannot share worker");
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01200)
|
||||
"%s: Unlock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
if ((rv = ap_proxy_initialize_worker(nworker, r->server, conf->pool)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01201)
|
||||
"Cannot init worker");
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01202)
|
||||
"%s: Unlock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
/* sync all timestamps */
|
||||
bsel->wupdated = bsel->s->wupdated = nworker->s->updated = apr_time_now();
|
||||
/* by default, all new workers are disabled */
|
||||
ap_proxy_set_wstatus(PROXY_WORKER_DISABLED_FLAG, 1, nworker);
|
||||
+ } else {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10163)
|
||||
+ "%s: failed to add worker %s",
|
||||
+ bsel->s->name, val);
|
||||
+#if APR_HAS_THREADS
|
||||
+ PROXY_GLOBAL_UNLOCK(bsel);
|
||||
+#endif
|
||||
+ return HTTP_BAD_REQUEST;
|
||||
}
|
||||
+#if APR_HAS_THREADS
|
||||
if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01203)
|
||||
"%s: Unlock failed for adding worker",
|
||||
bsel->s->name);
|
||||
}
|
||||
+#endif
|
||||
+ } else {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10164)
|
||||
+ "%s: failed to add worker %s",
|
||||
+ bsel->s->name, val);
|
||||
+ return HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
|
||||
index 5d9175e..5c4d641 100644
|
||||
--- a/modules/proxy/mod_proxy_ftp.c
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c
|
||||
@@ -979,8 +979,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
apr_status_t rv;
|
||||
conn_rec *origin, *data = NULL;
|
||||
apr_status_t err = APR_SUCCESS;
|
||||
+#if APR_HAS_THREADS
|
||||
apr_status_t uerr = APR_SUCCESS;
|
||||
- apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
|
||||
+#endif
|
||||
+ apr_bucket_brigade *bb;
|
||||
char *buf, *connectname;
|
||||
apr_port_t connectport;
|
||||
char *ftpmessage = NULL;
|
||||
@@ -1120,13 +1122,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
|
||||
if (worker->s->is_address_reusable) {
|
||||
if (!worker->cp->addr) {
|
||||
+#if APR_HAS_THREADS
|
||||
if ((err = PROXY_THREAD_LOCK(worker->balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(01037) "lock");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
- connect_addr = worker->cp->addr;
|
||||
- address_pool = worker->cp->pool;
|
||||
+ connect_addr = AP_VOLATILIZE_T(apr_sockaddr_t *, worker->cp->addr);
|
||||
+ address_pool = worker->cp->dns_pool;
|
||||
}
|
||||
else
|
||||
address_pool = r->pool;
|
||||
@@ -1139,9 +1143,11 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
address_pool);
|
||||
if (worker->s->is_address_reusable && !worker->cp->addr) {
|
||||
worker->cp->addr = connect_addr;
|
||||
+#if APR_HAS_THREADS
|
||||
if ((uerr = PROXY_THREAD_UNLOCK(worker->balancer)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(01038) "unlock");
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
/*
|
||||
* get all the possible IP addresses for the destname and loop through
|
||||
@@ -1212,6 +1218,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
* correct directory...
|
||||
*/
|
||||
|
||||
+ bb = apr_brigade_create(p, c->bucket_alloc);
|
||||
|
||||
/* possible results: */
|
||||
/* 120 Service ready in nnn minutes. */
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 2bfc8f0..7714b6c 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -1167,8 +1167,10 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
|
||||
lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0");
|
||||
|
||||
(*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
|
||||
+#if APR_HAS_THREADS
|
||||
(*balancer)->gmutex = NULL;
|
||||
(*balancer)->tmutex = NULL;
|
||||
+#endif
|
||||
(*balancer)->lbmethod = lbmethod;
|
||||
|
||||
if (do_malloc)
|
||||
@@ -1257,7 +1259,9 @@ PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
|
||||
|
||||
PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, server_rec *s, apr_pool_t *p)
|
||||
{
|
||||
+#if APR_HAS_THREADS
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
+#endif
|
||||
ap_slotmem_provider_t *storage = balancer->storage;
|
||||
apr_size_t size;
|
||||
unsigned int num;
|
||||
@@ -1297,6 +1301,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balance
|
||||
if (balancer->lbmethod && balancer->lbmethod->reset)
|
||||
balancer->lbmethod->reset(balancer, s);
|
||||
|
||||
+#if APR_HAS_THREADS
|
||||
if (balancer->tmutex == NULL) {
|
||||
rv = apr_thread_mutex_create(&(balancer->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
|
||||
if (rv != APR_SUCCESS) {
|
||||
@@ -1305,6 +1310,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balance
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1446,16 +1452,14 @@ static void socket_cleanup(proxy_conn_rec *conn)
|
||||
|
||||
static apr_status_t conn_pool_cleanup(void *theworker)
|
||||
{
|
||||
- proxy_worker *worker = (proxy_worker *)theworker;
|
||||
- if (worker->cp->res) {
|
||||
- worker->cp->pool = NULL;
|
||||
- }
|
||||
+ ((proxy_worker *)theworker)->cp = NULL;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
+ apr_pool_t *dns_pool;
|
||||
proxy_conn_pool *cp;
|
||||
|
||||
/*
|
||||
@@ -1466,12 +1470,21 @@ static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
|
||||
*/
|
||||
apr_pool_create(&pool, p);
|
||||
apr_pool_tag(pool, "proxy_worker_cp");
|
||||
+ /*
|
||||
+ * Create a subpool of the connection pool for worker
|
||||
+ * scoped DNS resolutions. This is needed to avoid race
|
||||
+ * conditions in using the connection pool by multiple
|
||||
+ * threads during ramp up.
|
||||
+ */
|
||||
+ apr_pool_create(&dns_pool, pool);
|
||||
+ apr_pool_tag(dns_pool, "proxy_worker_dns");
|
||||
/*
|
||||
* Alloc from the same pool as worker.
|
||||
* proxy_conn_pool is permanently attached to the worker.
|
||||
*/
|
||||
cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));
|
||||
cp->pool = pool;
|
||||
+ cp->dns_pool = dns_pool;
|
||||
worker->cp = cp;
|
||||
}
|
||||
|
||||
@@ -1487,14 +1500,6 @@ static apr_status_t connection_cleanup(void *theconn)
|
||||
proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
|
||||
proxy_worker *worker = conn->worker;
|
||||
|
||||
- /*
|
||||
- * If the connection pool is NULL the worker
|
||||
- * cleanup has been run. Just return.
|
||||
- */
|
||||
- if (!worker->cp->pool) {
|
||||
- return APR_SUCCESS;
|
||||
- }
|
||||
-
|
||||
if (conn->r) {
|
||||
apr_pool_destroy(conn->r->pool);
|
||||
conn->r = NULL;
|
||||
@@ -1616,7 +1621,7 @@ static apr_status_t connection_destructor(void *resource, void *params,
|
||||
proxy_worker *worker = params;
|
||||
|
||||
/* Destroy the pool only if not called from reslist_destroy */
|
||||
- if (worker->cp->pool) {
|
||||
+ if (worker->cp) {
|
||||
proxy_conn_rec *conn = resource;
|
||||
apr_pool_destroy(conn->pool);
|
||||
}
|
||||
@@ -1972,67 +1977,73 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
|
||||
ap_proxy_worker_name(p, worker));
|
||||
}
|
||||
else {
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
|
||||
- "initializing worker %s local",
|
||||
- ap_proxy_worker_name(p, worker));
|
||||
apr_global_mutex_lock(proxy_mutex);
|
||||
- /* Now init local worker data */
|
||||
- if (worker->tmutex == NULL) {
|
||||
- rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
|
||||
- if (rv != APR_SUCCESS) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00928)
|
||||
- "can not create worker thread mutex");
|
||||
+ /* Check again after we got the lock if we are still uninitialized */
|
||||
+ if (!(AP_VOLATILIZE_T(unsigned int, worker->local_status) & PROXY_WORKER_INITIALIZED)) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
|
||||
+ "initializing worker %s local",
|
||||
+ ap_proxy_worker_name(p, worker));
|
||||
+ /* Now init local worker data */
|
||||
+#if APR_HAS_THREADS
|
||||
+ if (worker->tmutex == NULL) {
|
||||
+ rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00928)
|
||||
+ "can not create worker thread mutex");
|
||||
+ apr_global_mutex_unlock(proxy_mutex);
|
||||
+ return rv;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ if (worker->cp == NULL)
|
||||
+ init_conn_pool(p, worker);
|
||||
+ if (worker->cp == NULL) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
|
||||
+ "can not create connection pool");
|
||||
apr_global_mutex_unlock(proxy_mutex);
|
||||
- return rv;
|
||||
+ return APR_EGENERAL;
|
||||
}
|
||||
- }
|
||||
- if (worker->cp == NULL)
|
||||
- init_conn_pool(p, worker);
|
||||
- if (worker->cp == NULL) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
|
||||
- "can not create connection pool");
|
||||
- apr_global_mutex_unlock(proxy_mutex);
|
||||
- return APR_EGENERAL;
|
||||
- }
|
||||
|
||||
- if (worker->s->hmax) {
|
||||
- rv = apr_reslist_create(&(worker->cp->res),
|
||||
- worker->s->min, worker->s->smax,
|
||||
- worker->s->hmax, worker->s->ttl,
|
||||
- connection_constructor, connection_destructor,
|
||||
- worker, worker->cp->pool);
|
||||
+ if (worker->s->hmax) {
|
||||
+ rv = apr_reslist_create(&(worker->cp->res),
|
||||
+ worker->s->min, worker->s->smax,
|
||||
+ worker->s->hmax, worker->s->ttl,
|
||||
+ connection_constructor, connection_destructor,
|
||||
+ worker, worker->cp->pool);
|
||||
|
||||
- apr_pool_cleanup_register(worker->cp->pool, (void *)worker,
|
||||
- conn_pool_cleanup,
|
||||
- apr_pool_cleanup_null);
|
||||
+ apr_pool_pre_cleanup_register(worker->cp->pool, worker,
|
||||
+ conn_pool_cleanup);
|
||||
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00930)
|
||||
- "initialized pool in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d",
|
||||
- getpid(), worker->s->hostname_ex, worker->s->min,
|
||||
- worker->s->hmax, worker->s->smax);
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00930)
|
||||
+ "initialized pool in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d",
|
||||
+ getpid(), worker->s->hostname_ex, worker->s->min,
|
||||
+ worker->s->hmax, worker->s->smax);
|
||||
|
||||
- /* Set the acquire timeout */
|
||||
- if (rv == APR_SUCCESS && worker->s->acquire_set) {
|
||||
- apr_reslist_timeout_set(worker->cp->res, worker->s->acquire);
|
||||
- }
|
||||
+ /* Set the acquire timeout */
|
||||
+ if (rv == APR_SUCCESS && worker->s->acquire_set) {
|
||||
+ apr_reslist_timeout_set(worker->cp->res, worker->s->acquire);
|
||||
+ }
|
||||
|
||||
- }
|
||||
- else {
|
||||
- void *conn;
|
||||
+ }
|
||||
+ else {
|
||||
+ void *conn;
|
||||
|
||||
- rv = connection_constructor(&conn, worker, worker->cp->pool);
|
||||
- worker->cp->conn = conn;
|
||||
+ rv = connection_constructor(&conn, worker, worker->cp->pool);
|
||||
+ worker->cp->conn = conn;
|
||||
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00931)
|
||||
- "initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
|
||||
- getpid(), worker->s->hostname_ex);
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(00931)
|
||||
+ "initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
|
||||
+ getpid(), worker->s->hostname_ex);
|
||||
+ }
|
||||
+ if (rv == APR_SUCCESS) {
|
||||
+ worker->local_status |= (PROXY_WORKER_INITIALIZED);
|
||||
+ }
|
||||
}
|
||||
apr_global_mutex_unlock(proxy_mutex);
|
||||
|
||||
}
|
||||
if (rv == APR_SUCCESS) {
|
||||
worker->s->status |= (PROXY_WORKER_INITIALIZED);
|
||||
- worker->local_status |= (PROXY_WORKER_INITIALIZED);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -2292,13 +2303,13 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
|
||||
else {
|
||||
/* create the new connection if the previous was destroyed */
|
||||
if (!worker->cp->conn) {
|
||||
- connection_constructor((void **)conn, worker, worker->cp->pool);
|
||||
+ rv = connection_constructor((void **)conn, worker, worker->cp->pool);
|
||||
}
|
||||
else {
|
||||
*conn = worker->cp->conn;
|
||||
worker->cp->conn = NULL;
|
||||
+ rv = APR_SUCCESS;
|
||||
}
|
||||
- rv = APR_SUCCESS;
|
||||
}
|
||||
|
||||
if (rv != APR_SUCCESS) {
|
||||
@@ -2344,7 +2355,9 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
|
||||
{
|
||||
int server_port;
|
||||
apr_status_t err = APR_SUCCESS;
|
||||
+#if APR_HAS_THREADS
|
||||
apr_status_t uerr = APR_SUCCESS;
|
||||
+#endif
|
||||
const char *uds_path;
|
||||
|
||||
/*
|
||||
@@ -2481,25 +2494,39 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
|
||||
* we can reuse the address.
|
||||
*/
|
||||
if (!worker->cp->addr) {
|
||||
+#if APR_HAS_THREADS
|
||||
if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/*
|
||||
- * Worker can have the single constant backend address.
|
||||
- * The single DNS lookup is used once per worker.
|
||||
- * If dynamic change is needed then set the addr to NULL
|
||||
- * inside dynamic config to force the lookup.
|
||||
+ * Recheck addr after we got the lock. This may have changed
|
||||
+ * while waiting for the lock.
|
||||
*/
|
||||
- err = apr_sockaddr_info_get(&(worker->cp->addr),
|
||||
- conn->hostname, APR_UNSPEC,
|
||||
- conn->port, 0,
|
||||
- worker->cp->pool);
|
||||
+ if (!AP_VOLATILIZE_T(apr_sockaddr_t *, worker->cp->addr)) {
|
||||
+
|
||||
+ apr_sockaddr_t *addr;
|
||||
+
|
||||
+ /*
|
||||
+ * Worker can have the single constant backend address.
|
||||
+ * The single DNS lookup is used once per worker.
|
||||
+ * If dynamic change is needed then set the addr to NULL
|
||||
+ * inside dynamic config to force the lookup.
|
||||
+ */
|
||||
+ err = apr_sockaddr_info_get(&addr,
|
||||
+ conn->hostname, APR_UNSPEC,
|
||||
+ conn->port, 0,
|
||||
+ worker->cp->dns_pool);
|
||||
+ worker->cp->addr = addr;
|
||||
+ }
|
||||
conn->addr = worker->cp->addr;
|
||||
+#if APR_HAS_THREADS
|
||||
if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
else {
|
||||
conn->addr = worker->cp->addr;
|
||||
@@ -3422,7 +3449,9 @@ PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, server_rec
|
||||
(*runtime)->cp = NULL;
|
||||
(*runtime)->balancer = b;
|
||||
(*runtime)->s = shm;
|
||||
+#if APR_HAS_THREADS
|
||||
(*runtime)->tmutex = NULL;
|
||||
+#endif
|
||||
rv = ap_proxy_initialize_worker(*runtime, s, conf->pool);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00966) "Cannot init worker");
|
265
httpd-2.4.37-r1873907.patch
Normal file
265
httpd-2.4.37-r1873907.patch
Normal file
@ -0,0 +1,265 @@
|
||||
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
|
||||
index b543150..ab72d4f 100644
|
||||
--- a/docs/manual/mod/mod_ssl.html.en
|
||||
+++ b/docs/manual/mod/mod_ssl.html.en
|
||||
@@ -1524,6 +1524,32 @@ The available (case-insensitive) <em>protocol</em>s are:</p>
|
||||
<div class="example"><h3>Example</h3><pre class="prettyprint lang-config">SSLProtocol TLSv1</pre>
|
||||
</div>
|
||||
|
||||
+<div class="note">
|
||||
+<h3><code class="directive">SSLProtocol</code> for name-based virtual hosts</h3>
|
||||
+<p>
|
||||
+Before OpenSSL 1.1.1, even though the Server Name Indication (SNI) allowed to
|
||||
+determine the targeted virtual host early in the TLS handshake, it was not
|
||||
+possible to switch the TLS protocol version of the connection at this point,
|
||||
+and thus the <code class="directive">SSLProtocol</code> negotiated was always based off
|
||||
+the one of the <em>base virtual host</em> (first virtual host declared on the
|
||||
+listening <code>IP:port</code> of the connection).
|
||||
+</p>
|
||||
+<p>
|
||||
+Beginning with Apache HTTP server version 2.4.42, when built/linked against
|
||||
+OpenSSL 1.1.1 or later, and when the SNI is provided by the client in the TLS
|
||||
+handshake, the <code class="directive">SSLProtocol</code> of each (name-based) virtual
|
||||
+host can and will be honored.
|
||||
+</p>
|
||||
+<p>
|
||||
+For compatibility with previous versions, if no
|
||||
+<code class="directive">SSLProtocol</code> is configured in a name-based virtual host,
|
||||
+the one from the base virtual host still applies, <strong>unless</strong>
|
||||
+<code class="directive">SSLProtocol</code> is configured globally in which case the
|
||||
+global value applies (this latter exception is more sensible than compatible,
|
||||
+though).
|
||||
+</p>
|
||||
+</div>
|
||||
+
|
||||
</div>
|
||||
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
|
||||
<div class="directive-section"><h2><a name="SSLProxyCACertificateFile" id="SSLProxyCACertificateFile">SSLProxyCACertificateFile</a> <a name="sslproxycacertificatefile" id="sslproxycacertificatefile">Directive</a></h2>
|
||||
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
|
||||
index 0c4bf1f..ca5f702 100644
|
||||
--- a/modules/ssl/ssl_engine_config.c
|
||||
+++ b/modules/ssl/ssl_engine_config.c
|
||||
@@ -269,6 +269,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
|
||||
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 31062bc..70d151e 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -520,7 +520,9 @@ static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s,
|
||||
"Configuring TLS extension handling");
|
||||
|
||||
/*
|
||||
- * Server name indication (SNI)
|
||||
+ * The Server Name Indication (SNI) provided by the ClientHello can be
|
||||
+ * used to select the right (name-based-)vhost and its SSL configuration
|
||||
+ * before the handshake takes place.
|
||||
*/
|
||||
if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
|
||||
ssl_callback_ServerNameIndication) ||
|
||||
@@ -532,6 +534,16 @@ static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s,
|
||||
return ssl_die(s);
|
||||
}
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
+ /*
|
||||
+ * The ClientHello callback also allows to retrieve the SNI, but since it
|
||||
+ * runs at the earliest possible connection stage we can even set the TLS
|
||||
+ * protocol version(s) according to the selected (name-based-)vhost, which
|
||||
+ * is not possible at the SNI callback stage (due to OpenSSL internals).
|
||||
+ */
|
||||
+ SSL_CTX_set_client_hello_cb(mctx->ssl_ctx, ssl_callback_ClientHello, NULL);
|
||||
+#endif
|
||||
+
|
||||
#ifdef HAVE_OCSP_STAPLING
|
||||
/*
|
||||
* OCSP Stapling support, status_request extension
|
||||
@@ -708,7 +720,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
|
||||
#else /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
/* We first determine the maximum protocol version we should provide */
|
||||
#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
- if (SSL_HAVE_PROTOCOL_TLSV1_3 && (protocol & SSL_PROTOCOL_TLSV1_3)) {
|
||||
+ if (protocol & SSL_PROTOCOL_TLSV1_3) {
|
||||
prot = TLS1_3_VERSION;
|
||||
} else
|
||||
#endif
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index 8b44674..7313a55 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -2357,28 +2357,31 @@ static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
|
||||
* This function sets the virtual host from an extended
|
||||
* client hello with a server name indication extension ("SNI", cf. RFC 6066).
|
||||
*/
|
||||
-static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
|
||||
+static apr_status_t init_vhost(conn_rec *c, SSL *ssl, const char *servername)
|
||||
{
|
||||
- const char *servername;
|
||||
X509 *cert;
|
||||
EVP_PKEY *key;
|
||||
|
||||
if (c) {
|
||||
SSLConnRec *sslcon = myConnConfig(c);
|
||||
-
|
||||
- if (sslcon->server != c->base_server) {
|
||||
- /* already found the vhost */
|
||||
- return APR_SUCCESS;
|
||||
+
|
||||
+ if (sslcon->vhost_found) {
|
||||
+ /* already found the vhost? */
|
||||
+ return sslcon->vhost_found > 0 ? APR_SUCCESS : APR_NOTFOUND;
|
||||
}
|
||||
+ sslcon->vhost_found = -1;
|
||||
|
||||
- servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
+ if (!servername) {
|
||||
+ servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
+ }
|
||||
if (servername) {
|
||||
if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
|
||||
(void *)servername)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043)
|
||||
"SSL virtual host for servername %s found",
|
||||
servername);
|
||||
-
|
||||
+
|
||||
+ sslcon->vhost_found = +1;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
else if (ssl_is_challenge(c, servername, &cert, &key)) {
|
||||
@@ -2428,11 +2431,72 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
|
||||
int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
|
||||
{
|
||||
conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
|
||||
- apr_status_t status = init_vhost(c, ssl);
|
||||
+ apr_status_t status = init_vhost(c, ssl, NULL);
|
||||
|
||||
return (status == APR_SUCCESS)? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
+/*
|
||||
+ * This callback function is called when the ClientHello is received.
|
||||
+ */
|
||||
+int ssl_callback_ClientHello(SSL *ssl, int *al, void *arg)
|
||||
+{
|
||||
+ char *servername = NULL;
|
||||
+ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
|
||||
+ const unsigned char *pos;
|
||||
+ size_t len, remaining;
|
||||
+ (void)arg;
|
||||
+
|
||||
+ /* We can't use SSL_get_servername() at this earliest OpenSSL connection
|
||||
+ * stage, and there is no SSL_client_hello_get0_servername() provided as
|
||||
+ * of OpenSSL 1.1.1. So the code below, that extracts the SNI from the
|
||||
+ * ClientHello's TLS extensions, is taken from some test code in OpenSSL,
|
||||
+ * i.e. client_hello_select_server_ctx() in "test/handshake_helper.c".
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ * The server_name extension was given too much extensibility when it
|
||||
+ * was written, so parsing the normal case is a bit complex.
|
||||
+ */
|
||||
+ if (!SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &pos,
|
||||
+ &remaining)
|
||||
+ || remaining <= 2)
|
||||
+ goto give_up;
|
||||
+
|
||||
+ /* Extract the length of the supplied list of names. */
|
||||
+ len = (*(pos++) << 8);
|
||||
+ len += *(pos++);
|
||||
+ if (len + 2 != remaining)
|
||||
+ goto give_up;
|
||||
+ remaining = len;
|
||||
+
|
||||
+ /*
|
||||
+ * The list in practice only has a single element, so we only consider
|
||||
+ * the first one.
|
||||
+ */
|
||||
+ if (remaining <= 3 || *pos++ != TLSEXT_NAMETYPE_host_name)
|
||||
+ goto give_up;
|
||||
+ remaining--;
|
||||
+
|
||||
+ /* Now we can finally pull out the byte array with the actual hostname. */
|
||||
+ len = (*(pos++) << 8);
|
||||
+ len += *(pos++);
|
||||
+ if (len + 2 != remaining)
|
||||
+ goto give_up;
|
||||
+
|
||||
+ /* Use the SNI to switch to the relevant vhost, should it differ from
|
||||
+ * c->base_server.
|
||||
+ */
|
||||
+ servername = apr_pstrmemdup(c->pool, (const char *)pos, len);
|
||||
+
|
||||
+give_up:
|
||||
+ init_vhost(c, ssl, servername);
|
||||
+ return SSL_CLIENT_HELLO_SUCCESS;
|
||||
+}
|
||||
+#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
|
||||
+
|
||||
+
|
||||
/*
|
||||
* Find a (name-based) SSL virtual host where either the ServerName
|
||||
* or one of the ServerAliases matches the supplied name (to be used
|
||||
@@ -2452,12 +2516,25 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
|
||||
if (found && (ssl = sslcon->ssl) &&
|
||||
(sc = mySrvConfig(s))) {
|
||||
SSL_CTX *ctx = SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx);
|
||||
+
|
||||
/*
|
||||
* SSL_set_SSL_CTX() only deals with the server cert,
|
||||
* so we need to duplicate a few additional settings
|
||||
* from the ctx by hand
|
||||
*/
|
||||
SSL_set_options(ssl, SSL_CTX_get_options(ctx));
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L \
|
||||
+ && (!defined(LIBRESSL_VERSION_NUMBER) \
|
||||
+ || LIBRESSL_VERSION_NUMBER >= 0x20800000L)
|
||||
+ /*
|
||||
+ * Don't switch the protocol if none is configured for this vhost,
|
||||
+ * the default in this case is still the base server's SSLProtocol.
|
||||
+ */
|
||||
+ if (myCtxConfig(sslcon, sc)->protocol_set) {
|
||||
+ SSL_set_min_proto_version(ssl, SSL_CTX_get_min_proto_version(ctx));
|
||||
+ SSL_set_max_proto_version(ssl, SSL_CTX_get_max_proto_version(ctx));
|
||||
+ }
|
||||
+#endif
|
||||
if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
|
||||
(SSL_num_renegotiations(ssl) == 0)) {
|
||||
/*
|
||||
@@ -2654,7 +2731,7 @@ int ssl_callback_alpn_select(SSL *ssl,
|
||||
* they callback the SNI. We need to make sure that we know which vhost
|
||||
* we are dealing with so we respect the correct protocols.
|
||||
*/
|
||||
- init_vhost(c, ssl);
|
||||
+ init_vhost(c, ssl, NULL);
|
||||
|
||||
proposed = ap_select_protocol(c, NULL, sslconn->server, client_protos);
|
||||
if (!proposed) {
|
||||
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
|
||||
index 8055200..f8a1db7 100644
|
||||
--- a/modules/ssl/ssl_private.h
|
||||
+++ b/modules/ssl/ssl_private.h
|
||||
@@ -563,6 +563,7 @@ typedef struct {
|
||||
|
||||
const char *cipher_suite; /* cipher suite used in last reneg */
|
||||
int service_unavailable; /* thouugh we negotiate SSL, no requests will be served */
|
||||
+ int vhost_found; /* whether we found vhost from SNI already */
|
||||
} SSLConnRec;
|
||||
|
||||
/* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is
|
||||
@@ -946,6 +947,9 @@ void ssl_callback_Info(const SSL *, int, int);
|
||||
#ifdef HAVE_TLSEXT
|
||||
int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
|
||||
#endif
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
+int ssl_callback_ClientHello(SSL *, int *, void *);
|
||||
+#endif
|
||||
#ifdef HAVE_TLS_SESSION_TICKETS
|
||||
int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *,
|
||||
EVP_CIPHER_CTX *, HMAC_CTX *, int);
|
249
httpd-2.4.37-r1877397.patch
Normal file
249
httpd-2.4.37-r1877397.patch
Normal file
@ -0,0 +1,249 @@
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index b286053..8b6c34f 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -824,6 +824,13 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
|
||||
SSL_CTX_set_keylog_callback(ctx, modssl_callback_keylog);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#ifdef SSL_OP_NO_RENEGOTIATION
|
||||
+ /* For server-side SSL_CTX, disable renegotiation by default.. */
|
||||
+ if (!mctx->pkp) {
|
||||
+ SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION);
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
@@ -845,6 +852,14 @@ static void ssl_init_ctx_session_cache(server_rec *s,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef SSL_OP_NO_RENEGOTIATION
|
||||
+/* OpenSSL-level renegotiation protection. */
|
||||
+#define MODSSL_BLOCKS_RENEG (0)
|
||||
+#else
|
||||
+/* mod_ssl-level renegotiation protection. */
|
||||
+#define MODSSL_BLOCKS_RENEG (1)
|
||||
+#endif
|
||||
+
|
||||
static void ssl_init_ctx_callbacks(server_rec *s,
|
||||
apr_pool_t *p,
|
||||
apr_pool_t *ptemp,
|
||||
@@ -854,7 +869,13 @@ static void ssl_init_ctx_callbacks(server_rec *s,
|
||||
|
||||
SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
|
||||
|
||||
- SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
|
||||
+ /* The info callback is used for debug-level tracing. For OpenSSL
|
||||
+ * versions where SSL_OP_NO_RENEGOTIATION is not available, the
|
||||
+ * callback is also used to prevent use of client-initiated
|
||||
+ * renegotiation. Enable it in either case. */
|
||||
+ if (APLOGdebug(s) || MODSSL_BLOCKS_RENEG) {
|
||||
+ SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
|
||||
+ }
|
||||
|
||||
#ifdef HAVE_TLS_ALPN
|
||||
SSL_CTX_set_alpn_select_cb(ctx, ssl_callback_alpn_select, NULL);
|
||||
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
|
||||
index 836bfdb..0958135 100644
|
||||
--- a/modules/ssl/ssl_engine_io.c
|
||||
+++ b/modules/ssl/ssl_engine_io.c
|
||||
@@ -200,11 +200,13 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
|
||||
apr_bucket *e;
|
||||
int need_flush;
|
||||
|
||||
+#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
outctx->rc = APR_ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* when handshaking we'll have a small number of bytes.
|
||||
* max size SSL will pass us here is about 16k.
|
||||
@@ -458,11 +460,13 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
+#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
inctx->rc = APR_ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
+#endif
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index e217b9d..21f701f 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -992,7 +992,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
|
||||
|
||||
/* Toggle the renegotiation state to allow the new
|
||||
* handshake to proceed. */
|
||||
- sslconn->reneg_state = RENEG_ALLOW;
|
||||
+ modssl_set_reneg_state(sslconn, RENEG_ALLOW);
|
||||
|
||||
SSL_renegotiate(ssl);
|
||||
SSL_do_handshake(ssl);
|
||||
@@ -1019,7 +1019,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
|
||||
*/
|
||||
SSL_peek(ssl, peekbuf, 0);
|
||||
|
||||
- sslconn->reneg_state = RENEG_REJECT;
|
||||
+ modssl_set_reneg_state(sslconn, RENEG_REJECT);
|
||||
|
||||
if (!SSL_is_init_finished(ssl)) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02261)
|
||||
@@ -1078,7 +1078,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
(sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
|
||||
int vmode_inplace, vmode_needed;
|
||||
int change_vmode = FALSE;
|
||||
- int old_state, n, rc;
|
||||
+ int n, rc;
|
||||
|
||||
vmode_inplace = SSL_get_verify_mode(ssl);
|
||||
vmode_needed = SSL_VERIFY_NONE;
|
||||
@@ -1180,8 +1180,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
return HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
- old_state = sslconn->reneg_state;
|
||||
- sslconn->reneg_state = RENEG_ALLOW;
|
||||
modssl_set_app_data2(ssl, r);
|
||||
|
||||
SSL_do_handshake(ssl);
|
||||
@@ -1191,7 +1189,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
*/
|
||||
SSL_peek(ssl, peekbuf, 0);
|
||||
|
||||
- sslconn->reneg_state = old_state;
|
||||
modssl_set_app_data2(ssl, NULL);
|
||||
|
||||
/*
|
||||
@@ -2271,8 +2268,8 @@ static void log_tracing_state(const SSL *ssl, conn_rec *c,
|
||||
/*
|
||||
* This callback function is executed while OpenSSL processes the SSL
|
||||
* handshake and does SSL record layer stuff. It's used to trap
|
||||
- * client-initiated renegotiations, and for dumping everything to the
|
||||
- * log.
|
||||
+ * client-initiated renegotiations (where SSL_OP_NO_RENEGOTIATION is
|
||||
+ * not available), and for dumping everything to the log.
|
||||
*/
|
||||
void ssl_callback_Info(const SSL *ssl, int where, int rc)
|
||||
{
|
||||
@@ -2284,14 +2281,12 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
|
||||
return;
|
||||
}
|
||||
|
||||
- /* With TLS 1.3 this callback may be called multiple times on the first
|
||||
- * negotiation, so the below logic to detect renegotiations can't work.
|
||||
- * Fortunately renegotiations are forbidden starting with TLS 1.3, and
|
||||
- * this is enforced by OpenSSL so there's nothing to be done here.
|
||||
- */
|
||||
-#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
- if (SSL_version(ssl) < TLS1_3_VERSION)
|
||||
-#endif
|
||||
+#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
+ /* With OpenSSL < 1.1.1 (implying TLS v1.2 or earlier), this
|
||||
+ * callback is used to block client-initiated renegotiation. With
|
||||
+ * TLSv1.3 it is unnecessary since renegotiation is forbidden at
|
||||
+ * protocol level. Otherwise (TLSv1.2 with OpenSSL >=1.1.1),
|
||||
+ * SSL_OP_NO_RENEGOTIATION is used to block renegotiation. */
|
||||
{
|
||||
SSLConnRec *sslconn;
|
||||
|
||||
@@ -2316,6 +2311,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
|
||||
sslconn->reneg_state = RENEG_REJECT;
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
|
||||
s = mySrvFromConn(c);
|
||||
if (s && APLOGdebug(s)) {
|
||||
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
|
||||
index 2514407..f4e5ac9 100644
|
||||
--- a/modules/ssl/ssl_private.h
|
||||
+++ b/modules/ssl/ssl_private.h
|
||||
@@ -508,6 +508,16 @@ typedef struct {
|
||||
apr_time_t source_mtime;
|
||||
} ssl_asn1_t;
|
||||
|
||||
+typedef enum {
|
||||
+ RENEG_INIT = 0, /* Before initial handshake */
|
||||
+ RENEG_REJECT, /* After initial handshake; any client-initiated
|
||||
+ * renegotiation should be rejected */
|
||||
+ RENEG_ALLOW, /* A server-initiated renegotiation is taking
|
||||
+ * place (as dictated by configuration) */
|
||||
+ RENEG_ABORT /* Renegotiation initiated by client, abort the
|
||||
+ * connection */
|
||||
+} modssl_reneg_state;
|
||||
+
|
||||
/**
|
||||
* Define the mod_ssl per-module configuration structure
|
||||
* (i.e. the global configuration for each httpd process)
|
||||
@@ -540,18 +550,13 @@ typedef struct {
|
||||
NON_SSL_SET_ERROR_MSG /* Need to set the error message */
|
||||
} non_ssl_request;
|
||||
|
||||
- /* Track the handshake/renegotiation state for the connection so
|
||||
- * that all client-initiated renegotiations can be rejected, as a
|
||||
- * partial fix for CVE-2009-3555. */
|
||||
- enum {
|
||||
- RENEG_INIT = 0, /* Before initial handshake */
|
||||
- RENEG_REJECT, /* After initial handshake; any client-initiated
|
||||
- * renegotiation should be rejected */
|
||||
- RENEG_ALLOW, /* A server-initiated renegotiation is taking
|
||||
- * place (as dictated by configuration) */
|
||||
- RENEG_ABORT /* Renegotiation initiated by client, abort the
|
||||
- * connection */
|
||||
- } reneg_state;
|
||||
+#ifndef SSL_OP_NO_RENEGOTIATION
|
||||
+ /* For OpenSSL < 1.1.1, track the handshake/renegotiation state
|
||||
+ * for the connection to block client-initiated renegotiations.
|
||||
+ * For OpenSSL >=1.1.1, the SSL_OP_NO_RENEGOTIATION flag is used in
|
||||
+ * the SSL * options state with equivalent effect. */
|
||||
+ modssl_reneg_state reneg_state;
|
||||
+#endif
|
||||
|
||||
server_rec *server;
|
||||
SSLDirConfigRec *dc;
|
||||
@@ -1130,6 +1135,9 @@ int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
* the configured ENGINE. */
|
||||
int modssl_is_engine_id(const char *name);
|
||||
|
||||
+/* Set the renegotation state for connection. */
|
||||
+void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state);
|
||||
+
|
||||
#endif /* SSL_PRIVATE_H */
|
||||
/** @} */
|
||||
|
||||
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
|
||||
index 4fa089b..3413d83 100644
|
||||
--- a/modules/ssl/ssl_util_ssl.c
|
||||
+++ b/modules/ssl/ssl_util_ssl.c
|
||||
@@ -504,3 +504,19 @@ char *modssl_SSL_SESSION_id2sz(IDCONST unsigned char *id, int idlen,
|
||||
|
||||
return str;
|
||||
}
|
||||
+
|
||||
+void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state)
|
||||
+{
|
||||
+#ifdef SSL_OP_NO_RENEGOTIATION
|
||||
+ switch (state) {
|
||||
+ case RENEG_ALLOW:
|
||||
+ SSL_clear_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
|
||||
+ break;
|
||||
+ default:
|
||||
+ SSL_set_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
|
||||
+ break;
|
||||
+ }
|
||||
+#else
|
||||
+ sslconn->reneg_state = state;
|
||||
+#endif
|
||||
+}
|
47
httpd-2.4.37-r1878280.patch
Normal file
47
httpd-2.4.37-r1878280.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From ced24e032ebe185a2d885fa309d6de47668ba31e Mon Sep 17 00:00:00 2001
|
||||
From: Yann Ylavic <ylavic@apache.org>
|
||||
Date: Fri, 26 Jun 2020 10:21:19 +0000
|
||||
Subject: [PATCH] Merge r1878280 from trunk:
|
||||
|
||||
mod_proxy_http: don't strip EOS when spooling request body to file.
|
||||
|
||||
To prevent stream_reqbody() from sending the FILE and FLUSH bucket in separate
|
||||
brigades, and thus apr_file_setaside() to trigger if network congestion occurs
|
||||
with the backend, restore the EOS in spool_reqbody_cl() which was stripped
|
||||
when spooling the request body to a file.
|
||||
|
||||
Until APR r1878279 is released (and installed by users), apr_file_setaside()
|
||||
on a temporary file (mktemp) will simply drop the file cleanup, leaking the
|
||||
fd and inode..
|
||||
|
||||
This fixes BZ 64452.
|
||||
|
||||
|
||||
Submitted by: ylavic
|
||||
Reviewed by: ylavic, jorton, rpluem
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1879226 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/proxy/mod_proxy_http.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
|
||||
index e94bf26d412..7a0f063f705 100644
|
||||
--- a/modules/proxy/mod_proxy_http.c
|
||||
+++ b/modules/proxy/mod_proxy_http.c
|
||||
@@ -548,6 +548,14 @@ static int spool_reqbody_cl(proxy_http_req_t *req, apr_off_t *bytes_spooled)
|
||||
e = apr_bucket_immortal_create(CRLF_ASCII, 2, bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(input_brigade, e);
|
||||
}
|
||||
+ if (tmpfile) {
|
||||
+ /* We dropped metadata buckets when spooling to tmpfile,
|
||||
+ * terminate with EOS for stream_reqbody() to flush the
|
||||
+ * whole in one go.
|
||||
+ */
|
||||
+ e = apr_bucket_eos_create(bucket_alloc);
|
||||
+ APR_BRIGADE_INSERT_TAIL(input_brigade, e);
|
||||
+ }
|
||||
return OK;
|
||||
}
|
||||
|
116
httpd-2.4.37-r1878890.patch
Normal file
116
httpd-2.4.37-r1878890.patch
Normal file
@ -0,0 +1,116 @@
|
||||
diff --git a/include/util_ldap.h b/include/util_ldap.h
|
||||
index f7cd736..f401e79 100644
|
||||
--- a/include/util_ldap.h
|
||||
+++ b/include/util_ldap.h
|
||||
@@ -32,7 +32,6 @@
|
||||
#if APR_MAJOR_VERSION < 2
|
||||
/* The LDAP API is currently only present in APR 1.x */
|
||||
#include "apr_ldap.h"
|
||||
-#include "apr_ldap_rebind.h"
|
||||
#else
|
||||
#define APR_HAS_LDAP 0
|
||||
#endif
|
||||
diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c
|
||||
index 08f986c..eecb3f7 100644
|
||||
--- a/modules/ldap/util_ldap.c
|
||||
+++ b/modules/ldap/util_ldap.c
|
||||
@@ -140,6 +140,38 @@ static int util_ldap_handler(request_rec *r)
|
||||
return OK;
|
||||
}
|
||||
|
||||
+/* For OpenLDAP with the 3-arg version of ldap_set_rebind_proc(), use
|
||||
+ * a simpler rebind callback than the implementation in APR-util.
|
||||
+ * Testing for API version >= 3001 appears safe although OpenLDAP
|
||||
+ * 2.1.x (API version = 2004) also has the 3-arg API. */
|
||||
+#if APR_HAS_OPENLDAP_LDAPSDK && defined(LDAP_API_VERSION) && LDAP_API_VERSION >= 3001
|
||||
+
|
||||
+#define uldap_rebind_init(p) APR_SUCCESS /* noop */
|
||||
+
|
||||
+static int uldap_rebind_proc(LDAP *ld, const char *url, ber_tag_t request,
|
||||
+ ber_int_t msgid, void *params)
|
||||
+{
|
||||
+ util_ldap_connection_t *ldc = params;
|
||||
+
|
||||
+ return ldap_bind_s(ld, ldc->binddn, ldc->bindpw, LDAP_AUTH_SIMPLE);
|
||||
+}
|
||||
+
|
||||
+static apr_status_t uldap_rebind_add(util_ldap_connection_t *ldc)
|
||||
+{
|
||||
+ ldap_set_rebind_proc(ldc->ldap, uldap_rebind_proc, ldc);
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#else /* !APR_HAS_OPENLDAP_LDAPSDK */
|
||||
+
|
||||
+#define USE_APR_LDAP_REBIND
|
||||
+#include <apr_ldap_rebind.h>
|
||||
+
|
||||
+#define uldap_rebind_init(p) apr_ldap_rebind_init(p)
|
||||
+#define uldap_rebind_add(ldc) apr_ldap_rebind_add((ldc)->rebind_pool, \
|
||||
+ (ldc)->ldap, (ldc)->binddn, \
|
||||
+ (ldc)->bindpw)
|
||||
+#endif
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -181,6 +213,13 @@ static apr_status_t uldap_connection_unbind(void *param)
|
||||
util_ldap_connection_t *ldc = param;
|
||||
|
||||
if (ldc) {
|
||||
+#ifdef USE_APR_LDAP_REBIND
|
||||
+ /* forget the rebind info for this conn */
|
||||
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
|
||||
+ apr_pool_clear(ldc->rebind_pool);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (ldc->ldap) {
|
||||
if (ldc->r) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, ldc->r, "LDC %pp unbind", ldc);
|
||||
@@ -189,12 +228,6 @@ static apr_status_t uldap_connection_unbind(void *param)
|
||||
ldc->ldap = NULL;
|
||||
}
|
||||
ldc->bound = 0;
|
||||
-
|
||||
- /* forget the rebind info for this conn */
|
||||
- if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
|
||||
- apr_ldap_rebind_remove(ldc->ldap);
|
||||
- apr_pool_clear(ldc->rebind_pool);
|
||||
- }
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
@@ -330,7 +363,7 @@ static int uldap_connection_init(request_rec *r,
|
||||
|
||||
if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
|
||||
/* Now that we have an ldap struct, add it to the referral list for rebinds. */
|
||||
- rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);
|
||||
+ rc = uldap_rebind_add(ldc);
|
||||
if (rc != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, APLOGNO(01277)
|
||||
"LDAP: Unable to add rebind cross reference entry. Out of memory?");
|
||||
@@ -855,6 +888,7 @@ static util_ldap_connection_t *
|
||||
/* whether or not to keep this connection in the pool when it's returned */
|
||||
l->keep = (st->connection_pool_ttl == 0) ? 0 : 1;
|
||||
|
||||
+#ifdef USE_APR_LDAP_REBIND
|
||||
if (l->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
|
||||
if (apr_pool_create(&(l->rebind_pool), l->pool) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01286)
|
||||
@@ -865,6 +899,7 @@ static util_ldap_connection_t *
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (p) {
|
||||
p->next = l;
|
||||
@@ -3051,7 +3086,7 @@ static int util_ldap_post_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
}
|
||||
|
||||
/* Initialize the rebind callback's cross reference list. */
|
||||
- apr_ldap_rebind_init (p);
|
||||
+ (void) uldap_rebind_init(p);
|
||||
|
||||
#ifdef AP_LDAP_OPT_DEBUG
|
||||
if (st->debug_level > 0) {
|
13
httpd-2.4.37-r1879224.patch
Normal file
13
httpd-2.4.37-r1879224.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index c217a0d..d07d0ba 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1947,7 +1947,7 @@ static void modssl_proxy_info_log(conn_rec *c,
|
||||
*cert = info->x509; \
|
||||
CRYPTO_add(&(*cert)->references, +1, CRYPTO_LOCK_X509); \
|
||||
*pkey = info->x_pkey->dec_pkey; \
|
||||
- CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_X509_PKEY)
|
||||
+ CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_EVP_PKEY)
|
||||
#else
|
||||
#define modssl_set_cert_info(info, cert, pkey) \
|
||||
*cert = info->x509; \
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user