import httpd-2.4.37-30.module+el8.3.0+7001+0766b9e7

This commit is contained in:
CentOS Sources 2020-07-10 01:42:37 +00:00 committed by Andrew Lukoshko
commit 25d8915cf3
88 changed files with 12034 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/httpd-2.4.37.tar.bz2

1
.httpd.metadata Normal file
View File

@ -0,0 +1 @@
4a38471de821288b0300148016f2b03dfee8adf2 SOURCES/httpd-2.4.37.tar.bz2

68
SOURCES/00-base.conf Normal file
View 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

3
SOURCES/00-dav.conf Normal file
View 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
SOURCES/00-lua.conf Normal file
View File

@ -0,0 +1 @@
LoadModule lua_module modules/mod_lua.so

23
SOURCES/00-mpm.conf Normal file
View 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
SOURCES/00-optional.conf Normal file
View 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
SOURCES/00-proxy.conf Normal file
View 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

View 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
SOURCES/00-ssl.conf Normal file
View File

@ -0,0 +1 @@
LoadModule ssl_module modules/mod_ssl.so

2
SOURCES/00-systemd.conf Normal file
View File

@ -0,0 +1,2 @@
# This file configures systemd module:
LoadModule systemd_module modules/mod_systemd.so

14
SOURCES/01-cgi.conf Normal file
View 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
SOURCES/01-ldap.conf Normal file
View 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
SOURCES/01-session.conf Normal file
View 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

View 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
SOURCES/README.confd Normal file
View 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
SOURCES/README.confmod Normal file
View 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.

View File

@ -0,0 +1,2 @@
#!/bin/sh
exec /sbin/apachectl configtest "$@"

View File

@ -0,0 +1,2 @@
#!/bin/sh
exec /sbin/apachectl graceful "$@"

24
SOURCES/config.layout Normal file
View 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>

View 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

View 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
-->

View 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=

View 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

View 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

View 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));

View 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);
}

View 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;

View 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

View 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);

View 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

View 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"),

View 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;
}

View 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)

View 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 ""'

View 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">

View 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;

View 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. */

View 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 ?

View 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)

View 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;
}

View 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, &params, 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,

View 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) {

View 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;
}

View 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;
}

View 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,
+};

View 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;
}
}

View 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;
}
}

View 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);

View 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 }
};

View 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), "&nbsp;", 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));

View 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,

View 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);
}

View 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);

View 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;

View 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");

View 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;

View 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;
}

View 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

View 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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 */

View 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;

View File

@ -0,0 +1,45 @@
# ./pullrev.sh 1851471
http://svn.apache.org/viewvc?view=revision&revision=1851471
--- httpd-2.4.37/modules/ssl/ssl_engine_io.c
+++ httpd-2.4.37/modules/ssl/ssl_engine_io.c
@@ -200,6 +200,8 @@
apr_bucket *e;
int need_flush;
+ BIO_clear_retry_flags(bio);
+
/* Abort early if the client has initiated a renegotiation. */
if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
outctx->rc = APR_ECONNABORTED;
@@ -206,12 +208,6 @@
return -1;
}
- /* 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);
@@ -458,6 +454,8 @@
if (!in)
return 0;
+ BIO_clear_retry_flags(bio);
+
/* Abort early if the client has initiated a renegotiation. */
if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
inctx->rc = APR_ECONNABORTED;
@@ -464,8 +462,6 @@
return -1;
}
- BIO_clear_retry_flags(bio);
-
if (!inctx->bb) {
inctx->rc = APR_EOF;
return -1;

View 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 aencryption 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,

View 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];

View File

@ -0,0 +1,194 @@
diff --git a/docs/manual/mod/mod_session.html.en b/docs/manual/mod/mod_session.html.en
index 6834f8e..9f8301f 100644
--- a/docs/manual/mod/mod_session.html.en
+++ b/docs/manual/mod/mod_session.html.en
@@ -82,6 +82,7 @@
<li><img alt="" src="../images/down.gif" /> <a href="#sessionheader">SessionHeader</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sessioninclude">SessionInclude</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sessionmaxage">SessionMaxAge</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#sessionexpiryupdateinterval">SessionExpiryUpdateInterval</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__&amp;list_id=144532&amp;product=Apache%20httpd-2&amp;query_format=specific&amp;order=changeddate%20DESC%2Cpriority%2Cbug_severity&amp;component=mod_session">Known issues</a></li><li><a href="https://bz.apache.org/bugzilla/enter_bug.cgi?product=Apache%20httpd-2&amp;component=mod_session">Report a bug</a></li></ul><h3>See also</h3>
<ul class="seealso">
@@ -482,6 +483,37 @@ AuthName realm
<p>Setting the maxage to zero disables session expiry.</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="SessionExpiryUpdateInterval" id="sessionexpiryupdateinterval">SessionExpiryUpdateInterval</a> <a name="sessionexpiryupdateinterval" id="sessionexpiryupdateinterval">Directive</a></h2>
+<table class="directive">
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Define the number of seconds a session's expiry may change without the session being updated</td></tr>
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>SessionExpiryUpdateInterval <var>interval</var></code></td></tr>
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>SessionExpiryUpdateInterval 0 (always update)</code></td></tr>
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_session</td></tr>
+</table>
+ <p>The <code class="directive">SessionExpiryUpdateInterval</code> directive allows
+ sessions to avoid the cost associated with writing the session each request
+ when only the expiry time has changed. This can be used to make a website
+ more efficient or reduce load on a database when using
+ <module>mod_session_dbd</module>. The session is always written if the data
+ stored in the session has changed or the expiry has changed by more than the
+ configured interval.</p>
+
+ <p>Setting the interval to zero disables this directive, and the session
+ expiry is refreshed for each request.</p>
+
+ <p>This directive only has an effect when combined with <code class="directive"><a href="../mod/mod_session.html#sessionmaxage">SessionMaxAge</a></code> to enable session
+ expiry. Sessions without an expiry are only written when the data stored in
+ the session has changed.</p>
+
+ <div class="warning"><h3>Warning</h3>
+ <p>Because the session expiry may not be refreshed with each request, it's
+ possible for sessions to expire up to <var>interval</var> seconds early.
+ Using a small interval usually provides sufficient savings while having a
+ minimal effect on expiry resolution.</p></div>
+
</div>
</div>
<div class="bottomlang">
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
index d517020..10e6396 100644
--- a/modules/session/mod_session.c
+++ b/modules/session/mod_session.c
@@ -177,6 +177,7 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z)
{
if (z) {
apr_time_t now = apr_time_now();
+ apr_time_t initialExpiry = z->expiry;
int rv = 0;
session_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
@@ -207,6 +208,17 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z)
z->expiry = now + z->maxage * APR_USEC_PER_SEC;
}
+ /* don't save if the only change is the expiry by a small amount */
+ if (!z->dirty && dconf->expiry_update_time
+ && (z->expiry - initialExpiry < dconf->expiry_update_time)) {
+ return APR_SUCCESS;
+ }
+
+ /* also don't save sessions that didn't change at all */
+ if (!z->dirty && !z->maxage) {
+ return APR_SUCCESS;
+ }
+
/* encode the session */
rv = ap_run_session_encode(r, z);
if (OK != rv) {
@@ -553,6 +565,10 @@ static void *merge_session_dir_config(apr_pool_t * p, void *basev, void *addv)
new->env_set = add->env_set || base->env_set;
new->includes = apr_array_append(p, base->includes, add->includes);
new->excludes = apr_array_append(p, base->excludes, add->excludes);
+ new->expiry_update_time = (add->expiry_update_set == 0)
+ ? base->expiry_update_time
+ : add->expiry_update_time;
+ new->expiry_update_set = add->expiry_update_set || base->expiry_update_set;
return new;
}
@@ -622,6 +638,21 @@ static const char *add_session_exclude(cmd_parms * cmd, void *dconf, const char
return NULL;
}
+static const char *
+ set_session_expiry_update(cmd_parms * parms, void *dconf, const char *arg)
+{
+ session_dir_conf *conf = dconf;
+
+ conf->expiry_update_time = atoi(arg);
+ if (conf->expiry_update_time < 0) {
+ return "SessionExpiryUpdateInterval must be positive or nul";
+ }
+ conf->expiry_update_time = apr_time_from_sec(conf->expiry_update_time);
+ conf->expiry_update_set = 1;
+
+ return NULL;
+}
+
static const command_rec session_cmds[] =
{
@@ -637,6 +668,9 @@ static const command_rec session_cmds[] =
"URL prefixes to include in the session. Defaults to all URLs"),
AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, RSRC_CONF|OR_AUTHCFG,
"URL prefixes to exclude from the session. Defaults to no URLs"),
+ AP_INIT_TAKE1("SessionExpiryUpdateInterval", set_session_expiry_update, NULL, RSRC_CONF|OR_AUTHCFG,
+ "time interval for which a session's expiry time may change "
+ "without having to be rewritten. Zero to disable"),
{NULL}
};
diff --git a/modules/session/mod_session.h b/modules/session/mod_session.h
index a6dd5e9..bdeb532 100644
--- a/modules/session/mod_session.h
+++ b/modules/session/mod_session.h
@@ -115,6 +115,9 @@ typedef struct {
* URLs included if empty */
apr_array_header_t *excludes; /* URL prefixes to be excluded. No
* URLs excluded if empty */
+ apr_time_t expiry_update_time; /* seconds the session expiry may change and
+ * not have to be rewritten */
+ int expiry_update_set;
} session_dir_conf;
/**
diff --git a/modules/session/mod_session_cookie.c b/modules/session/mod_session_cookie.c
index 6a02322..4aa75e4 100644
--- a/modules/session/mod_session_cookie.c
+++ b/modules/session/mod_session_cookie.c
@@ -60,9 +60,6 @@ static apr_status_t session_cookie_save(request_rec * r, session_rec * z)
session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config,
&session_cookie_module);
- /* don't cache auth protected pages */
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
-
/* create RFC2109 compliant cookie */
if (conf->name_set) {
if (z->encoded && z->encoded[0]) {
@@ -162,6 +159,9 @@ static apr_status_t session_cookie_load(request_rec * r, session_rec ** z)
/* put the session in the notes so we don't have to parse it again */
apr_table_setn(m->notes, note, (char *)zz);
+ /* don't cache auth protected pages */
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private");
+
return OK;
}
diff --git a/modules/session/mod_session_dbd.c b/modules/session/mod_session_dbd.c
index 0be7306..f683da2 100644
--- a/modules/session/mod_session_dbd.c
+++ b/modules/session/mod_session_dbd.c
@@ -245,6 +245,9 @@ static apr_status_t session_dbd_load(request_rec * r, session_rec ** z)
/* put the session in the notes so we don't have to parse it again */
apr_table_setn(m->notes, note, (char *)zz);
+ /* don't cache pages with a session */
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private");
+
return OK;
}
@@ -409,9 +412,6 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z)
if (conf->name_set || conf->name2_set) {
char *oldkey = NULL, *newkey = NULL;
- /* don't cache pages with a session */
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
-
/* if the session is new or changed, make a new session ID */
if (z->uuid) {
oldkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
@@ -458,7 +458,7 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z)
else if (conf->peruser) {
/* don't cache pages with a session */
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private");
if (r->user) {
ret = dbd_save(r, r->user, r->user, z->encoded, z->expiry);

View File

@ -0,0 +1,123 @@
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 1d201d9..0c4bf1f 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -75,6 +75,10 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
mc->stapling_refresh_mutex = NULL;
#endif
+#ifdef HAVE_OPENSSL_KEYLOG
+ mc->keylog_file = NULL;
+#endif
+
apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
apr_pool_cleanup_null,
pool);
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index ef631c1..b286053 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -437,6 +437,28 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
init_bio_methods();
#endif
+#ifdef HAVE_OPENSSL_KEYLOG
+ {
+ const char *logfn = getenv("SSLKEYLOGFILE");
+
+ if (logfn) {
+ rv = apr_file_open(&mc->keylog_file, logfn,
+ APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_APPEND|APR_FOPEN_LARGEFILE,
+ APR_FPROT_UREAD|APR_FPROT_UWRITE,
+ mc->pPool);
+ if (rv) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s, APLOGNO(10226)
+ "Could not open log file '%s' configured via SSLKEYLOGFILE",
+ logfn);
+ return rv;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(10227)
+ "Init: Logging SSL private key material to %s", logfn);
+ }
+ }
+#endif
+
return OK;
}
@@ -796,6 +818,12 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
* https://github.com/openssl/openssl/issues/7178 */
SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
#endif
+
+#ifdef HAVE_OPENSSL_KEYLOG
+ if (mctx->sc->mc->keylog_file) {
+ SSL_CTX_set_keylog_callback(ctx, modssl_callback_keylog);
+ }
+#endif
return APR_SUCCESS;
}
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index 6611610..7058865 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -2719,3 +2719,17 @@ int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
}
#endif /* HAVE_SRP */
+
+
+#ifdef HAVE_OPENSSL_KEYLOG
+/* Callback used with SSL_CTX_set_keylog_callback. */
+void modssl_callback_keylog(const SSL *ssl, const char *line)
+{
+ conn_rec *conn = SSL_get_app_data(ssl);
+ SSLSrvConfigRec *sc = mySrvConfig(conn->base_server);
+
+ if (sc && sc->mc->keylog_file) {
+ apr_file_printf(sc->mc->keylog_file, "%s\n", line);
+ }
+}
+#endif
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 0fac5d1..2514407 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -250,6 +250,10 @@ void free_bio_methods(void);
#endif
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define HAVE_OPENSSL_KEYLOG
+#endif
+
/* mod_ssl headers */
#include "ssl_util_ssl.h"
@@ -617,6 +621,12 @@ typedef struct {
apr_global_mutex_t *stapling_cache_mutex;
apr_global_mutex_t *stapling_refresh_mutex;
#endif
+
+#ifdef HAVE_OPENSSL_KEYLOG
+ /* Used for logging if SSLKEYLOGFILE is set at startup. */
+ apr_file_t *keylog_file;
+#endif
+
} SSLModConfigRec;
/** Structure representing configured filenames for certs and keys for
@@ -970,6 +980,11 @@ int ssl_stapling_init_cert(server_rec *, apr_pool_t *, apr_pool_t *,
int ssl_callback_SRPServerParams(SSL *, int *, void *);
#endif
+#ifdef HAVE_OPENSSL_KEYLOG
+/* Callback used with SSL_CTX_set_keylog_callback. */
+void modssl_callback_keylog(const SSL *ssl, const char *line);
+#endif
+
/** I/O */
void ssl_io_filter_init(conn_rec *, request_rec *r, SSL *);
void ssl_io_filter_register(apr_pool_t *);

View File

@ -0,0 +1,98 @@
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 55c237e..5467d23 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -119,7 +119,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
mctx->ticket_key = NULL;
#endif
- mctx->protocol = SSL_PROTOCOL_DEFAULT;
+ mctx->protocol = SSL_PROTOCOL_NONE;
mctx->protocol_set = 0;
mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET;
@@ -262,6 +262,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
{
if (add->protocol_set) {
mrg->protocol = add->protocol;
+ mrg->protocol_set = 1;
}
else {
mrg->protocol = base->protocol;
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index e3f62fe..31fc0e6 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -568,6 +568,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL;
char *cp;
int protocol = mctx->protocol;
+ int protocol_set = mctx->protocol_set;
SSLSrvConfigRec *sc = mySrvConfig(s);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
int prot;
@@ -577,12 +578,18 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
* Create the new per-server SSL context
*/
if (protocol == SSL_PROTOCOL_NONE) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231)
- "No SSL protocols available [hint: SSLProtocol]");
- return ssl_die(s);
- }
+ if (protocol_set) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231)
+ "No SSL protocols available [hint: SSLProtocol]");
+ return ssl_die(s);
+ }
- cp = apr_pstrcat(p,
+ ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
+ "Using OpenSSL/system default SSL/TLS protocols");
+ cp = "default";
+ }
+ else {
+ cp = apr_pstrcat(p,
#ifndef OPENSSL_NO_SSL3
(protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
#endif
@@ -595,7 +602,8 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
#endif
#endif
NULL);
- cp[strlen(cp)-2] = NUL;
+ cp[strlen(cp)-2] = NUL;
+ }
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
"Creating new SSL context (protocols: %s)", cp);
@@ -696,13 +704,15 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
prot = SSL3_VERSION;
#endif
} else {
- SSL_CTX_free(ctx);
- mctx->ssl_ctx = NULL;
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(03378)
- "No SSL protocols available [hint: SSLProtocol]");
- return ssl_die(s);
+ if (protocol_set) {
+ SSL_CTX_free(ctx);
+ mctx->ssl_ctx = NULL;
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(03378)
+ "No SSL protocols available [hint: SSLProtocol]");
+ return ssl_die(s);
+ }
}
- SSL_CTX_set_max_proto_version(ctx, prot);
+ if (protocol != SSL_PROTOCOL_NONE) SSL_CTX_set_max_proto_version(ctx, prot);
/* Next we scan for the minimal protocol version we should provide,
* but we do not allow holes between max and min */
@@ -726,7 +736,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
prot = SSL3_VERSION;
}
#endif
- SSL_CTX_set_min_proto_version(ctx, prot);
+ if (protocol != SSL_PROTOCOL_NONE) SSL_CTX_set_min_proto_version(ctx, prot);
#endif /* if OPENSSL_VERSION_NUMBER < 0x10100000L */
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE

View File

@ -0,0 +1,12 @@
[Unit]
Description=One-time temporary TLS key generation for httpd.service
Documentation=man:httpd-init.service(8)
ConditionPathExists=|!/etc/pki/tls/certs/localhost.crt
ConditionPathExists=|!/etc/pki/tls/private/localhost.key
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/libexec/httpd-ssl-gencerts

39
SOURCES/httpd-ssl-gencerts Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/bash
set -e
FQDN=`hostname`
ssldotconf=/etc/httpd/conf.d/ssl.conf
if test -f /etc/pki/tls/certs/localhost.crt -a \
-f /etc/pki/tls/private/localhost.key; then
exit 0
fi
if test -f /etc/pki/tls/certs/localhost.crt -a \
! -f /etc/pki/tls/private/localhost.key; then
echo "Missing certificate key!"
exit 1
fi
if test ! -f /etc/pki/tls/certs/localhost.crt -a \
-f /etc/pki/tls/private/localhost.key; then
echo "Missing certificate, but key is present!"
exit 1
fi
if ! test -f ${ssldotconf} || \
! grep -q '^SSLCertificateFile /etc/pki/tls/certs/localhost.crt' ${ssldotconf} || \
! grep -q '^SSLCertificateKeyFile /etc/pki/tls/private/localhost.key' ${ssldotconf}; then
# Non-default configuration, do nothing.
exit 0
fi
sscg -q \
--cert-file /etc/pki/tls/certs/localhost.crt \
--cert-key-file /etc/pki/tls/private/localhost.key \
--ca-file /etc/pki/tls/certs/localhost.crt \
--lifetime 365 \
--hostname $FQDN \
--email root@$FQDN

3
SOURCES/httpd-ssl-pass-dialog Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
exec /bin/systemd-ask-password "Enter TLS private key passphrase for $1 ($2) : "

356
SOURCES/httpd.conf Normal file
View File

@ -0,0 +1,356 @@
#
# This is the main Apache HTTP server configuration file. It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
# for a discussion of each configuration directive.
#
# See the httpd.conf(5) man page for more information on this configuration,
# and httpd.service(8) on using and configuring the httpd service.
#
# Do NOT simply read the instructions in here without understanding
# what they do. They're here only as hints or reminders. If you are unsure
# consult the online docs. You have been warned.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path. If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
# with ServerRoot set to '/www' will be interpreted by the
# server as '/www/log/access_log', where as '/log/access_log' will be
# interpreted as '/log/access_log'.
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path. If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used. If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
ServerRoot "/etc/httpd"
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
Include conf.modules.d/*.conf
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User apache
Group apache
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin@your-domain.com
#
ServerAdmin root@localhost
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80
#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
AllowOverride none
Require all denied
</Directory>
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/var/www/html"
#
# Relax access to content within /var/www.
#
<Directory "/var/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
# Further relax access to the default document root:
<Directory "/var/www/html">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
# for more information.
#
Options Indexes FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
AllowOverride None
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ".ht*">
Require all denied
</Files>
#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog "logs/error_log"
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn
<IfModule log_config_module>
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
#
#CustomLog "logs/access_log" common
#
# If you prefer a logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
#
# Redirect: Allows you to tell clients about documents that used to
# exist in your server's namespace, but do not anymore. The client
# will make a new request for the document at its new location.
# Example:
# Redirect permanent /foo http://www.example.com/bar
#
# Alias: Maps web paths into filesystem paths and is used to
# access content that does not live under the DocumentRoot.
# Example:
# Alias /webpath /full/filesystem/path
#
# If you include a trailing / on /webpath then the server will
# require it to be present in the URL. You will also likely
# need to provide a <Directory> section to allow access to
# the filesystem path.
#
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the target directory are treated as applications and
# run by the server when requested rather than as documents sent to the
# client. The same rules about trailing "/" apply to ScriptAlias
# directives as to Alias.
#
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
#
# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule mime_module>
#
# TypesConfig points to the file containing the list of mappings from
# filename extension to MIME-type.
#
TypesConfig /etc/mime.types
#
# AddType allows you to add to or override the MIME configuration
# file specified in TypesConfig for specific file types.
#
#AddType application/x-gzip .tgz
#
# AddEncoding allows you to have certain browsers uncompress
# information on the fly. Note: Not all browsers support this.
#
#AddEncoding x-compress .Z
#AddEncoding x-gzip .gz .tgz
#
# If the AddEncoding directives above are commented-out, then you
# probably should define those extensions to indicate media types:
#
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
#
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
# For type maps (negotiated resources):
#AddHandler type-map var
#
# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
</IfModule>
#
# Specify a default charset for all content served; this enables
# interpretation of all content as UTF-8 by default. To use the
# default browser choice (ISO-8859-1), or to allow the META tags
# in HTML content to override this choice, comment out this
# directive:
#
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type. The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
MIMEMagicFile conf/magic
</IfModule>
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#
# EnableMMAP and EnableSendfile: On systems that support it,
# memory-mapping or the sendfile syscall may be used to deliver
# files. This usually improves server performance, but must
# be turned off when serving from networked-mounted
# filesystems or if support for these functions is otherwise
# broken on your system.
# Defaults if commented: EnableMMAP On, EnableSendfile Off
#
#EnableMMAP off
EnableSendfile on
# Supplemental configuration
#
# Load config files in the "/etc/httpd/conf.d" directory, if any.
IncludeOptional conf.d/*.conf

259
SOURCES/httpd.conf.xml Normal file
View File

@ -0,0 +1,259 @@
<?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 governing permissions and
limitations under the License.
-->
<refentry>
<refentryinfo>
<title>httpd.conf</title>
<productname>httpd</productname>
<author><contrib>Author</contrib><surname>Orton</surname><firstname>Joe</firstname><email>jorton@redhat.com</email></author>
</refentryinfo>
<refmeta>
<refentrytitle>httpd.conf</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>httpd.conf</refname>
<refpurpose>Configuration files for httpd</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para>
<filename>/etc/httpd/conf/httpd.conf</filename>,
<filename>/etc/httpd/conf.modules.d</filename>,
<filename>/etc/httpd/conf.d</filename>
</para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>The main configuration file for the <command>httpd</command> daemon is
<filename>/etc/httpd/conf/httpd.conf</filename>. The syntax of
this file is described at <ulink
url="https://httpd.apache.org/docs/2.4/configuring.html"/>, and
the full set of available directives is listed at <ulink
url="https://httpd.apache.org/docs/2.4/mod/directives.html"/>.
</para>
<refsect2>
<title>Configuration structure</title>
<para>The main configuration file
(<filename>httpd.conf</filename>) sets up various defaults and
includes configuration files from two directories -
<filename>/etc/httpd/conf.modules.d</filename> and
<filename>/etc/httpd/conf.d</filename>. Packages containing
loadable modules (like <option>mod_ssl.so</option>) place files
in the <filename>conf.modules.d</filename> directory with the
appropriate <option>LoadModule</option> directive so that module
is loaded by default.</para>
<para>Some notable configured defaults are:.</para>
<variablelist>
<varlistentry>
<term><option>DocumentRoot @DOCROOT@/html</option></term>
<listitem><para>The default document root from which content
is served.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>Listen 80</option></term>
<listitem><para>The daemon lists on TCP port 80.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>ErrorLog "logs/error_log"</option></term>
<listitem><para>Error messages are logged to
<filename>@LOGDIR@/error_log</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>ScriptAlias /cgi-bin/ "@DOCROOT@/cgi-bin/"</option></term>
<listitem><para>CGI scripts are served via the URL-path <option>/cgi-bin/</option>.</para></listitem>
</varlistentry>
</variablelist>
<para>To remove any of the default configuration provided in
separate files covered below, replace that file with an empty
file rather than removing it from the filesystem, otherwise it
may be restored to the original when the package which provides
it is upgraded.</para>
</refsect2>
<refsect2>
<title>MPM configuration</title>
<para>The configuration file at
<filename>/etc/httpd/conf.modules.d/00-mpm.conf</filename> is
used to select the multi-processing module (MPM), which governs
how <command>httpd</command> divides work between processes
and/or threads at run-time. Exactly one
<option>LoadModule</option> directive must be uncommented in
this file; by default the <option>@MPM@</option> MPM is enabled.
For more information on MPMs, see <ulink
url="https://httpd.apache.org/docs/2.4/mpm.html"/>.</para>
<para>If using the <emphasis>prefork</emphasis> MPM, the
"httpd_graceful_shutdown" SELinux boolean should also be
enabled, since with this MPM, httpd needs to establish TCP
connections to local ports to successfully complete a graceful
restart or shutdown. This boolean can be enabled by running the
command: <command>semanage boolean -m --on
httpd_graceful_shutdown</command></para>
</refsect2>
<refsect2>
<title>Module configuration files</title>
<para>Module configuration files are provided in the
<filename>/etc/httpd/conf.modules.d/</filename> directory. Filenames
in this directory are by convention prefixed with two digit numeric
prefix to ensure they are processed in the desired order. Core
modules provide with the <command>httpd</command> package are
loaded by files with a <option>0x-</option> prefix to ensure
these are loaded first. Only filenames with a
<option>.conf</option> suffix in this directory will be
processed.</para>
<para>Other provided configuration files are listed below.
<variablelist>
<varlistentry>
<term><filename>/etc/httpd/conf.modules.d/00-base.conf</filename></term>
<listitem><para>The set of core modules included with
<command>httpd</command> which are all loaded by
default.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/httpd/conf.modules.d/00-optional.conf</filename></term>
<listitem><para>The set of non-core modules included with
<command>httpd</command> which are <emphasis>not</emphasis>
loaded by default.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/httpd/conf.modules.d/00-systemd.conf</filename></term>
<listitem><para>This file loads <option>mod_systemd</option>
which is necessary for the correct operation of the
<command>httpd.service</command> service, and should not be
removed or disabled.</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
<refsect2>
<title>Other configuration files</title>
<para>Default module configuration files and site-specific
configuration files are loaded from the
<filename>/etc/httpd/conf.d/</filename> directory. Only files
with a <option>.conf</option> suffix will be loaded. The
following files are provided:
<variablelist>
<varlistentry>
<term><filename>/etc/httpd/conf.d/userdir.conf</filename></term>
<listitem><para>This file gives an example configuration for
<option>mod_userdir</option> to map URLs such as
<option>http://localhost/~jim/</option> to
<filename>/home/jim/public_html/</filename>. Userdir mapping
is disabled by default.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/httpd/conf.d/autoindex.conf</filename></term>
<listitem><para>This file provides the default configuration
for <option>mod_autoindex</option> which generates HTML
directory listings when enabled. It also makes file icon
image files available at the <option>/icons/</option>
URL-path.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/httpd/conf.d/welcome.conf</filename></term>
<listitem><para>This file enables a "welcome page" at
<option>http://localhost/</option> if no content is present
in the default documentation root
<filename>/var/www/html</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/httpd/conf.d/ssl.conf</filename> (present only if <option>mod_ssl</option> is installed)</term>
<listitem><para>This file configures a TLS
<option>VirtualHost</option> listening on port
<option>443</option>. If the default configuration is used,
the referenced test certificate and private key are
generated the first time <command>httpd.service</command> is
started; see
<citerefentry><refentrytitle>httpd-init.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information.</para></listitem>
</varlistentry>
</variablelist></para>
</refsect2>
<refsect2>
<title>Instantiated services</title>
<para>As an alternative to (or in addition to) the
<command>httpd.service</command> unit, the instantiated template
service <command>httpd@.service</command> unit file can be used,
which starts <command>httpd</command> using a different
configuration file to the default. For example,
<command>systemctl start httpd@foobar.service</command> will
start httpd using the configuration file
<filename>/etc/httpd/conf/foobar.conf</filename>. See <citerefentry><refentrytitle>httpd@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> for more information.</para>
</refsect2>
</refsect1>
<refsect1>
<title>Files</title>
<para>
<filename>/etc/httpd/conf/httpd.conf</filename>,
<filename>/etc/httpd/conf.d</filename>,
<filename>/etc/httpd/conf.modules.d</filename>
</para>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>httpd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>httpd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<ulink url="https://httpd.apache.org/docs/2.4/configuring.html"/>,
<ulink url="https://httpd.apache.org/docs/2.4/mod/directives.html"/>
</para>
</refsect1>
</refentry>
<!-- LocalWords: systemd PidFile
-->

9
SOURCES/httpd.logrotate Normal file
View File

@ -0,0 +1,9 @@
/var/log/httpd/*log {
missingok
notifempty
sharedscripts
delaycompress
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}

32
SOURCES/httpd.service Normal file
View File

@ -0,0 +1,32 @@
# See httpd.service(8) for more information on using the httpd service.
# Modifying this file in-place is not recommended, because changes
# will be overwritten during package upgrades. To customize the
# behaviour, run "systemctl edit httpd" to create an override unit.
# For example, to pass additional options (such as -D definitions) to
# the httpd binary at startup, create an override unit (as is done by
# systemctl edit) and enter the following:
# [Service]
# Environment=OPTIONS=-DMY_DEFINE
[Unit]
Description=The Apache HTTP Server
Wants=httpd-init.service
After=network.target remote-fs.target nss-lookup.target httpd-init.service
Documentation=man:httpd.service(8)
[Service]
Type=notify
Environment=LANG=C
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target

332
SOURCES/httpd.service.xml Normal file
View File

@ -0,0 +1,332 @@
<?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 governing permissions and
limitations under the License.
-->
<refentry>
<refentryinfo>
<title>httpd systemd units</title>
<productname>httpd</productname>
<author><contrib>Author</contrib><surname>Orton</surname><firstname>Joe</firstname><email>jorton@redhat.com</email></author>
</refentryinfo>
<refmeta>
<refentrytitle>httpd.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>httpd.service</refname>
<refname>httpd@.service</refname>
<refname>httpd.socket</refname>
<refname>httpd-init.service</refname>
<refpurpose>httpd unit files for systemd</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para>
<filename>/usr/lib/systemd/system/httpd.service</filename>,
<filename>/usr/lib/systemd/system/httpd@.service</filename>,
<filename>/usr/lib/systemd/system/httpd-init.service</filename>,
<filename>/usr/lib/systemd/system/httpd.socket</filename>
</para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>This manual page describes the <command>systemd</command>
unit files used to integrate the <command>httpd</command> daemon
with <command>systemd</command>. Two main unit files are
available: <command>httpd.service</command> allows the
<command>httpd</command> daemon to be run as a system service, and
<command>httpd.socket</command> allows httpd to be started via
socket-based activation. Most systems will use
<command>httpd.service</command>.</para>
<para>The <command>apachectl</command> command has been modified
to invoke <command>systemctl</command> for most uses, so for
example, running <command>apachectl start</command> is equivalent
to running <command>systemctl start httpd.service</command>. This
ensures that the running httpd daemon is tracked and managed by
<command>systemd</command>. In contrast, running
<command>httpd</command> directly from a root shell will start the
service outside of <command>systemd</command>; in this case,
default security restrictions described below (including, but not
limited to, SELinux) will not be enforced.</para>
<refsect2>
<title>Changing default behaviour</title>
<para>To change the default behaviour of the httpd service, an
<emphasis>over-ride</emphasis> file should be created, rather
than changing
<filename>/usr/lib/systemd/system/httpd.service</filename>
directly, since such changes would be lost over package
upgrades. Running <command>systemctl edit
httpd.service</command> or <command>systemctl edit
httpd.socket</command> as root will create a drop-in file (in
the former case, in
<filename>/etc/systemd/system/httpd.service.d</filename>) which
over-rides the system defaults.</para>
<para>For example, to set the <option>LD_LIBRARY_PATH</option>
environment variable for the daemon, run <command>systemctl edit
httpd.service</command> and enter:
<programlisting>[Service]
Environment=LD_LIBRARY_PATH=/opt/vendor/lib</programlisting></para>
</refsect2>
<refsect2>
<title>Starting the service at boot time</title>
<para>The httpd.service and httpd.socket units are
<emphasis>disabled</emphasis> by default. To start the httpd
service at boot time, run: <command>systemctl enable
httpd.service</command>. In the default configuration, the
httpd daemon will accept connections on port 80 (and, if mod_ssl
is installed, TLS connections on port 443) for any configured
IPv4 or IPv6 address.</para>
<para>If httpd is configured to depend on any specific IP
address (for example, with a "Listen" directive) which may only
become available during start-up, or if httpd depends on other
services (such as a database daemon), the service
<emphasis>must</emphasis> be configured to ensure correct
start-up ordering.</para>
<para>For example, to ensure httpd is only running after all
configured network interfaces are configured, create a drop-in
file (as described above) with the following section:
<programlisting>[Unit]
After=network-online.target
Wants=network-online.target</programlisting>
See <ulink
url="https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/"/>
for more information on start-up ordering with systemd.</para>
</refsect2>
<refsect2>
<title>SSL/TLS certificate generation</title>
<para>The <command>httpd-init.service</command> unit is provided
with the mod_ssl package. This oneshot unit automatically
creates a TLS server certificate and key (using a generated
self-signed CA certificate and key) for testing purposes before
httpd is started. To inhibit certificate generation, use
<command>systemctl mask httpd-init.service</command> after
installing mod_ssl, and adjust the mod_ssl configuration to use
an appropriate certificate and key.</para>
</refsect2>
<refsect2>
<title>Reloading and stopping the service</title>
<para>When running <command>systemctl reload
httpd.service</command>, a <emphasis>graceful</emphasis>
restart is used, which sends a signal to the httpd parent
process to reload the configuration and re-open log files. Any
children with open connections at the time of reload will
terminate only once they have completed serving requests. This
prevents users of the server seeing errors (or potentially
losing data) due to the reload, but means some there is some
delay before any configuration changes take effect for all
users.</para>
<para>Similarly, a <emphasis>graceful stop</emphasis> is used
when <command>systemctl stop httpd.service</command> is run,
which terminates the server only once active connections have
been processed.</para>
<para>To "ungracefully" stop the server without waiting for
requests to complete, use <command>systemctl kill
--kill-who=main httpd</command>; similarly to "ungracefully"
reload the configuration, use <command>systemctl kill
--kill-who=main --signal=HUP httpd</command>.</para>
</refsect2>
<refsect2>
<title>Automated service restarts</title>
<para>System packages (including the httpd package itself) may
restart the httpd service automatically after packages are
upgraded, installed, or removed. This is done using the
<command>systemctl reload httpd.service</command>, which
produces a <emphasis>graceful</emphasis> restart by default as
described above.</para>
<para>To suppress automatic reloads entirely, create the file
<filename>/etc/sysconfig/httpd-disable-posttrans</filename>.</para>
</refsect2>
<refsect2>
<title>Changing the default MPM (Multi-Processing Module)</title>
<para>httpd offers a choice of multi-processing modules (MPMs),
which can be configured in
<filename>/etc/httpd/conf.modules.d/00-mpm.conf</filename>.
See
<citerefentry><refentrytitle>httpd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information on changing the MPM.</para>
</refsect2>
<refsect2>
<title>systemd integration and mod_systemd</title>
<para>The httpd service uses the <option>notify</option> systemd
service type. The <literal>mod_systemd</literal> module must be
loaded (as in the default configuration) for this to work
correctly - the service will fail if this module is not
loaded. <literal>mod_systemd</literal> also makes worker and
request statistics available when running <command>systemctl status
httpd</command>. See
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information on systemd service types.</para>
</refsect2>
<refsect2>
<title>Security and SELinux</title>
<para>The default SELinux policy restricts the httpd service in
various ways. For example, the default policy limits the ports
to which httpd can bind (using the <literal>Listen</literal>
directive), which parts of the filesystem can be accessed, and
whether outgoing TCP connections are possible. Many of these
restrictions can be relaxed or adjusted by using
<command>semanage</command> to change booleans or other
types. See
<citerefentry><refentrytitle>httpd_selinux</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information.</para>
<para>The httpd service enables <emphasis>PrivateTmp</emphasis>
by default. The <filename>/tmp</filename> and
<filename>/var/tmp</filename> directories available within the
httpd process (and CGI scripts, etc) are not shared by other
processes. See
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information.</para>
</refsect2>
<refsect2>
<title>Socket activation</title>
<para>Socket activation (see
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information) can be used with <command>httpd</command>
by enabling the <command>httpd.socket</command> unit. The
<command>httpd</command> listener configuration must exactly
match the <literal>ListenStream</literal> options configured for
the <command>httpd.socket</command> unit. The default
<command>httpd.socket</command> has a
<literal>ListenStream=80</literal> and, if mod_ssl is installed,
<literal>ListenStream=443</literal> by a drop-in file. If
additional <literal>Listen</literal> directives are added to the
httpd configuration, corresponding
<literal>ListenStream</literal> options should be added via
drop-in files, for example via <command>systemctl edit
httpd.socket</command>.</para>
<para>If using socket activation with httpd, only one listener
on any given TCP port is supported; a configuration with both
"<literal>Listen 127.0.0.1:80</literal>" and "<literal>Listen
192.168.1.2:80</literal>" will not work.</para>
</refsect2>
<refsect2>
<title>Instantiated services</title>
<para>The <command>httpd@.service</command> unit is an
instantiated template service. An instance of this unit will be
started using the configuration file
<filename>/etc/httpd/conf/INSTANCE.conf</filename>, where
<emphasis>INSTANCE</emphasis> is replaced with the instance
name. For example, <command>systemctl start
httpd@foobar.service</command> will start httpd using the
configuration file
<filename>/etc/httpd/conf/foobar.conf</filename>. The
<option>HTTPD_INSTANCE</option> environment variable is set to
the instance name by the unit and is available for use within
the configuration file.</para>
<para>To allow multiple instances of httpd to run
simultaneously, a number of configuration directives must be
changed, such as <command>PidFile</command> and
<command>DefaultRuntimeDir</command> to pick non-conflicting
paths, and <command>Listen</command> to choose different ports.
The example configuration file
<filename>/usr/share/doc/httpd/instance.conf</filename>
demonstrates how to make such changes using
<option>HTTPD_INSTANCE</option> variable.</para>
<para>It can be useful to configure instances of
<command>httpd@.service</command> to reload when
<command>httpd.service</command> is reloaded; for example,
<command>logrotate</command> will reload only
<command>httpd.service</command> when logs are rotated. If this
behaviour is required, create a drop-in file for the instance as
follows:
<programlisting>[Unit]
ReloadPropagatedFrom=httpd.service</programlisting>
As with normal units, drop-in files for instances can be created
using <command>systemctl edit</command>, e.g. <command>systemctl edit
httpd@foobar.service</command>.</para>
</refsect2>
</refsect1>
<refsect1>
<title>Files</title>
<para><filename>/usr/lib/systemd/system/httpd.service</filename>,
<filename>/usr/lib/systemd/system/httpd.socket</filename>,
<filename>/usr/lib/systemd/system/httpd@.service</filename>,
<filename>/etc/systemd/systemd/httpd.service.d</filename></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>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>httpd_selinux</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>semanage</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
<!-- LocalWords: systemd PidFile
-->

13
SOURCES/httpd.socket Normal file
View File

@ -0,0 +1,13 @@
# See httpd.socket(8) for more information on using the httpd service.
[Unit]
Description=Apache httpd Server Socket
Documentation=man:httpd.socket(8)
[Socket]
ListenStream=80
NoDelay=true
DeferAcceptSec=30
[Install]
WantedBy=sockets.target

2
SOURCES/httpd.tmpfiles Normal file
View File

@ -0,0 +1,2 @@
d /run/httpd 710 root apache
d /run/httpd/htcacheclean 700 apache apache

23
SOURCES/httpd@.service Normal file
View File

@ -0,0 +1,23 @@
# This is a template for httpd instances.
# See httpd@.service(8) for more information.
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd@.service(8)
[Service]
Type=notify
Environment=LANG=C
Environment=HTTPD_INSTANCE=%i
ExecStartPre=/bin/mkdir -m 710 -p /run/httpd/instance-%i
ExecStartPre=/bin/chown root.apache /run/httpd/instance-%i
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND -f conf/%i.conf
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful -f conf/%i.conf
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target

123
SOURCES/index.html Normal file
View File

@ -0,0 +1,123 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test Page for the Apache HTTP Server on Red Hat Enterprise Linux</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
/*<![CDATA[*/
body {
background-color: #fff;
color: #000;
font-size: 0.9em;
font-family: sans-serif,helvetica;
margin: 0;
padding: 0;
}
:link {
color: #c00;
}
:visited {
color: #c00;
}
a:hover {
color: #f50;
}
h1 {
text-align: center;
margin: 0;
padding: 0.6em 2em 0.4em;
background-color: #900;
color: #fff;
font-weight: normal;
font-size: 1.75em;
border-bottom: 2px solid #000;
}
h1 strong {
font-weight: bold;
}
h2 {
font-size: 1.1em;
font-weight: bold;
}
hr {
display: none;
}
.content {
padding: 1em 5em;
}
.content-columns {
/* Setting relative positioning allows for
absolute positioning for sub-classes */
position: relative;
padding-top: 1em;
}
.content-column-left {
/* Value for IE/Win; will be overwritten for other browsers */
width: 47%;
padding-right: 3%;
float: left;
padding-bottom: 2em;
}
.content-column-left hr {
display: none;
}
.content-column-right {
/* Values for IE/Win; will be overwritten for other browsers */
width: 47%;
padding-left: 3%;
float: left;
padding-bottom: 2em;
}
.content-columns>.content-column-left, .content-columns>.content-column-right {
/* Non-IE/Win */
}
img {
border: 2px solid #fff;
padding: 2px;
margin: 2px;
}
a:hover img {
border: 2px solid #f50;
}
/*]]>*/
</style>
</head>
<body>
<h1>Red Hat Enterprise Linux <strong>Test Page</strong></h1>
<div class="content">
<div class="content-middle">
<p>This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the Apache HTTP server installed at this site is working properly.</p>
</div>
<hr />
<div class="content-columns">
<div class="content-column-left">
<h2>If you are a member of the general public:</h2>
<p>The fact that you are seeing this page indicates that the website you just visited is either experiencing problems, or is undergoing routine maintenance.</p>
<p>If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name "webmaster" and directed to the website's domain should reach the appropriate person.</p>
<p>For example, if you experienced problems while visiting www.example.com, you should send e-mail to "webmaster@example.com".</p>
<p>For information on Red Hat Enterprise Linux, please visit the <a href="http://www.redhat.com/">Red Hat, Inc. website</a>. The documentation for Red Hat Enterprise Linux is <a href="http://www.redhat.com/docs/manuals/enterprise/">available on the Red Hat, Inc. website</a>.</p>
<hr />
</div>
<div class="content-column-right">
<h2>If you are the website administrator:</h2>
<p>You may now add content to the directory <tt>/var/www/html/</tt>. Note that until you do so, people visiting your website will see this page, and not your content. To prevent this page from ever being used, follow the instructions in the file <tt>/etc/httpd/conf.d/welcome.conf</tt>.</p>
<p>You are free to use the image below on web sites powered by the Apache HTTP Server:</p>
<p align="center"><a href="http://httpd.apache.org/"><img src="/icons/apache_pb2.gif" alt="[ Powered by Apache ]"/></a></p>
</div>
</div>
</div>
</body>
</html>

23
SOURCES/instance.conf Normal file
View File

@ -0,0 +1,23 @@
#
# This is an example instance-specific configuration file. See the
# httpd.service(8) man page for detailed information on using the
# the httpd@.service with instances.
#
# To use this example, copy instance.conf to /etc/httpd/conf/foobar.conf
# This config will then used as the default configuration when
# running:
#
# # systemctl start httpd@foobar.service
#
# The changes compared to the default are:
# - DefaultRuntime and Pidfile renamed to be instance-specific
# - default logfile names are prefixed with the instance name
# - /etc/httpd/conf.d is NOT included by default (conf.modules.d still is)
#
# Further customisations will be required for an instance to run
# simultaneously to httpd.service under the default configuration,
# e.g. changing the port used with Listen.
#
DefaultRuntimeDir /run/httpd/instance-${HTTPD_INSTANCE}
PidFile /run/httpd/instance-${HTTPD_INSTANCE}.pid

13
SOURCES/manual.conf Normal file
View File

@ -0,0 +1,13 @@
#
# This configuration file allows the manual to be accessed at
# http://localhost/manual/
#
Alias /manual /usr/share/httpd/manual
<Directory "/usr/share/httpd/manual">
Options Indexes
AllowOverride None
Require all granted
RedirectMatch 301 ^/manual/(?:da|de|en|es|fr|ja|ko|pt-br|ru|tr|zh-cn)(/.*)$ "/manual$1"
</Directory>

203
SOURCES/ssl.conf Normal file
View File

@ -0,0 +1,203 @@
#
# When we also provide SSL we have to listen to the
# standard HTTPS port in addition.
#
Listen 443 https
##
## SSL Global Context
##
## All SSL configuration in this context applies both to
## the main server and all SSL-enabled virtual hosts.
##
# Pass Phrase Dialog:
# Configure the pass phrase gathering process.
# The filtering dialog program (`builtin' is a internal
# terminal dialog) has to provide the pass phrase on stdout.
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
# Inter-Process Session Cache:
# Configure the SSL Session Cache: First the mechanism
# to use and second the expiring timeout (in seconds).
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
#
# Use "SSLCryptoDevice" to enable any supported hardware
# accelerators. Use "openssl engine -v" to list supported
# engine names. NOTE: If you enable an accelerator and the
# server does not start, consult the error logs and ensure
# your accelerator is functioning properly.
#
SSLCryptoDevice builtin
#SSLCryptoDevice ubsec
##
## SSL Virtual Host Context
##
<VirtualHost _default_:443>
# General setup for the virtual host, inherited from global configuration
#DocumentRoot "/var/www/html"
#ServerName www.example.com:443
# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
# SSL Engine Switch:
# Enable/Disable SSL for this virtual host.
SSLEngine on
# List the protocol versions which clients are allowed to connect with.
# The OpenSSL system profile is used by default. See
# update-crypto-policies(8) for more details.
#SSLProtocol all -SSLv3
#SSLProxyProtocol all -SSLv3
# User agents such as web browsers are not configured for the user's
# own preference of either security or performance, therefore this
# must be the prerogative of the web server administrator who manages
# cpu load versus confidentiality, so enforce the server's cipher order.
SSLHonorCipherOrder on
# SSL Cipher Suite:
# List the ciphers that the client is permitted to negotiate.
# See the mod_ssl documentation for a complete list.
# The OpenSSL system profile is configured by default. See
# update-crypto-policies(8) for more details.
SSLCipherSuite PROFILE=SYSTEM
SSLProxyCipherSuite PROFILE=SYSTEM
# Point SSLCertificateFile at a PEM encoded certificate. If
# the certificate is encrypted, then you will be prompted for a
# pass phrase. Note that restarting httpd will prompt again. Keep
# in mind that if you have both an RSA and a DSA certificate you
# can configure both in parallel (to also allow the use of DSA
# ciphers, etc.)
# Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
# require an ECC certificate which can also be configured in
# parallel.
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
# Server Private Key:
# If the key is not combined with the certificate, use this
# directive to point at the key file. Keep in mind that if
# you've both a RSA and a DSA private key you can configure
# both in parallel (to also allow the use of DSA ciphers, etc.)
# ECC keys, when in use, can also be configured in parallel
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
# Server Certificate Chain:
# Point SSLCertificateChainFile at a file containing the
# concatenation of PEM encoded CA certificates which form the
# certificate chain for the server certificate. Alternatively
# the referenced file can be the same as SSLCertificateFile
# when the CA certificates are directly appended to the server
# certificate for convenience.
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
# Certificate Authority (CA):
# Set the CA certificate verification path where to find CA
# certificates for client authentication or alternatively one
# huge file containing all of them (file must be PEM encoded)
#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
# Client Authentication (Type):
# Client certificate verification type and depth. Types are
# none, optional, require and optional_no_ca. Depth is a
# number which specifies how deeply to verify the certificate
# issuer chain before deciding the certificate is not valid.
#SSLVerifyClient require
#SSLVerifyDepth 10
# Access Control:
# With SSLRequire you can do per-directory access control based
# on arbitrary complex boolean expressions containing server
# variable checks and other lookup directives. The syntax is a
# mixture between C and Perl. See the mod_ssl documentation
# for more details.
#<Location />
#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#</Location>
# SSL Engine Options:
# Set various options for the SSL engine.
# o FakeBasicAuth:
# Translate the client X.509 into a Basic Authorisation. This means that
# the standard Auth/DBMAuth methods can be used for access control. The
# user name is the `one line' version of the client's X.509 certificate.
# Note that no password is obtained from the user. Every entry in the user
# file needs this password: `xxj31ZMTZzkVA'.
# o ExportCertData:
# This exports two additional environment variables: SSL_CLIENT_CERT and
# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
# server (always existing) and the client (only existing when client
# authentication is used). This can be used to import the certificates
# into CGI scripts.
# o StdEnvVars:
# This exports the standard SSL/TLS related `SSL_*' environment variables.
# Per default this exportation is switched off for performance reasons,
# because the extraction step is an expensive operation and is usually
# useless for serving static content. So one usually enables the
# exportation for CGI and SSI requests only.
# o StrictRequire:
# This denies access when "SSLRequireSSL" or "SSLRequire" applied even
# under a "Satisfy any" situation, i.e. when it applies access is denied
# and no other module can change it.
# o OptRenegotiate:
# This enables optimized SSL connection renegotiation handling when SSL
# directives are used in per-directory context.
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
# SSL Protocol Adjustments:
# The safe and default but still SSL/TLS standard compliant shutdown
# approach is that mod_ssl sends the close notify alert but doesn't wait for
# the close notify alert from client. When you need a different shutdown
# approach you can use one of the following variables:
# o ssl-unclean-shutdown:
# This forces an unclean shutdown when the connection is closed, i.e. no
# SSL close notify alert is sent or allowed to be received. This violates
# the SSL/TLS standard but is needed for some brain-dead browsers. Use
# this when you receive I/O errors because of the standard approach where
# mod_ssl sends the close notify alert.
# o ssl-accurate-shutdown:
# This forces an accurate shutdown when the connection is closed, i.e. a
# SSL close notify alert is sent and mod_ssl waits for the close notify
# alert of the client. This is 100% SSL/TLS standard compliant, but in
# practice often causes hanging connections with brain-dead browsers. Use
# this only for browsers where you know that their SSL implementation
# works correctly.
# Notice: Most problems of broken clients are also related to the HTTP
# keep-alive facility, so you usually additionally want to disable
# keep-alive for those clients, too. Use variable "nokeepalive" for this.
# Similarly, one has to force some clients to use HTTP/1.0 to workaround
# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
# "force-response-1.0" for this.
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# Per-Server Logging:
# The home of a custom SSL log file. Use this when you want a
# compact non-error SSL logfile on a virtual host basis.
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

36
SOURCES/userdir.conf Normal file
View File

@ -0,0 +1,36 @@
#
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received.
#
# The path to the end user account 'public_html' directory must be
# accessible to the webserver userid. This usually means that ~userid
# must have permissions of 711, ~userid/public_html must have permissions
# of 755, and documents contained therein must be world-readable.
# Otherwise, the client will only receive a "403 Forbidden" message.
#
<IfModule mod_userdir.c>
#
# UserDir is disabled by default since it can confirm the presence
# of a username on the system (depending on home directory
# permissions).
#
UserDir disabled
#
# To enable requests to /~user/ to serve the user's public_html
# directory, remove the "UserDir disabled" line above, and uncomment
# the following line instead:
#
#UserDir public_html
</IfModule>
#
# Control access to UserDir directories. The following is an example
# for a site where these directories are restricted to read-only.
#
<Directory "/home/*/public_html">
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS
</Directory>

18
SOURCES/welcome.conf Normal file
View File

@ -0,0 +1,18 @@
#
# This configuration file enables the default "Welcome" page if there
# is no default index page present for the root URL. To disable the
# Welcome page, comment out all the lines below.
#
# NOTE: if this file is removed, it will be restored on upgrades.
#
<LocationMatch "^/+$">
Options -Indexes
ErrorDocument 403 /.noindex.html
</LocationMatch>
<Directory /usr/share/httpd/noindex>
AllowOverride None
Require all granted
</Directory>
Alias /.noindex.html /usr/share/httpd/noindex/index.html

1628
SPECS/httpd.spec Normal file

File diff suppressed because it is too large Load Diff