Browse Source

httpd package update

Signed-off-by: webbuilder_pel7x64builder0 <webbuilder@powerel.org>
master
webbuilder_pel7x64builder0 6 years ago
parent
commit
6adfc1fc30
  1. 77
      SOURCES/00-base.conf
  2. 3
      SOURCES/00-dav.conf
  3. 1
      SOURCES/00-lua.conf
  4. 19
      SOURCES/00-mpm.conf
  5. 16
      SOURCES/00-proxy.conf
  6. 3
      SOURCES/00-proxyhtml.conf
  7. 1
      SOURCES/00-ssl.conf
  8. 2
      SOURCES/00-systemd.conf
  9. 14
      SOURCES/01-cgi.conf
  10. 3
      SOURCES/01-ldap.conf
  11. 6
      SOURCES/01-session.conf
  12. 94
      SOURCES/httpd-2.4.1-apctl.patch
  13. 35
      SOURCES/httpd-2.4.1-corelimit.patch
  14. 19
      SOURCES/httpd-2.4.1-deplibs.patch
  15. 61
      SOURCES/httpd-2.4.1-selinux.patch
  16. 26
      SOURCES/httpd-2.4.2-icons.patch
  17. 45
      SOURCES/httpd-2.4.3-apctl-systemd.patch
  18. 56
      SOURCES/httpd-2.4.3-apxs.patch
  19. 34
      SOURCES/httpd-2.4.3-layout.patch
  20. 163
      SOURCES/httpd-2.4.3-mod_systemd.patch
  21. 83
      SOURCES/httpd-2.4.3-sslsninotreq.patch
  22. 82
      SOURCES/httpd-2.4.4-cachehardmax.patch
  23. 20
      SOURCES/httpd-2.4.4-export.patch
  24. 12
      SOURCES/httpd-2.4.4-malformed-host.patch
  25. 239
      SOURCES/httpd-2.4.4-mod_unique_id.patch
  26. 250
      SOURCES/httpd-2.4.4-r1337344+.patch
  27. 25
      SOURCES/httpd-2.4.6-CVE-2013-4352.patch
  28. 381
      SOURCES/httpd-2.4.6-CVE-2013-5704.patch
  29. 14
      SOURCES/httpd-2.4.6-CVE-2013-6438.patch
  30. 41
      SOURCES/httpd-2.4.6-CVE-2014-0098.patch
  31. 11
      SOURCES/httpd-2.4.6-CVE-2014-0117.patch
  32. 266
      SOURCES/httpd-2.4.6-CVE-2014-0118.patch
  33. 119
      SOURCES/httpd-2.4.6-CVE-2014-0226.patch
  34. 144
      SOURCES/httpd-2.4.6-CVE-2014-0231.patch
  35. 17
      SOURCES/httpd-2.4.6-CVE-2014-3581.patch
  36. 982
      SOURCES/httpd-2.4.6-CVE-2015-3183.patch
  37. 175
      SOURCES/httpd-2.4.6-CVE-2015-3185.patch
  38. 325
      SOURCES/httpd-2.4.6-CVE-2016-0736.patch
  39. 121
      SOURCES/httpd-2.4.6-CVE-2016-2161.patch
  40. 16
      SOURCES/httpd-2.4.6-CVE-2016-5387.patch
  41. 2124
      SOURCES/httpd-2.4.6-CVE-2016-8743.patch
  42. 343
      SOURCES/httpd-2.4.6-CVE-2017-3167.patch
  43. 64
      SOURCES/httpd-2.4.6-CVE-2017-3169.patch
  44. 15
      SOURCES/httpd-2.4.6-CVE-2017-7668.patch
  45. 14
      SOURCES/httpd-2.4.6-CVE-2017-7679.patch
  46. 29
      SOURCES/httpd-2.4.6-CVE-2017-9788.patch
  47. 17
      SOURCES/httpd-2.4.6-CVE-2017-9798.patch
  48. 20
      SOURCES/httpd-2.4.6-ab-overflow.patch
  49. 27
      SOURCES/httpd-2.4.6-ab-ssl-error.patch
  50. 139
      SOURCES/httpd-2.4.6-ap-ipv6.patch
  51. 38
      SOURCES/httpd-2.4.6-apachectl-httpd-env.patch
  52. 13
      SOURCES/httpd-2.4.6-apachectl-status.patch
  53. 14
      SOURCES/httpd-2.4.6-bomb.patch
  54. 31
      SOURCES/httpd-2.4.6-dhparams-free.patch
  55. 48
      SOURCES/httpd-2.4.6-full-release.patch
  56. 17
      SOURCES/httpd-2.4.6-http-protocol-options-define.patch
  57. 73
      SOURCES/httpd-2.4.6-ldaprefer.patch
  58. 55
      SOURCES/httpd-2.4.6-mod_authz_dbd-missing-query.patch
  59. 10
      SOURCES/httpd-2.4.6-mpm-segfault.patch
  60. 140
      SOURCES/httpd-2.4.6-pre_htaccess.patch
  61. 313
      SOURCES/httpd-2.4.6-r1332643+.patch
  62. 77
      SOURCES/httpd-2.4.6-r1348019.patch
  63. 154
      SOURCES/httpd-2.4.6-r1420184.patch
  64. 13
      SOURCES/httpd-2.4.6-r1506474.patch
  65. 62
      SOURCES/httpd-2.4.6-r1507681+.patch
  66. 20
      SOURCES/httpd-2.4.6-r1524368.patch
  67. 62
      SOURCES/httpd-2.4.6-r1526189.patch
  68. 21
      SOURCES/httpd-2.4.6-r1527509.patch
  69. 23
      SOURCES/httpd-2.4.6-r1528556.patch
  70. 46
      SOURCES/httpd-2.4.6-r1528958.patch
  71. 59
      SOURCES/httpd-2.4.6-r1530280.patch
  72. 19
      SOURCES/httpd-2.4.6-r1530999.patch
  73. 155
      SOURCES/httpd-2.4.6-r1533448.patch
  74. 38
      SOURCES/httpd-2.4.6-r1537535.patch
  75. 868
      SOURCES/httpd-2.4.6-r1542327.patch
  76. 28
      SOURCES/httpd-2.4.6-r1553540.patch
  77. 31
      SOURCES/httpd-2.4.6-r1556473.patch
  78. 26
      SOURCES/httpd-2.4.6-r1556818.patch
  79. 16
      SOURCES/httpd-2.4.6-r1560093.patch
  80. 19
      SOURCES/httpd-2.4.6-r1569006.patch
  81. 20
      SOURCES/httpd-2.4.6-r1570327.patch
  82. 29
      SOURCES/httpd-2.4.6-r1573626.patch
  83. 92
      SOURCES/httpd-2.4.6-r1587053.patch
  84. 35
      SOURCES/httpd-2.4.6-r1593002.patch
  85. 25
      SOURCES/httpd-2.4.6-r1594625.patch
  86. 22
      SOURCES/httpd-2.4.6-r1604460.patch
  87. 141
      SOURCES/httpd-2.4.6-r1610013.patch
  88. 189
      SOURCES/httpd-2.4.6-r1610396.patch
  89. 28
      SOURCES/httpd-2.4.6-r1618851.patch
  90. 21
      SOURCES/httpd-2.4.6-r1621601.patch
  91. 21
      SOURCES/httpd-2.4.6-r1624349.patch
  92. 16
      SOURCES/httpd-2.4.6-r1631119.patch
  93. 14
      SOURCES/httpd-2.4.6-r1633085.patch
  94. 275
      SOURCES/httpd-2.4.6-r1634529.patch
  95. 132
      SOURCES/httpd-2.4.6-r1650310.patch
  96. 41
      SOURCES/httpd-2.4.6-r1650655.patch
  97. 49
      SOURCES/httpd-2.4.6-r1650677.patch
  98. 10
      SOURCES/httpd-2.4.6-r1651083.patch
  99. 100
      SOURCES/httpd-2.4.6-r1651653.patch
  100. 22
      SOURCES/httpd-2.4.6-r1651658.patch
  101. Some files were not shown because too many files have changed in this diff Show More

77
SOURCES/00-base.conf

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
#
# 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 cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.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 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 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 buffer_module modules/mod_buffer.so
#LoadModule watchdog_module modules/mod_watchdog.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 ratelimit_module modules/mod_ratelimit.so
#LoadModule reflector_module modules/mod_reflector.so
#LoadModule request_module modules/mod_request.so
#LoadModule sed_module modules/mod_sed.so
#LoadModule speling_module modules/mod_speling.so

3
SOURCES/00-dav.conf

@ -0,0 +1,3 @@ @@ -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

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

19
SOURCES/00-mpm.conf

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
# Select the MPM module which should be used by uncommenting exactly
# one of the following LoadModule lines:

# prefork MPM: Implements a non-threaded, pre-forking web server
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
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

16
SOURCES/00-proxy.conf

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
# 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_scgi_module modules/mod_proxy_scgi.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

3
SOURCES/00-proxyhtml.conf

@ -0,0 +1,3 @@ @@ -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

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

2
SOURCES/00-systemd.conf

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

14
SOURCES/01-cgi.conf

@ -0,0 +1,14 @@ @@ -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

@ -0,0 +1,3 @@ @@ -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

@ -0,0 +1,6 @@ @@ -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

94
SOURCES/httpd-2.4.1-apctl.patch

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@

- fail gracefully if links is not installed on target system
- source sysconfig/httpd for custom env. vars etc.
- make httpd -t work even in SELinux
- pass $OPTIONS to all $HTTPD invocation

Upstream-HEAD: vendor
Upstream-2.0: vendor
Upstream-Status: Vendor-specific changes for better initscript integration

--- httpd-2.4.1/support/apachectl.in.apctl
+++ httpd-2.4.1/support/apachectl.in
@@ -44,19 +44,25 @@ ARGV="$@"
# the path to your httpd binary, including options if necessary
HTTPD='@exp_sbindir@/@progname@'
#
-# pick up any necessary environment variables
-if test -f @exp_sbindir@/envvars; then
- . @exp_sbindir@/envvars
-fi
#
# a command that outputs a formatted text version of the HTML at the
# url given on the command line. Designed for lynx, however other
# programs may work.
-LYNX="@LYNX_PATH@ -dump"
+if [ -x "@LYNX_PATH@" ]; then
+ LYNX="@LYNX_PATH@ -dump"
+else
+ LYNX=none
+fi
#
# the URL to your server's mod_status status page. If you do not
# have one, then status and fullstatus will not work.
STATUSURL="http://localhost:@PORT@/server-status"
+
+# Source /etc/sysconfig/httpd for $HTTPD setting, etc.
+if [ -r /etc/sysconfig/httpd ]; then
+ . /etc/sysconfig/httpd
+fi
+
#
# Set this variable to a command that increases the maximum
# number of file descriptors allowed per child process. This is
@@ -76,9 +82,27 @@ if [ "x$ARGV" = "x" ] ; then
ARGV="-h"
fi
+function checklynx() {
+if [ "$LYNX" = "none" ]; then
+ echo "The 'links' package is required for this functionality."
+ exit 8
+fi
+}
+
+function testconfig() {
+# httpd is denied terminal access in SELinux, so run in the
+# current context to get stdout from $HTTPD -t.
+if test -x /usr/sbin/selinuxenabled && /usr/sbin/selinuxenabled; then
+ runcon -- `id -Z` $HTTPD $OPTIONS -t
+else
+ $HTTPD $OPTIONS -t
+fi
+ERROR=$?
+}
+
case $ACMD in
start|stop|restart|graceful|graceful-stop)
- $HTTPD -k $ARGV
+ $HTTPD $OPTIONS -k $ARGV
ERROR=$?
;;
startssl|sslstart|start-SSL)
@@ -88,17 +112,18 @@ startssl|sslstart|start-SSL)
ERROR=2
;;
configtest)
- $HTTPD -t
- ERROR=$?
+ testconfig
;;
status)
+ checklynx
$LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
;;
fullstatus)
+ checklynx
$LYNX $STATUSURL
;;
*)
- $HTTPD "$@"
+ $HTTPD $OPTIONS "$@"
ERROR=$?
esac

35
SOURCES/httpd-2.4.1-corelimit.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@

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.

--- httpd-2.4.1/server/core.c.corelimit
+++ httpd-2.4.1/server/core.c
@@ -4433,6 +4433,25 @@ static int core_post_config(apr_pool_t *
}
apr_pool_cleanup_register(pconf, NULL, ap_mpm_end_gen_helper,
apr_pool_cleanup_null);
+
+#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;
}

19
SOURCES/httpd-2.4.1-deplibs.patch

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@

Link straight against .la files.

Upstream-Status: vendor specific

--- httpd-2.4.1/configure.in.deplibs
+++ httpd-2.4.1/configure.in
@@ -707,9 +707,9 @@ APACHE_HELP_STRING(--with-suexec-umask,u
dnl APR should go after the other libs, so the right symbols can be picked up
if test x${apu_found} != xobsolete; then
- 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)

61
SOURCES/httpd-2.4.1-selinux.patch

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@

Log the SELinux context at startup.

Upstream-Status: unlikely to be any interest in this upstream

--- httpd-2.4.1/configure.in.selinux
+++ httpd-2.4.1/configure.in
@@ -458,6 +458,11 @@ fopen64
dnl confirm that a void pointer is large enough to store a long integer
APACHE_CHECK_VOID_PTR_LEN
+AC_CHECK_LIB(selinux, is_selinux_enabled, [
+ AC_DEFINE(HAVE_SELINUX, 1, [Defined if SELinux is supported])
+ APR_ADDTO(AP_LIBS, [-lselinux])
+])
+
AC_CACHE_CHECK([for gettid()], ac_cv_gettid,
[AC_TRY_RUN(#define _GNU_SOURCE
#include <unistd.h>
--- httpd-2.4.1/server/core.c.selinux
+++ httpd-2.4.1/server/core.c
@@ -58,6 +58,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)
@@ -4452,6 +4456,28 @@ static int core_post_config(apr_pool_t *
}
#endif
+#ifdef HAVE_SELINUX
+ {
+ static int already_warned = 0;
+ int is_enabled = is_selinux_enabled() > 0;
+
+ if (is_enabled && !already_warned) {
+ security_context_t con;
+
+ if (getcon(&con) == 0) {
+
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
+ "SELinux policy enabled; "
+ "httpd running as context %s", con);
+
+ already_warned = 1;
+
+ freecon(con);
+ }
+ }
+ }
+#endif
+
return OK;
}

26
SOURCES/httpd-2.4.2-icons.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@

- Fix config for /icons/ dir to allow symlink to poweredby.png.
- Avoid using coredump GIF for a directory called "core"

Upstream-Status: vendor specific patch

--- httpd-2.4.2/docs/conf/extra/httpd-autoindex.conf.in.icons
+++ httpd-2.4.2/docs/conf/extra/httpd-autoindex.conf.in
@@ -21,7 +21,7 @@ IndexOptions FancyIndexing HTMLTable Ver
Alias /icons/ "@exp_iconsdir@/"
<Directory "@exp_iconsdir@">
- Options Indexes MultiViews
+ Options Indexes MultiViews FollowSymlinks
AllowOverride None
Require all granted
</Directory>
@@ -53,7 +53,7 @@ AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
-AddIcon /icons/bomb.gif core
+AddIcon /icons/bomb.gif core.
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README

45
SOURCES/httpd-2.4.3-apctl-systemd.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@

Upstream-Status: vendor specific patch

diff --git a/support/apachectl.in b/support/apachectl.in
index c6ac3ea..2599386 100644
--- a/support/apachectl.in
+++ b/support/apachectl.in
@@ -100,9 +100,24 @@ fi
ERROR=$?
}
+if [ "x$2" != "x" ] ; then
+ echo Passing arguments to httpd using apachectl is no longer supported.
+ echo You can only start/stop/restart httpd using this script.
+ echo If you want to pass extra arguments to httpd, edit the
+ echo /etc/sysconfig/httpd config file.
+fi
+
case $ACMD in
-start|stop|restart|graceful|graceful-stop)
- $HTTPD $OPTIONS -k $ARGV
+start|stop|restart|status)
+ /usr/bin/systemctl $ACMD httpd.service
+ ERROR=$?
+ ;;
+graceful)
+ /usr/bin/systemctl reload httpd.service
+ ERROR=$?
+ ;;
+graceful-stop)
+ /usr/bin/systemctl stop httpd.service
ERROR=$?
;;
startssl|sslstart|start-SSL)
@@ -114,10 +129,6 @@ startssl|sslstart|start-SSL)
configtest)
testconfig
;;
-status)
- checklynx
- $LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
- ;;
fullstatus)
checklynx
$LYNX $STATUSURL

56
SOURCES/httpd-2.4.3-apxs.patch

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
--- httpd-2.4.3/support/apxs.in.apxs
+++ httpd-2.4.3/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
APXS=apxs

34
SOURCES/httpd-2.4.3-layout.patch

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@

Add layout for Fedora.

--- httpd-2.4.3/config.layout.layout
+++ httpd-2.4.3/config.layout
@@ -370,3 +370,28 @@
logfiledir: ${localstatedir}/log/httpd
proxycachedir: ${localstatedir}/cache/httpd
</Layout>
+
+# Fedora/RHEL layout
+<Layout Fedora>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${prefix}/bin
+ sbindir: ${prefix}/sbin
+ libdir: ${prefix}/lib
+ libexecdir: ${prefix}/libexec
+ mandir: ${prefix}/man
+ sysconfdir: /etc/httpd/conf
+ datadir: ${prefix}/share/httpd
+ installbuilddir: ${libdir}/httpd/build
+ errordir: ${datadir}/error
+ iconsdir: ${datadir}/icons
+ htdocsdir: /var/www/html
+ manualdir: ${datadir}/manual
+ cgidir: /var/www/cgi-bin
+ includedir: ${prefix}/include/httpd
+ localstatedir: /var
+ runtimedir: /run/httpd
+ logfiledir: ${localstatedir}/log/httpd
+ proxycachedir: ${localstatedir}/cache/httpd/proxy
+ davlockdb: ${localstatedir}/lib/dav/lockdb
+</Layout>

163
SOURCES/httpd-2.4.3-mod_systemd.patch

@ -0,0 +1,163 @@ @@ -0,0 +1,163 @@
--- httpd-2.4.3/modules/arch/unix/config5.m4.systemd
+++ httpd-2.4.3/modules/arch/unix/config5.m4
@@ -18,6 +18,19 @@ APACHE_MODULE(privileges, Per-virtualhos
fi
])
+
+APACHE_MODULE(systemd, Systemd support, , , $unixd_mods_enabled, [
+ AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon")
+ AC_CHECK_HEADERS(systemd/sd-daemon.h, [ap_HAVE_SD_DAEMON_H="yes"], [ap_HAVE_SD_DAEMON_H="no"])
+ if test $ap_HAVE_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.3/modules/arch/unix/mod_systemd.c.systemd
+++ httpd-2.4.3/modules/arch/unix/mod_systemd.c
@@ -0,0 +1,138 @@
+/* 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 <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"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define KBYTE 1024
+
+static pid_t pid; /* PID of the main httpd instance */
+static int server_limit, thread_limit, threads_per_child, max_servers;
+static time_t last_update_time;
+static unsigned long last_update_access;
+static unsigned long last_update_kbytes;
+
+static int systemd_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
+{
+ int rv;
+ last_update_time = time(0);
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &threads_per_child);
+ /* work around buggy MPMs */
+ if (threads_per_child == 0)
+ threads_per_child = 1;
+ ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_servers);
+
+ pid = getpid();
+
+ rv = sd_notifyf(0, "READY=1\n"
+ "STATUS=Processing requests...\n"
+ "MAINPID=%lu",
+ (unsigned long) pid);
+ if (rv < 0) {
+ ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
+ "sd_notifyf returned an error %d", rv);
+ }
+
+ return OK;
+}
+
+static int systemd_monitor(apr_pool_t *p, server_rec *s)
+{
+ int i, j, res, rv;
+ process_score *ps_record;
+ worker_score *ws_record;
+ unsigned long access = 0;
+ unsigned long bytes = 0;
+ unsigned long kbytes = 0;
+ char bps[5];
+ time_t now = time(0);
+ time_t elapsed = now - last_update_time;
+
+ for (i = 0; i < server_limit; ++i) {
+ ps_record = ap_get_scoreboard_process(i);
+ for (j = 0; j < thread_limit; ++j) {
+ ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
+ if (ap_extended_status && !ps_record->quiescing && ps_record->pid) {
+ res = ws_record->status;
+ if (ws_record->access_count != 0 ||
+ (res != SERVER_READY && res != SERVER_DEAD)) {
+ access += ws_record->access_count;
+ bytes += ws_record->bytes_served;
+ if (bytes >= KBYTE) {
+ kbytes += (bytes >> 10);
+ bytes = bytes & 0x3ff;
+ }
+ }
+ }
+ }
+ }
+
+ apr_strfsize((unsigned long)(KBYTE *(float) (kbytes - last_update_kbytes)
+ / (float) elapsed), bps);
+
+ rv = sd_notifyf(0, "READY=1\n"
+ "STATUS=Total requests: %lu; Current requests/sec: %.3g; "
+ "Current traffic: %sB/sec\n", access,
+ ((float)access - last_update_access) / (float) elapsed, bps);
+ if (rv < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00000)
+ "sd_notifyf returned an error %d", rv);
+ }
+
+ last_update_access = access;
+ last_update_kbytes = kbytes;
+ last_update_time = now;
+
+ return DECLINED;
+}
+
+static void systemd_register_hooks(apr_pool_t *p)
+{
+ /* 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);
+}
+
+module AP_MODULE_DECLARE_DATA systemd_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ systemd_register_hooks,
+};

83
SOURCES/httpd-2.4.3-sslsninotreq.patch

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 15993f1..53ed6f1 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -55,6 +55,7 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
mc = (SSLModConfigRec *)apr_palloc(pool, sizeof(*mc));
mc->pPool = pool;
mc->bFixed = FALSE;
+ mc->sni_required = FALSE;
/*
* initialize per-module configuration
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index bf1f0e4..a7523de 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -409,7 +409,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
/*
* Configuration consistency checks
*/
- ssl_init_CheckServers(base_server, ptemp);
+ ssl_init_CheckServers(mc, base_server, ptemp);
/*
* Announce mod_ssl and SSL library in HTTP Server field
@@ -1475,7 +1475,7 @@ void ssl_init_ConfigureServer(server_rec *s,
}
}
-void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
+void ssl_init_CheckServers(SSLModConfigRec *mc, server_rec *base_server, apr_pool_t *p)
{
server_rec *s, *ps;
SSLSrvConfigRec *sc;
@@ -1557,6 +1557,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
}
if (conflict) {
+ mc->sni_required = TRUE;
#ifdef OPENSSL_NO_TLSEXT
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01917)
"Init: You should not use name-based "
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index bc9e26b..2460f01 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -164,6 +164,7 @@ int ssl_hook_ReadReq(request_rec *r)
return DECLINED;
}
#ifndef OPENSSL_NO_TLSEXT
+ if (myModConfig(r->server)->sni_required) {
if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
char *host, *scope_id;
apr_port_t port;
@@ -206,6 +207,7 @@ int ssl_hook_ReadReq(request_rec *r)
" virtual host");
return HTTP_FORBIDDEN;
}
+ }
#endif
SSL_set_app_data2(ssl, r);
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 75fc0e3..31dbfa9 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -554,6 +554,7 @@ typedef struct {
struct {
void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
} rCtx;
+ BOOL sni_required;
} SSLModConfigRec;
/** Structure representing configured filenames for certs and keys for
@@ -786,7 +787,7 @@ const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag);
int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
void ssl_init_Engine(server_rec *, apr_pool_t *);
void ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *);
-void ssl_init_CheckServers(server_rec *, apr_pool_t *);
+void ssl_init_CheckServers(SSLModConfigRec *mc, server_rec *, apr_pool_t *);
STACK_OF(X509_NAME)
*ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *);
void ssl_init_Child(apr_pool_t *, server_rec *);

82
SOURCES/httpd-2.4.4-cachehardmax.patch

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
diff --git a/modules/cache/cache_util.h b/modules/cache/cache_util.h
index eec38f3..1a2d5ee 100644
--- a/modules/cache/cache_util.h
+++ b/modules/cache/cache_util.h
@@ -194,6 +194,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 4f2d3e0..30c88f4 100644
--- a/modules/cache/mod_cache.c
+++ b/modules/cache/mod_cache.c
@@ -1299,6 +1299,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. */
@@ -1717,7 +1722,9 @@ static void *create_dir_config(apr_pool_t *p, char *dummy)
/* array of providers for this URL space */
dconf->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
-
+ /* flag; treat maxex as hard limit */
+ dconf->hardmaxex = 0;
+ dconf->hardmaxex_set = 0;
return dconf;
}
@@ -1767,7 +1774,10 @@ static void *merge_dir_config(apr_pool_t *p, void *basev, void *addv) {
new->enable_set = add->enable_set || base->enable_set;
new->disable = (add->disable_set == 0) ? base->disable : add->disable;
new->disable_set = add->disable_set || base->disable_set;
-
+ new->hardmaxex =
+ (add->hardmaxex_set == 0)
+ ? base->hardmaxex
+ : add->hardmaxex;
return new;
}
@@ -2096,12 +2106,18 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy,
}
static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
- 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;
}
@@ -2309,7 +2325,7 @@ static const command_rec cache_cmds[] =
"caching is enabled"),
AP_INIT_TAKE1("CacheDisable", add_cache_disable, NULL, RSRC_CONF|ACCESS_CONF,
"A partial URL prefix below which caching is disabled"),
- 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"),

20
SOURCES/httpd-2.4.4-export.patch

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@

There is no need to "suck in" the apr/apr-util symbols when using
a shared libapr{,util}, it just bloats the symbol table; so don't.

Upstream-HEAD: needed
Upstream-2.0: omit
Upstream-Status: EXPORT_DIRS change is conditional on using shared apr

--- httpd-2.4.4/server/Makefile.in.export
+++ httpd-2.4.4/server/Makefile.in
@@ -57,9 +57,6 @@ export_files:
( for dir in $(EXPORT_DIRS); do \
ls $$dir/*.h ; \
done; \
- 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

12
SOURCES/httpd-2.4.4-malformed-host.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff --git a/server/protocol.c b/server/protocol.c
index e1ef204..d6d9165 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1049,6 +1049,7 @@ request_rec *ap_read_request(conn_rec *conn)
* now read. may update status.
*/
ap_update_vhost_from_headers(r);
+ access_status = r->status;
/* Toggle to the Host:-based vhost's timeout mode to fetch the
* request body and send the response body, if needed.

239
SOURCES/httpd-2.4.4-mod_unique_id.patch

@ -0,0 +1,239 @@ @@ -0,0 +1,239 @@
--- trunk/modules/metadata/mod_unique_id.c 2011/12/02 23:02:04 1209766
+++ trunk/modules/metadata/mod_unique_id.c 2013/07/10 16:20:31 1501827
@@ -31,14 +31,11 @@
#include "http_log.h"
#include "http_protocol.h" /* for ap_hook_post_read_request */
-#if APR_HAVE_UNISTD_H
-#include <unistd.h> /* for getpid() */
-#endif
+#define ROOT_SIZE 10
typedef struct {
unsigned int stamp;
- unsigned int in_addr;
- unsigned int pid;
+ char root[ROOT_SIZE];
unsigned short counter;
unsigned int thread_index;
} unique_id_rec;
@@ -64,20 +61,15 @@
* gethostbyname (gethostname()) is unique across all the machines at the
* "site".
*
- * We also further assume that pids fit in 32-bits. If something uses more
- * than 32-bits, the fix is trivial, but it requires the unrolled uuencoding
- * loop to be extended. * A similar fix is needed to support multithreaded
- * servers, using a pid/tid combo.
- *
- * Together, the in_addr and pid are assumed to absolutely uniquely identify
- * this one child from all other currently running children on all servers
- * (including this physical server if it is running multiple httpds) from each
+ * The root is assumed to absolutely uniquely identify this one child
+ * from all other currently running children on all servers (including
+ * this physical server if it is running multiple httpds) from each
* other.
*
- * The stamp and counter are used to distinguish all hits for a particular
- * (in_addr,pid) pair. The stamp is updated using r->request_time,
- * saving cpu cycles. The counter is never reset, and is used to permit up to
- * 64k requests in a single second by a single child.
+ * The stamp and counter are used to distinguish all hits for a
+ * particular root. The stamp is updated using r->request_time,
+ * saving cpu cycles. The counter is never reset, and is used to
+ * permit up to 64k requests in a single second by a single child.
*
* The 144-bits of unique_id_rec are encoded using the alphabet
* [A-Za-z0-9@-], resulting in 24 bytes of printable characters. That is then
@@ -92,7 +84,7 @@
* module change.
*
* It is highly desirable that identifiers exist for "eternity". But future
- * needs (such as much faster webservers, moving to 64-bit pids, or moving to a
+ * needs (such as much faster webservers, or moving to a
* multithreaded server) may dictate a need to change the contents of
* unique_id_rec. Such a future implementation should ensure that the first
* field is still a time_t stamp. By doing that, it is possible for a site to
@@ -100,7 +92,15 @@
* wait one entire second, and then start all of their new-servers. This
* procedure will ensure that the new space of identifiers is completely unique
* from the old space. (Since the first four unencoded bytes always differ.)
+ *
+ * Note: previous implementations used 32-bits of IP address plus pid
+ * in place of the PRNG output in the "root" field. This was
+ * insufficient for IPv6-only hosts, required working DNS to determine
+ * a unique IP address (fragile), and needed a [0, 1) second sleep
+ * call at startup to avoid pid reuse. Use of the PRNG avoids all
+ * these issues.
*/
+
/*
* Sun Jun 7 05:43:49 CEST 1998 -- Alvaro
* More comments:
@@ -116,8 +116,6 @@
* htonl/ntohl. Well, this shouldn't be a problem till year 2106.
*/
-static unsigned global_in_addr;
-
/*
* XXX: We should have a per-thread counter and not use cur_unique_id.counter
* XXX: in all threads, because this is bad for performance on multi-processor
@@ -129,7 +127,7 @@
/*
* Number of elements in the structure unique_id_rec.
*/
-#define UNIQUE_ID_REC_MAX 5
+#define UNIQUE_ID_REC_MAX 4
static unsigned short unique_id_rec_offset[UNIQUE_ID_REC_MAX],
unique_id_rec_size[UNIQUE_ID_REC_MAX],
@@ -138,113 +136,32 @@
static int unique_id_global_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server)
{
- char str[APRMAXHOSTLEN + 1];
- apr_status_t rv;
- char *ipaddrstr;
- apr_sockaddr_t *sockaddr;
-
/*
* Calculate the sizes and offsets in cur_unique_id.
*/
unique_id_rec_offset[0] = APR_OFFSETOF(unique_id_rec, stamp);
unique_id_rec_size[0] = sizeof(cur_unique_id.stamp);
- unique_id_rec_offset[1] = APR_OFFSETOF(unique_id_rec, in_addr);
- unique_id_rec_size[1] = sizeof(cur_unique_id.in_addr);
- unique_id_rec_offset[2] = APR_OFFSETOF(unique_id_rec, pid);
- unique_id_rec_size[2] = sizeof(cur_unique_id.pid);
- unique_id_rec_offset[3] = APR_OFFSETOF(unique_id_rec, counter);
- unique_id_rec_size[3] = sizeof(cur_unique_id.counter);
- unique_id_rec_offset[4] = APR_OFFSETOF(unique_id_rec, thread_index);
- unique_id_rec_size[4] = sizeof(cur_unique_id.thread_index);
+ unique_id_rec_offset[1] = APR_OFFSETOF(unique_id_rec, root);
+ unique_id_rec_size[1] = sizeof(cur_unique_id.root);
+ unique_id_rec_offset[2] = APR_OFFSETOF(unique_id_rec, counter);
+ unique_id_rec_size[2] = sizeof(cur_unique_id.counter);
+ unique_id_rec_offset[3] = APR_OFFSETOF(unique_id_rec, thread_index);
+ unique_id_rec_size[3] = sizeof(cur_unique_id.thread_index);
unique_id_rec_total_size = unique_id_rec_size[0] + unique_id_rec_size[1] +
- unique_id_rec_size[2] + unique_id_rec_size[3] +
- unique_id_rec_size[4];
+ unique_id_rec_size[2] + unique_id_rec_size[3];
/*
* Calculate the size of the structure when encoded.
*/
unique_id_rec_size_uu = (unique_id_rec_total_size*8+5)/6;
- /*
- * Now get the global in_addr. Note that it is not sufficient to use one
- * of the addresses from the main_server, since those aren't as likely to
- * be unique as the physical address of the machine
- */
- if ((rv = apr_gethostname(str, sizeof(str) - 1, p)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rv, main_server, APLOGNO(01563)
- "unable to find hostname of the server");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if ((rv = apr_sockaddr_info_get(&sockaddr, str, AF_INET, 0, 0, p)) == APR_SUCCESS) {
- global_in_addr = sockaddr->sa.sin.sin_addr.s_addr;
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rv, main_server, APLOGNO(01564)
- "unable to find IPv4 address of \"%s\"", str);
-#if APR_HAVE_IPV6
- if ((rv = apr_sockaddr_info_get(&sockaddr, str, AF_INET6, 0, 0, p)) == APR_SUCCESS) {
- memcpy(&global_in_addr,
- (char *)sockaddr->ipaddr_ptr + sockaddr->ipaddr_len - sizeof(global_in_addr),
- sizeof(global_in_addr));
- ap_log_error(APLOG_MARK, APLOG_ALERT, rv, main_server, APLOGNO(01565)
- "using low-order bits of IPv6 address "
- "as if they were unique");
- }
- else
-#endif
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- apr_sockaddr_ip_get(&ipaddrstr, sockaddr);
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, main_server, APLOGNO(01566) "using ip addr %s",
- ipaddrstr);
-
- /*
- * If the server is pummelled with restart requests we could possibly end
- * up in a situation where we're starting again during the same second
- * that has been used in previous identifiers. Avoid that situation.
- *
- * In truth, for this to actually happen not only would it have to restart
- * in the same second, but it would have to somehow get the same pids as
- * one of the other servers that was running in that second. Which would
- * mean a 64k wraparound on pids ... not very likely at all.
- *
- * But protecting against it is relatively cheap. We just sleep into the
- * next second.
- */
- apr_sleep(apr_time_from_sec(1) - apr_time_usec(apr_time_now()));
return OK;
}
static void unique_id_child_init(apr_pool_t *p, server_rec *s)
{
- pid_t pid;
-
- /*
- * Note that we use the pid because it's possible that on the same
- * physical machine there are multiple servers (i.e. using Listen). But
- * it's guaranteed that none of them will share the same pids between
- * children.
- *
- * XXX: for multithread this needs to use a pid/tid combo and probably
- * needs to be expanded to 32 bits
- */
- pid = getpid();
- cur_unique_id.pid = pid;
-
- /*
- * Test our assumption that the pid is 32-bits. It's possible that
- * 64-bit machines will declare pid_t to be 64 bits but only use 32
- * of them. It would have been really nice to test this during
- * global_init ... but oh well.
- */
- if ((pid_t)cur_unique_id.pid != pid) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(01567)
- "oh no! pids are greater than 32-bits! I'm broken!");
- }
-
- cur_unique_id.in_addr = global_in_addr;
+ ap_random_insecure_bytes(&cur_unique_id.root,
+ sizeof(cur_unique_id.root));
/*
* If we use 0 as the initial counter we have a little less protection
@@ -253,13 +170,6 @@
*/
ap_random_insecure_bytes(&cur_unique_id.counter,
sizeof(cur_unique_id.counter));
-
- /*
- * We must always use network ordering for these bytes, so that
- * identifiers are comparable between machines of different byte
- * orderings. Note in_addr is already in network order.
- */
- cur_unique_id.pid = htonl(cur_unique_id.pid);
}
/* NOTE: This is *NOT* the same encoding used by base64encode ... the last two
@@ -291,10 +201,8 @@
unsigned short counter;
int i,j,k;
- new_unique_id.in_addr = cur_unique_id.in_addr;
- new_unique_id.pid = cur_unique_id.pid;
+ memcpy(&new_unique_id.root, &cur_unique_id.root, ROOT_SIZE);
new_unique_id.counter = cur_unique_id.counter;
-
new_unique_id.stamp = htonl((unsigned int)apr_time_sec(r->request_time));
new_unique_id.thread_index = htonl((unsigned int)r->connection->id);

250
SOURCES/httpd-2.4.4-r1337344+.patch

@ -0,0 +1,250 @@ @@ -0,0 +1,250 @@
# ./pullrev.sh 1337344 1341905 1342065 1341930

suexec enhancements:

1) use syslog for logging
2) use capabilities not setuid/setgid root binary

http://svn.apache.org/viewvc?view=revision&revision=1337344
http://svn.apache.org/viewvc?view=revision&revision=1341905
http://svn.apache.org/viewvc?view=revision&revision=1342065
http://svn.apache.org/viewvc?view=revision&revision=1341930

--- httpd-2.4.4/configure.in.r1337344+
+++ httpd-2.4.4/configure.in
@@ -734,7 +734,24 @@ APACHE_HELP_STRING(--with-suexec-gidmin,
AC_ARG_WITH(suexec-logfile,
APACHE_HELP_STRING(--with-suexec-logfile,Set the logfile),[
- AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file] ) ] )
+ if test "x$withval" = "xyes"; then
+ AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file])
+ fi
+])
+
+AC_ARG_WITH(suexec-syslog,
+APACHE_HELP_STRING(--with-suexec-syslog,Set the logfile),[
+ if test $withval = "yes"; then
+ if test "x${with_suexec_logfile}" != "xno"; then
+ AC_MSG_NOTICE([hint: use "--without-suexec-logfile --with-suexec-syslog"])
+ AC_MSG_ERROR([suexec does not support both logging to file and syslog])
+ fi
+ AC_CHECK_FUNCS([vsyslog], [], [
+ AC_MSG_ERROR([cannot support syslog from suexec without vsyslog()])])
+ AC_DEFINE(AP_LOG_SYSLOG, 1, [SuExec log to syslog])
+ fi
+])
+
AC_ARG_WITH(suexec-safepath,
APACHE_HELP_STRING(--with-suexec-safepath,Set the safepath),[
@@ -744,6 +761,15 @@ AC_ARG_WITH(suexec-umask,
APACHE_HELP_STRING(--with-suexec-umask,umask for suexec'd process),[
AC_DEFINE_UNQUOTED(AP_SUEXEC_UMASK, 0$withval, [umask for suexec'd process] ) ] )
+INSTALL_SUEXEC=setuid
+AC_ARG_ENABLE([suexec-capabilities],
+APACHE_HELP_STRING(--enable-suexec-capabilities,Use Linux capability bits not setuid root suexec), [
+INSTALL_SUEXEC=caps
+AC_DEFINE(AP_SUEXEC_CAPABILITIES, 1,
+ [Enable if suexec is installed with Linux capabilities, not setuid])
+])
+APACHE_SUBST(INSTALL_SUEXEC)
+
dnl APR should go after the other libs, so the right symbols can be picked up
if test x${apu_found} != xobsolete; then
AP_LIBS="$AP_LIBS `$apu_config --avoid-ldap --link-libtool`"
--- httpd-2.4.4/docs/manual/suexec.html.en.r1337344+
+++ httpd-2.4.4/docs/manual/suexec.html.en
@@ -372,6 +372,21 @@
together with the <code>--enable-suexec</code> option to let
APACI accept your request for using the suEXEC feature.</dd>
+ <dt><code>--enable-suexec-capabilities</code></dt>
+
+ <dd><strong>Linux specific:</strong> Normally,
+ the <code>suexec</code> binary is installed "setuid/setgid
+ root", which allows it to run with the full privileges of the
+ root user. If this option is used, the <code>suexec</code>
+ binary will instead be installed with only the setuid/setgid
+ "capability" bits set, which is the subset of full root
+ priviliges required for suexec operation. Note that
+ the <code>suexec</code> binary may not be able to write to a log
+ file in this mode; it is recommended that the
+ <code>--with-suexec-syslog --without-suexec-logfile</code>
+ options are used in conjunction with this mode, so that syslog
+ logging is used instead.</dd>
+
<dt><code>--with-suexec-bin=<em>PATH</em></code></dt>
<dd>The path to the <code>suexec</code> binary must be hard-coded
@@ -433,6 +448,12 @@
"<code>suexec_log</code>" and located in your standard logfile
directory (<code>--logfiledir</code>).</dd>
+ <dt><code>--with-suexec-syslog</code></dt>
+
+ <dd>If defined, suexec will log notices and errors to syslog
+ instead of a logfile. This option must be combined
+ with <code>--without-suexec-logfile</code>.</dd>
+
<dt><code>--with-suexec-safepath=<em>PATH</em></code></dt>
<dd>Define a safe PATH environment to pass to CGI
@@ -550,9 +571,12 @@ Group webgroup
<p>The suEXEC wrapper will write log information
to the file defined with the <code>--with-suexec-logfile</code>
- option as indicated above. If you feel you have configured and
- installed the wrapper properly, have a look at this log and the
- error_log for the server to see where you may have gone astray.</p>
+ option as indicated above, or to syslog if <code>--with-suexec-syslog</code>
+ is used. If you feel you have configured and
+ installed the wrapper properly, have a look at the log and the
+ error_log for the server to see where you may have gone astray.
+ The output of <code>"suexec -V"</code> will show the options
+ used to compile suexec, if using a binary distribution.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
@@ -640,4 +664,4 @@ if (typeof(prettyPrint) !== 'undefined')
prettyPrint();
}
//--><!]]></script>
-</body></html>
\ No newline at end of file
+</body></html>
--- httpd-2.4.4/Makefile.in.r1337344+
+++ httpd-2.4.4/Makefile.in
@@ -238,11 +238,22 @@ install-man:
cd $(DESTDIR)$(manualdir) && find . -name ".svn" -type d -print | xargs rm -rf 2>/dev/null || true; \
fi
-install-suexec:
+install-suexec: install-suexec-binary install-suexec-$(INSTALL_SUEXEC)
+
+install-suexec-binary:
@if test -f $(builddir)/support/suexec; then \
test -d $(DESTDIR)$(sbindir) || $(MKINSTALLDIRS) $(DESTDIR)$(sbindir); \
$(INSTALL_PROGRAM) $(top_builddir)/support/suexec $(DESTDIR)$(sbindir); \
- chmod 4755 $(DESTDIR)$(sbindir)/suexec; \
+ fi
+
+install-suexec-setuid:
+ @if test -f $(builddir)/support/suexec; then \
+ chmod 4755 $(DESTDIR)$(sbindir)/suexec; \
+ fi
+
+install-suexec-caps:
+ @if test -f $(builddir)/support/suexec; then \
+ setcap 'cap_setuid,cap_setgid+pe' $(DESTDIR)$(sbindir)/suexec; \
fi
suexec:
--- httpd-2.4.4/modules/arch/unix/mod_unixd.c.r1337344+
+++ httpd-2.4.4/modules/arch/unix/mod_unixd.c
@@ -284,6 +284,13 @@ unixd_set_suexec(cmd_parms *cmd, void *d
return NULL;
}
+#ifdef AP_SUEXEC_CAPABILITIES
+/* If suexec is using capabilities, don't test for the setuid bit. */
+#define SETUID_TEST(finfo) (1)
+#else
+#define SETUID_TEST(finfo) (finfo.protection & APR_USETID)
+#endif
+
static int
unixd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp)
@@ -300,7 +307,7 @@ unixd_pre_config(apr_pool_t *pconf, apr_
ap_unixd_config.suexec_enabled = 0;
if ((apr_stat(&wrapper, SUEXEC_BIN, APR_FINFO_NORM, ptemp))
== APR_SUCCESS) {
- if ((wrapper.protection & APR_USETID) && wrapper.user == 0
+ if (SETUID_TEST(wrapper) && wrapper.user == 0
&& (access(SUEXEC_BIN, R_OK|X_OK) == 0)) {
ap_unixd_config.suexec_enabled = 1;
ap_unixd_config.suexec_disabled_reason = "";
--- httpd-2.4.4/support/suexec.c.r1337344+
+++ httpd-2.4.4/support/suexec.c
@@ -58,6 +58,10 @@
#include <grp.h>
#endif
+#ifdef AP_LOG_SYSLOG
+#include <syslog.h>
+#endif
+
#if defined(PATH_MAX)
#define AP_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
@@ -69,7 +73,20 @@
#define AP_ENVBUF 256
extern char **environ;
+
+#ifdef AP_LOG_SYSLOG
+/* Syslog support. */
+#if !defined(AP_LOG_FACILITY) && defined(LOG_AUTHPRIV)
+#define AP_LOG_FACILITY LOG_AUTHPRIV
+#elif !defined(AP_LOG_FACILITY)
+#define AP_LOG_FACILITY LOG_AUTH
+#endif
+
+static int log_open;
+#else
+/* Non-syslog support. */
static FILE *log = NULL;
+#endif
static const char *const safe_env_lst[] =
{
@@ -137,7 +154,14 @@ static void err_output(int is_error, con
static void err_output(int is_error, const char *fmt, va_list ap)
{
-#ifdef AP_LOG_EXEC
+#if defined(AP_LOG_SYSLOG)
+ if (!log_open) {
+ openlog("suexec", LOG_PID, AP_LOG_FACILITY);
+ log_open = 1;
+ }
+
+ vsyslog(is_error ? LOG_ERR : LOG_INFO, fmt, ap);
+#elif defined(AP_LOG_EXEC)
time_t timevar;
struct tm *lt;
@@ -295,7 +319,9 @@ int main(int argc, char *argv[])
#ifdef AP_HTTPD_USER
fprintf(stderr, " -D AP_HTTPD_USER=\"%s\"\n", AP_HTTPD_USER);
#endif
-#ifdef AP_LOG_EXEC
+#if defined(AP_LOG_SYSLOG)
+ fprintf(stderr, " -D AP_LOG_SYSLOG\n");
+#elif defined(AP_LOG_EXEC)
fprintf(stderr, " -D AP_LOG_EXEC=\"%s\"\n", AP_LOG_EXEC);
#endif
#ifdef AP_SAFE_PATH
@@ -591,6 +617,12 @@ int main(int argc, char *argv[])
#endif /* AP_SUEXEC_UMASK */
/* Be sure to close the log file so the CGI can't mess with it. */
+#ifdef AP_LOG_SYSLOG
+ if (log_open) {
+ closelog();
+ log_open = 0;
+ }
+#else
if (log != NULL) {
#if APR_HAVE_FCNTL_H
/*
@@ -612,6 +644,7 @@ int main(int argc, char *argv[])
log = NULL;
#endif
}
+#endif
/*
* Execute the command, replacing our image with its own.

25
SOURCES/httpd-2.4.6-CVE-2013-4352.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
--- a/modules/cache/cache_storage.c 2013/09/14 13:30:39 1523234
+++ b/modules/cache/cache_storage.c 2013/09/14 13:32:25 1523235
@@ -713,7 +713,9 @@
|| APR_SUCCESS
!= cache_canonicalise_key(r, r->pool, location,
&location_uri, &location_key)
- || strcmp(r->parsed_uri.hostname, location_uri.hostname)) {
+ || !(r->parsed_uri.hostname && location_uri.hostname
+ && !strcmp(r->parsed_uri.hostname,
+ location_uri.hostname))) {
location_key = NULL;
}
}
@@ -726,8 +728,9 @@
|| APR_SUCCESS
!= cache_canonicalise_key(r, r->pool, content_location,
&content_location_uri, &content_location_key)
- || strcmp(r->parsed_uri.hostname,
- content_location_uri.hostname)) {
+ || !(r->parsed_uri.hostname && content_location_uri.hostname
+ && !strcmp(r->parsed_uri.hostname,
+ content_location_uri.hostname))) {
content_location_key = NULL;
}
}

381
SOURCES/httpd-2.4.6-CVE-2013-5704.patch

@ -0,0 +1,381 @@ @@ -0,0 +1,381 @@
diff --git a/include/http_core.h b/include/http_core.h
index 3c47989..f6f4aa2 100644
--- a/include/http_core.h
+++ b/include/http_core.h
@@ -663,6 +663,10 @@ typedef struct {
#define AP_TRACE_ENABLE 1
#define AP_TRACE_EXTENDED 2
int trace_enable;
+#define AP_MERGE_TRAILERS_UNSET 0
+#define AP_MERGE_TRAILERS_ENABLE 1
+#define AP_MERGE_TRAILERS_DISABLE 2
+ int merge_trailers;
} core_server_config;
diff --git a/include/httpd.h b/include/httpd.h
index 36cd58d..2e415f9 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -1032,6 +1032,11 @@ struct request_rec {
*/
apr_sockaddr_t *useragent_addr;
char *useragent_ip;
+
+ /** MIME trailer environment from the request */
+ apr_table_t *trailers_in;
+ /** MIME trailer environment from the response */
+ apr_table_t *trailers_out;
};
/**
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 24a939a..2ae8f46 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -214,6 +214,49 @@ static apr_status_t get_chunk_line(http_ctx_t *ctx, apr_bucket_brigade *b,
}
+static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
+ apr_bucket_brigade *b, int merge)
+{
+ int rv;
+ apr_bucket *e;
+ request_rec *r = f->r;
+ apr_table_t *saved_headers_in = r->headers_in;
+ int saved_status = r->status;
+
+ r->status = HTTP_OK;
+ r->headers_in = r->trailers_in;
+ apr_table_clear(r->headers_in);
+ ctx->state = BODY_NONE;
+ ap_get_mime_headers(r);
+
+ if(r->status == HTTP_OK) {
+ r->status = saved_status;
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ ctx->eos_sent = 1;
+ rv = APR_SUCCESS;
+ }
+ else {
+ const char *error_notes = apr_table_get(r->notes,
+ "error-notes");
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
+ "Error while reading HTTP trailer: %i%s%s",
+ r->status, error_notes ? ": " : "",
+ error_notes ? error_notes : "");
+ rv = APR_EINVAL;
+ }
+
+ if(!merge) {
+ r->headers_in = saved_headers_in;
+ }
+ else {
+ r->headers_in = apr_table_overlay(r->pool, saved_headers_in,
+ r->trailers_in);
+ }
+
+ return rv;
+}
+
/* This is the HTTP_INPUT filter for HTTP requests and responses from
* proxied servers (mod_proxy). It handles chunked and content-length
* bodies. This can only be inserted/used after the headers
@@ -223,6 +266,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
ap_input_mode_t mode, apr_read_type_e block,
apr_off_t readbytes)
{
+ core_server_config *conf;
apr_bucket *e;
http_ctx_t *ctx = f->ctx;
apr_status_t rv;
@@ -230,6 +274,9 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
apr_bucket_brigade *bb;
+ conf = (core_server_config *)
+ ap_get_module_config(f->r->server->module_config, &core_module);
+
/* just get out of the way of things we don't want. */
if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
return ap_get_brigade(f->next, b, mode, block, readbytes);
@@ -403,13 +450,8 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
}
if (!ctx->remaining) {
- /* Handle trailers by calling ap_get_mime_headers again! */
- ctx->state = BODY_NONE;
- ap_get_mime_headers(f->r);
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- ctx->eos_sent = 1;
- return APR_SUCCESS;
+ return read_chunked_trailers(ctx, f, b,
+ conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
}
}
}
@@ -509,13 +551,8 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
}
if (!ctx->remaining) {
- /* Handle trailers by calling ap_get_mime_headers again! */
- ctx->state = BODY_NONE;
- ap_get_mime_headers(f->r);
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- ctx->eos_sent = 1;
- return APR_SUCCESS;
+ return read_chunked_trailers(ctx, f, b,
+ conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
}
}
break;
diff --git a/modules/http/http_request.c b/modules/http/http_request.c
index 796d506..cdfec8b 100644
--- a/modules/http/http_request.c
+++ b/modules/http/http_request.c
@@ -463,6 +463,7 @@ static request_rec *internal_internal_redirect(const char *new_uri,
new->main = r->main;
new->headers_in = r->headers_in;
+ new->trailers_in = r->trailers_in;
new->headers_out = apr_table_make(r->pool, 12);
if (ap_is_HTTP_REDIRECT(new->status)) {
const char *location = apr_table_get(r->headers_out, "Location");
@@ -470,6 +471,7 @@ static request_rec *internal_internal_redirect(const char *new_uri,
apr_table_setn(new->headers_out, "Location", location);
}
new->err_headers_out = r->err_headers_out;
+ new->trailers_out = apr_table_make(r->pool, 5);
new->subprocess_env = rename_original_env(r->pool, r->subprocess_env);
new->notes = apr_table_make(r->pool, 5);
@@ -583,6 +585,8 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r)
r->headers_out);
r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out,
r->err_headers_out);
+ r->trailers_out = apr_table_overlay(r->pool, rr->trailers_out,
+ r->trailers_out);
r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env,
r->subprocess_env);
diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c
index 25f5030..b021dd3 100644
--- a/modules/loggers/mod_log_config.c
+++ b/modules/loggers/mod_log_config.c
@@ -431,6 +431,12 @@ static const char *log_header_in(request_rec *r, char *a)
return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a));
}
+static const char *log_trailer_in(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, apr_table_get(r->trailers_in, a));
+}
+
+
static APR_INLINE char *find_multiple_headers(apr_pool_t *pool,
const apr_table_t *table,
const char *key)
@@ -514,6 +520,11 @@ static const char *log_header_out(request_rec *r, char *a)
return ap_escape_logitem(r->pool, cp);
}
+static const char *log_trailer_out(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, apr_table_get(r->trailers_out, a));
+}
+
static const char *log_note(request_rec *r, char *a)
{
return ap_escape_logitem(r->pool, apr_table_get(r->notes, a));
@@ -916,7 +927,7 @@ static char *parse_log_misc_string(apr_pool_t *p, log_format_item *it,
static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
{
const char *s = *sa;
- ap_log_handler *handler;
+ ap_log_handler *handler = NULL;
if (*s != '%') {
return parse_log_misc_string(p, it, sa);
@@ -986,7 +997,16 @@ static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
break;
default:
- handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
+ /* check for '^' + two character format first */
+ if (*s == '^' && *(s+1) && *(s+2)) {
+ handler = (ap_log_handler *)apr_hash_get(log_hash, s, 3);
+ if (handler) {
+ s += 3;
+ }
+ }
+ if (!handler) {
+ handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
+ }
if (!handler) {
char dummy[2];
@@ -1516,7 +1536,7 @@ static void ap_register_log_handler(apr_pool_t *p, char *tag,
log_struct->func = handler;
log_struct->want_orig_default = def;
- apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
+ apr_hash_set(log_hash, tag, strlen(tag), (const void *)log_struct);
}
static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle)
{
@@ -1686,6 +1706,9 @@ static int log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
log_pfn_register(p, "U", log_request_uri, 1);
log_pfn_register(p, "s", log_status, 1);
log_pfn_register(p, "R", log_handler, 1);
+
+ log_pfn_register(p, "^ti", log_trailer_in, 0);
+ log_pfn_register(p, "^to", log_trailer_out, 0);
}
/* reset to default conditions */
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 7ae0fa4..05f33b4 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -994,8 +994,11 @@ static request_rec *make_fake_req(conn_rec *c, request_rec *r)
rp->status = HTTP_OK;
rp->headers_in = apr_table_make(pool, 50);
+ rp->trailers_in = apr_table_make(pool, 5);
+
rp->subprocess_env = apr_table_make(pool, 50);
rp->headers_out = apr_table_make(pool, 12);
+ rp->trailers_out = apr_table_make(pool, 5);
rp->err_headers_out = apr_table_make(pool, 5);
rp->notes = apr_table_make(pool, 5);
@@ -1076,6 +1079,7 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr,
psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
r->headers_out = apr_table_make(r->pool, 20);
+ r->trailers_out = apr_table_make(r->pool, 5);
*pread_len = 0;
/*
@@ -1206,6 +1210,14 @@ apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec
#define AP_MAX_INTERIM_RESPONSES 10
#endif
+static int add_trailers(void *data, const char *key, const char *val)
+{
+ if (val) {
+ apr_table_add((apr_table_t*)data, key, val);
+ }
+ return 1;
+}
+
static
apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
proxy_conn_rec **backend_ptr,
@@ -1717,6 +1729,12 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
/* next time try a non-blocking read */
mode = APR_NONBLOCK_READ;
+ if (!apr_is_empty_table(backend->r->trailers_in)) {
+ apr_table_do(add_trailers, r->trailers_out,
+ backend->r->trailers_in, NULL);
+ apr_table_clear(backend->r->trailers_in);
+ }
+
apr_brigade_length(bb, 0, &readbytes);
backend->worker->s->read += readbytes;
#if DEBUGGING
diff --git a/server/core.c b/server/core.c
index 024bab6..7cfde63 100644
--- a/server/core.c
+++ b/server/core.c
@@ -523,6 +523,10 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
if (virt->error_log_req)
conf->error_log_req = virt->error_log_req;
+ conf->merge_trailers = (virt->merge_trailers != AP_MERGE_TRAILERS_UNSET)
+ ? virt->merge_trailers
+ : base->merge_trailers;
+
return conf;
}
@@ -3877,6 +3881,16 @@ AP_DECLARE(void) ap_register_errorlog_handler(apr_pool_t *p, char *tag,
}
+static const char *set_merge_trailers(cmd_parms *cmd, void *dummy, int arg)
+{
+ core_server_config *conf = ap_get_module_config(cmd->server->module_config,
+ &core_module);
+ conf->merge_trailers = (arg ? AP_MERGE_TRAILERS_ENABLE :
+ AP_MERGE_TRAILERS_DISABLE);
+
+ return NULL;
+}
+
/* Note --- ErrorDocument will now work from .htaccess files.
* The AllowOverride of Fileinfo allows webmasters to turn it off
*/
@@ -4124,6 +4138,8 @@ AP_INIT_TAKE1("EnableExceptionHook", ap_mpm_set_exception_hook, NULL, RSRC_CONF,
#endif
AP_INIT_TAKE1("TraceEnable", set_trace_enable, NULL, RSRC_CONF,
"'on' (default), 'off' or 'extended' to trace request body content"),
+AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF,
+ "merge request trailers into request headers or not"),
{ NULL }
};
@@ -4206,7 +4222,6 @@ static int core_map_to_storage(request_rec *r)
static int do_nothing(request_rec *r) { return OK; }
-
static int core_override_type(request_rec *r)
{
core_dir_config *conf =
diff --git a/server/protocol.c b/server/protocol.c
index 14329eb..46fc034 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -718,6 +718,8 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb
r->status = HTTP_REQUEST_TIME_OUT;
}
else {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
+ "Failed to read request header line %s", field);
r->status = HTTP_BAD_REQUEST;
}
@@ -917,9 +919,11 @@ request_rec *ap_read_request(conn_rec *conn)
r->allowed_methods = ap_make_method_list(p, 2);
r->headers_in = apr_table_make(r->pool, 25);
+ r->trailers_in = apr_table_make(r->pool, 5);
r->subprocess_env = apr_table_make(r->pool, 25);
r->headers_out = apr_table_make(r->pool, 12);
r->err_headers_out = apr_table_make(r->pool, 5);
+ r->trailers_out = apr_table_make(r->pool, 5);
r->notes = apr_table_make(r->pool, 5);
r->request_config = ap_create_request_config(r->pool);
@@ -1162,6 +1166,7 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew,
rnew->status = HTTP_OK;
rnew->headers_in = apr_table_copy(rnew->pool, r->headers_in);
+ rnew->trailers_in = apr_table_copy(rnew->pool, r->trailers_in);
/* did the original request have a body? (e.g. POST w/SSI tags)
* if so, make sure the subrequest doesn't inherit body headers
@@ -1173,6 +1178,7 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew,
rnew->subprocess_env = apr_table_copy(rnew->pool, r->subprocess_env);
rnew->headers_out = apr_table_make(rnew->pool, 5);
rnew->err_headers_out = apr_table_make(rnew->pool, 5);
+ rnew->trailers_out = apr_table_make(rnew->pool, 5);
rnew->notes = apr_table_make(rnew->pool, 5);
rnew->expecting_100 = r->expecting_100;

14
SOURCES/httpd-2.4.6-CVE-2013-6438.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
--- a/modules/dav/main/util.c 2014/01/09 14:28:39 1556815
+++ b/modules/dav/main/util.c 2014/01/09 14:29:47 1556816
@@ -396,8 +396,10 @@
if (strip_white) {
/* trim leading whitespace */
- while (apr_isspace(*cdata)) /* assume: return false for '\0' */
+ while (apr_isspace(*cdata)) { /* assume: return false for '\0' */
++cdata;
+ --len;
+ }
/* trim trailing whitespace */
while (len-- > 0 && apr_isspace(cdata[len]))

41
SOURCES/httpd-2.4.6-CVE-2014-0098.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
--- a/modules/loggers/mod_log_config.c 2013/11/15 17:07:52 1542329
+++ b/modules/loggers/mod_log_config.c 2014/03/10 11:23:47 1575904
@@ -543,14 +543,24 @@
while ((cookie = apr_strtok(cookies, ";", &last1))) {
char *name = apr_strtok(cookie, "=", &last2);
- if (name) {
- char *value = name + strlen(name) + 1;
- apr_collapse_spaces(name, name);
+ /* last2 points to the next char following an '=' delim,
+ or the trailing NUL char of the string */
+ char *value = last2;
+ if (name && *name && value && *value) {
+ char *last = value - 2;
+ /* Move past leading WS */
+ name += strspn(name, " \t");
+ while (last >= name && apr_isspace(*last)) {
+ *last = '\0';
+ --last;
+ }
if (!strcasecmp(name, a)) {
- char *last;
- value += strspn(value, " \t"); /* Move past leading WS */
- last = value + strlen(value) - 1;
+ /* last1 points to the next char following the ';' delim,
+ or the trailing NUL char of the string */
+ last = last1 - (*last1 ? 2 : 1);
+ /* Move past leading WS */
+ value += strspn(value, " \t");
while (last >= value && apr_isspace(*last)) {
*last = '\0';
--last;
@@ -559,6 +569,7 @@
return ap_escape_logitem(r->pool, value);
}
}
+ /* Iterate the remaining tokens using apr_strtok(NULL, ...) */
cookies = NULL;
}
}

11
SOURCES/httpd-2.4.6-CVE-2014-0117.patch

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
--- a/modules/proxy/proxy_util.c 2014/07/15 16:07:44 1610736
+++ b/modules/proxy/proxy_util.c 2014/07/15 16:11:04 1610737
@@ -3132,7 +3132,7 @@
const char *name;
do {
- while (*val == ',') {
+ while (*val == ',' || *val == ';') {
val++;
}
name = ap_get_token(x->pool, &val, 0);

266
SOURCES/httpd-2.4.6-CVE-2014-0118.patch

@ -0,0 +1,266 @@ @@ -0,0 +1,266 @@
diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
index 79f6f8d..6c415c8 100644
--- a/modules/filters/mod_deflate.c
+++ b/modules/filters/mod_deflate.c
@@ -37,6 +37,7 @@
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
+#include "http_core.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "apr_general.h"
@@ -52,6 +53,9 @@
static const char deflateFilterName[] = "DEFLATE";
module AP_MODULE_DECLARE_DATA deflate_module;
+#define AP_INFLATE_RATIO_LIMIT 200
+#define AP_INFLATE_RATIO_BURST 3
+
typedef struct deflate_filter_config_t
{
int windowSize;
@@ -63,6 +67,12 @@ typedef struct deflate_filter_config_t
char *note_output_name;
} deflate_filter_config;
+typedef struct deflate_dirconf_t {
+ apr_off_t inflate_limit;
+ int ratio_limit,
+ ratio_burst;
+} deflate_dirconf_t;
+
/* RFC 1952 Section 2.3 defines the gzip header:
*
* +---+---+---+---+---+---+---+---+---+---+
@@ -204,6 +214,14 @@ static void *create_deflate_server_config(apr_pool_t *p, server_rec *s)
return c;
}
+static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
+{
+ deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
+ dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
+ dc->ratio_burst = AP_INFLATE_RATIO_BURST;
+ return dc;
+}
+
static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
const char *arg)
{
@@ -295,6 +313,55 @@ static const char *deflate_set_compressionlevel(cmd_parms *cmd, void *dummy,
return NULL;
}
+
+static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
+ const char *arg)
+{
+ deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
+ char *errp;
+
+ if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
+ return "DeflateInflateLimitRequestBody is not parsable.";
+ }
+ if (*errp || dc->inflate_limit < 0) {
+ return "DeflateInflateLimitRequestBody requires a non-negative integer.";
+ }
+
+ return NULL;
+}
+
+static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
+ void *dirconf,
+ const char *arg)
+{
+ deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
+ int i;
+
+ i = atoi(arg);
+ if (i <= 0)
+ return "DeflateInflateRatioLimit must be positive";
+
+ dc->ratio_limit = i;
+
+ return NULL;
+}
+
+static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
+ void *dirconf,
+ const char *arg)
+{
+ deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
+ int i;
+
+ i = atoi(arg);
+ if (i <= 0)
+ return "DeflateInflateRatioBurst must be positive";
+
+ dc->ratio_burst = i;
+
+ return NULL;
+}
+
typedef struct deflate_ctx_t
{
z_stream stream;
@@ -304,6 +371,8 @@ typedef struct deflate_ctx_t
int (*libz_end_func)(z_streamp);
unsigned char *validation_buffer;
apr_size_t validation_buffer_length;
+ int ratio_hits;
+ apr_off_t inflate_total;
unsigned int inflate_init:1;
unsigned int filter_init:1;
unsigned int done:1;
@@ -422,6 +491,22 @@ static void deflate_check_etag(request_rec *r, const char *transform)
}
}
+/* Check whether the (inflate) ratio exceeds the configured limit/burst. */
+static int check_ratio(request_rec *r, deflate_ctx *ctx,
+ const deflate_dirconf_t *dc)
+{
+ if (ctx->stream.total_in) {
+ int ratio = ctx->stream.total_out / ctx->stream.total_in;
+ if (ratio < dc->ratio_limit) {
+ ctx->ratio_hits = 0;
+ }
+ else if (++ctx->ratio_hits > dc->ratio_burst) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
static int have_ssl_compression(request_rec *r)
{
const char *comp;
@@ -897,6 +982,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
int zRC;
apr_status_t rv;
deflate_filter_config *c;
+ deflate_dirconf_t *dc;
+ apr_off_t inflate_limit;
/* just get out of the way of things we don't want. */
if (mode != AP_MODE_READBYTES) {
@@ -904,6 +991,7 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
}
c = ap_get_module_config(r->server->module_config, &deflate_module);
+ dc = ap_get_module_config(r->per_dir_config, &deflate_module);
if (!ctx) {
char deflate_hdr[10];
@@ -994,6 +1082,12 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
apr_brigade_cleanup(ctx->bb);
}
+ inflate_limit = dc->inflate_limit;
+ if (inflate_limit == 0) {
+ /* The core is checking the deflated body, we'll check the inflated */
+ inflate_limit = ap_get_limit_req_body(f->r);
+ }
+
if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
@@ -1038,6 +1132,17 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;
+
+ ctx->inflate_total += len;
+ if (inflate_limit && ctx->inflate_total > inflate_limit) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02647)
+ "Inflated content length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT,
+ ctx->inflate_total, inflate_limit);
+ return APR_ENOSPC;
+ }
ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
@@ -1073,6 +1178,26 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;
+ ctx->inflate_total += len;
+ if (inflate_limit && ctx->inflate_total > inflate_limit) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02648)
+ "Inflated content length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT,
+ ctx->inflate_total, inflate_limit);
+ return APR_ENOSPC;
+ }
+
+ if (!check_ratio(r, ctx, dc)) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02649)
+ "Inflated content ratio is larger than the "
+ "configured limit %i by %i time(s)",
+ dc->ratio_limit, dc->ratio_burst);
+ return APR_EINVAL;
+ }
+
ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
NULL, f->c->bucket_alloc);
@@ -1193,6 +1318,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
int zRC;
apr_status_t rv;
deflate_filter_config *c;
+ deflate_dirconf_t *dc;
/* Do nothing if asked to filter nothing. */
if (APR_BRIGADE_EMPTY(bb)) {
@@ -1200,6 +1326,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
}
c = ap_get_module_config(r->server->module_config, &deflate_module);
+ dc = ap_get_module_config(r->per_dir_config, &deflate_module);
if (!ctx) {
@@ -1462,6 +1589,14 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
+ if (!check_ratio(r, ctx, dc)) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02650)
+ "Inflated content ratio is larger than the "
+ "configured limit %i by %i time(s)",
+ dc->ratio_limit, dc->ratio_burst);
+ return APR_EINVAL;
+ }
+
ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;
@@ -1548,12 +1683,20 @@ static const command_rec deflate_filter_cmds[] = {
"Set the Deflate Memory Level (1-9)"),
AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
"Set the Deflate Compression Level (1-9)"),
+ AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
+ "Set a limit on size of inflated input"),
+ AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
+ "Set the inflate ratio limit above which inflation is "
+ "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
+ AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
+ "Set the maximum number of following inflate ratios above limit "
+ "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
{NULL}
};
AP_DECLARE_MODULE(deflate) = {
STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
+ create_deflate_dirconf, /* dir config creater */
NULL, /* dir merger --- default is to override */
create_deflate_server_config, /* server config */
NULL, /* merge server config */

119
SOURCES/httpd-2.4.6-CVE-2014-0226.patch

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
Index: server/scoreboard.c
===================================================================
--- a/server/scoreboard.c (revision 1610498)
+++ b/server/scoreboard.c (revision 1610499)
@@ -579,6 +579,21 @@
sbh->thread_num);
}
+AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest,
+ int child_num,
+ int thread_num)
+{
+ worker_score *ws = ap_get_scoreboard_worker_from_indexes(child_num, thread_num);
+
+ memcpy(dest, ws, sizeof *ws);
+
+ /* For extra safety, NUL-terminate the strings returned, though it
+ * should be true those last bytes are always zero anyway. */
+ dest->client[sizeof(dest->client) - 1] = '\0';
+ dest->request[sizeof(dest->request) - 1] = '\0';
+ dest->vhost[sizeof(dest->vhost) - 1] = '\0';
+}
+
AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
{
if ((x < 0) || (x >= server_limit)) {
Index: modules/generators/mod_status.c
===================================================================
--- a/modules/generators/mod_status.c (revision 1610498)
+++ b/modules/generators/mod_status.c (revision 1610499)
@@ -194,7 +194,7 @@
long req_time;
int short_report;
int no_table_report;
- worker_score *ws_record;
+ worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
process_score *ps_record;
char *stat_buffer;
pid_t *pid_buffer, worker_pid;
@@ -306,7 +306,7 @@
for (j = 0; j < thread_limit; ++j) {
int indx = (i * thread_limit) + j;
- ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
+ ap_copy_scoreboard_worker(ws_record, i, j);
res = ws_record->status;
if ((i >= max_servers || j >= threads_per_child)
@@ -637,7 +637,7 @@
for (i = 0; i < server_limit; ++i) {
for (j = 0; j < thread_limit; ++j) {
- ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
+ ap_copy_scoreboard_worker(ws_record, i, j);
if (ws_record->access_count == 0 &&
(ws_record->status == SERVER_READY ||
Index: modules/lua/lua_request.c
===================================================================
--- a/modules/lua/lua_request.c (revision 1610498)
+++ b/modules/lua/lua_request.c (revision 1610499)
@@ -1245,16 +1245,22 @@
*/
static int lua_ap_scoreboard_worker(lua_State *L)
{
- int i,
- j;
- worker_score *ws_record;
+ int i, j;
+ worker_score *ws_record = NULL;
+ request_rec *r = NULL;
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TNUMBER);
luaL_checktype(L, 3, LUA_TNUMBER);
+
+ r = ap_lua_check_request_rec(L, 1);
+ if (!r) return 0;
+
i = lua_tointeger(L, 2);
j = lua_tointeger(L, 3);
- ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
+ ws_record = apr_palloc(r->pool, sizeof *ws_record);
+
+ ap_copy_scoreboard_worker(ws_record, i, j);
if (ws_record) {
lua_newtable(L);
Index: include/scoreboard.h
===================================================================
--- a/include/scoreboard.h (revision 1610498)
+++ b/include/scoreboard.h (revision 1610499)
@@ -183,8 +183,25 @@
AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status);
AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh);
+
+/** Return a pointer to the worker_score for a given child, thread pair.
+ * @param child_num The child number.
+ * @param thread_num The thread number.
+ * @return A pointer to the worker_score structure.
+ * @deprecated This function is deprecated, use ap_copy_scoreboard_worker instead. */
AP_DECLARE(worker_score *) ap_get_scoreboard_worker_from_indexes(int child_num,
int thread_num);
+
+/** Copy the contents of a worker scoreboard entry. The contents of
+ * the worker_score structure are copied verbatim into the dest
+ * structure.
+ * @param dest Output parameter.
+ * @param child_num The child number.
+ * @param thread_num The thread number.
+ */
+AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest,
+ int child_num, int thread_num);
+
AP_DECLARE(process_score *) ap_get_scoreboard_process(int x);
AP_DECLARE(global_score *) ap_get_scoreboard_global(void);

144
SOURCES/httpd-2.4.6-CVE-2014-0231.patch

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
--- a/modules/generators/mod_cgid.c 2014/07/14 20:16:45 1610511
+++ b/modules/generators/mod_cgid.c 2014/07/14 20:18:26 1610512
@@ -97,6 +97,10 @@
static pid_t parent_pid;
static ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
+typedef struct {
+ apr_interval_time_t timeout;
+} cgid_dirconf;
+
/* The APR other-child API doesn't tell us how the daemon exited
* (SIGSEGV vs. exit(1)). The other-child maintenance function
* needs to decide whether to restart the daemon after a failure
@@ -968,7 +972,14 @@
return overrides->logname ? overrides : base;
}
+static void *create_cgid_dirconf(apr_pool_t *p, char *dummy)
+{
+ cgid_dirconf *c = (cgid_dirconf *) apr_pcalloc(p, sizeof(cgid_dirconf));
+ return c;
+}
+
static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
+
{
server_rec *s = cmd->server;
cgid_server_conf *conf = ap_get_module_config(s->module_config,
@@ -1021,7 +1032,16 @@
return NULL;
}
+static const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ cgid_dirconf *dc = dummy;
+ if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) {
+ return "CGIDScriptTimeout has wrong format";
+ }
+
+ return NULL;
+}
static const command_rec cgid_cmds[] =
{
AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
@@ -1033,6 +1053,10 @@
AP_INIT_TAKE1("ScriptSock", set_script_socket, NULL, RSRC_CONF,
"the name of the socket to use for communication with "
"the cgi daemon."),
+ AP_INIT_TAKE1("CGIDScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF,
+ "The amount of time to wait between successful reads from "
+ "the CGI script, in seconds."),
+
{NULL}
};
@@ -1356,12 +1380,16 @@
apr_file_t *tempsock;
struct cleanup_script_info *info;
apr_status_t rv;
+ cgid_dirconf *dc;
if (strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script")) {
return DECLINED;
}
conf = ap_get_module_config(r->server->module_config, &cgid_module);
+ dc = ap_get_module_config(r->per_dir_config, &cgid_module);
+
+
is_included = !strcmp(r->protocol, "INCLUDED");
if ((argv0 = strrchr(r->filename, '/')) != NULL) {
@@ -1441,6 +1469,12 @@
*/
apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
+ if (dc->timeout > 0) {
+ apr_file_pipe_timeout_set(tempsock, dc->timeout);
+ }
+ else {
+ apr_file_pipe_timeout_set(tempsock, r->server->timeout);
+ }
apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
/* Transfer any put/post args, CERN style...
@@ -1517,6 +1551,10 @@
if (rv != APR_SUCCESS) {
/* silly script stopped reading, soak up remaining message */
child_stopped_reading = 1;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02651)
+ "Error writing request body to script %s",
+ r->filename);
+
}
}
apr_brigade_cleanup(bb);
@@ -1610,7 +1648,13 @@
return HTTP_MOVED_TEMPORARILY;
}
- ap_pass_brigade(r->output_filters, bb);
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if (rv != APR_SUCCESS) {
+ /* APLOG_ERR because the core output filter message is at error,
+ * but doesn't know it's passing CGI output
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02550) "Failed to flush CGI output to client");
+ }
}
if (nph) {
@@ -1741,6 +1785,8 @@
request_rec *r = f->r;
cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
&cgid_module);
+ cgid_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgid_module);
+
struct cleanup_script_info *info;
add_ssi_vars(r);
@@ -1770,6 +1816,13 @@
* get rid of the cleanup we registered when we created the socket.
*/
apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
+ if (dc->timeout > 0) {
+ apr_file_pipe_timeout_set(tempsock, dc->timeout);
+ }
+ else {
+ apr_file_pipe_timeout_set(tempsock, r->server->timeout);
+ }
+
apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(tempsock,
@@ -1875,7 +1928,7 @@
AP_DECLARE_MODULE(cgid) = {
STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
+ create_cgid_dirconf, /* dir config creater */
NULL, /* dir merger --- default is to override */
create_cgid_config, /* server config */
merge_cgid_config, /* merge server config */

17
SOURCES/httpd-2.4.6-CVE-2014-3581.patch

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c
index 7b7fb45..fbebb1e 100644
--- a/modules/cache/cache_util.c
+++ b/modules/cache/cache_util.c
@@ -1251,8 +1251,10 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_headers_out(request_rec *r)
if (!apr_table_get(headers_out, "Content-Type")
&& r->content_type) {
- apr_table_setn(headers_out, "Content-Type",
- ap_make_content_type(r, r->content_type));
+ const char *ctype = ap_make_content_type(r, r->content_type);
+ if (ctype) {
+ apr_table_setn(headers_out, "Content-Type", ctype);
+ }
}
if (!apr_table_get(headers_out, "Content-Encoding")

982
SOURCES/httpd-2.4.6-CVE-2015-3183.patch

@ -0,0 +1,982 @@ @@ -0,0 +1,982 @@
diff --git a/include/http_protocol.h b/include/http_protocol.h
index 415270b..67fa02f 100644
--- a/include/http_protocol.h
+++ b/include/http_protocol.h
@@ -502,6 +502,23 @@ AP_DECLARE(int) ap_should_client_block(request_rec *r);
*/
AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, apr_size_t bufsiz);
+/*
+ * Map specific APR codes returned by the filter stack to HTTP error
+ * codes, or the default status code provided. Use it as follows:
+ *
+ * return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+ *
+ * If the filter has already handled the error, AP_FILTER_ERROR will
+ * be returned, which is cleanly passed through.
+ *
+ * These mappings imply that the filter stack is reading from the
+ * downstream client, the proxy will map these codes differently.
+ * @param rv APR status code
+ * @param status Default HTTP code should the APR code not be recognised
+ * @return Mapped HTTP status code
+ */
+AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status);
+
/**
* In HTTP/1.1, any method can have a body. However, most GET handlers
* wouldn't know what to do with a request body if they received one.
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 1dde402..ed8749f 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -57,24 +57,29 @@
APLOG_USE_MODULE(http);
-#define INVALID_CHAR -2
-
-static long get_chunk_size(char *);
-
-typedef struct http_filter_ctx {
+typedef struct http_filter_ctx
+{
apr_off_t remaining;
apr_off_t limit;
apr_off_t limit_used;
- enum {
- BODY_NONE,
- BODY_LENGTH,
- BODY_CHUNK,
- BODY_CHUNK_PART
+ apr_int32_t chunk_used;
+ apr_int32_t chunk_bws;
+ apr_int32_t chunkbits;
+ enum
+ {
+ BODY_NONE, /* streamed data */
+ BODY_LENGTH, /* data constrained by content length */
+ BODY_CHUNK, /* chunk expected */
+ BODY_CHUNK_PART, /* chunk digits */
+ BODY_CHUNK_EXT, /* chunk extension */
+ BODY_CHUNK_CR, /* got space(s) after digits, expect [CR]LF or ext */
+ BODY_CHUNK_LF, /* got CR after digits or ext, expect LF */
+ BODY_CHUNK_DATA, /* data constrained by chunked encoding */
+ BODY_CHUNK_END, /* chunked data terminating CRLF */
+ BODY_CHUNK_END_LF, /* got CR after data, expect LF */
+ BODY_CHUNK_TRAILER /* trailers */
} state;
- int eos_sent;
- char chunk_ln[32];
- char *pos;
- apr_off_t linesize;
+ unsigned int eos_sent :1;
apr_bucket_brigade *bb;
} http_ctx_t;
@@ -87,6 +92,23 @@ static apr_status_t bail_out_on_error(http_ctx_t *ctx,
apr_bucket_brigade *bb = ctx->bb;
apr_brigade_cleanup(bb);
+
+ if (f->r->proxyreq == PROXYREQ_RESPONSE) {
+ switch (http_error) {
+ case HTTP_REQUEST_ENTITY_TOO_LARGE:
+ return APR_ENOSPC;
+
+ case HTTP_REQUEST_TIME_OUT:
+ return APR_INCOMPLETE;
+
+ case HTTP_NOT_IMPLEMENTED:
+ return APR_ENOTIMPL;
+
+ default:
+ return APR_EGENERAL;
+ }
+ }
+
e = ap_bucket_error_create(http_error,
NULL, f->r->pool,
f->c->bucket_alloc);
@@ -102,117 +124,154 @@ static apr_status_t bail_out_on_error(http_ctx_t *ctx,
return ap_pass_brigade(f->r->output_filters, bb);
}
-static apr_status_t get_remaining_chunk_line(http_ctx_t *ctx,
- apr_bucket_brigade *b,
- int linelimit)
+/**
+ * Parse a chunk line with optional extension, detect overflow.
+ * There are two error cases:
+ * 1) If the conversion would require too many bits, APR_EGENERAL is returned.
+ * 2) If the conversion used the correct number of bits, but an overflow
+ * caused only the sign bit to flip, then APR_ENOSPC is returned.
+ * In general, any negative number can be considered an overflow error.
+ */
+static apr_status_t parse_chunk_size(http_ctx_t *ctx, const char *buffer,
+ apr_size_t len, int linelimit)
{
- apr_status_t rv;
- apr_off_t brigade_length;
- apr_bucket *e;
- const char *lineend;
- apr_size_t len = 0;
+ apr_size_t i = 0;
- /*
- * As the brigade b should have been requested in mode AP_MODE_GETLINE
- * all buckets in this brigade are already some type of memory
- * buckets (due to the needed scanning for LF in mode AP_MODE_GETLINE)
- * or META buckets.
- */
- rv = apr_brigade_length(b, 0, &brigade_length);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- /* Sanity check. Should never happen. See above. */
- if (brigade_length == -1) {
- return APR_EGENERAL;
- }
- if (!brigade_length) {
- return APR_EAGAIN;
- }
- ctx->linesize += brigade_length;
- if (ctx->linesize > linelimit) {
- return APR_ENOSPC;
- }
- /*
- * As all buckets are already some type of memory buckets or META buckets
- * (see above), we only need to check the last byte in the last data bucket.
- */
- for (e = APR_BRIGADE_LAST(b);
- e != APR_BRIGADE_SENTINEL(b);
- e = APR_BUCKET_PREV(e)) {
+ while (i < len) {
+ char c = buffer[i];
+
+ ap_xlate_proto_from_ascii(&c, 1);
- if (APR_BUCKET_IS_METADATA(e)) {
+ /* handle CRLF after the chunk */
+ if (ctx->state == BODY_CHUNK_END
+ || ctx->state == BODY_CHUNK_END_LF) {
+ if (c == LF) {
+ ctx->state = BODY_CHUNK;
+ }
+ else if (c == CR && ctx->state == BODY_CHUNK_END) {
+ ctx->state = BODY_CHUNK_END_LF;
+ }
+ else {
+ /*
+ * LF expected.
+ */
+ return APR_EINVAL;
+ }
+ i++;
continue;
}
- rv = apr_bucket_read(e, &lineend, &len, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- return rv;
+
+ /* handle start of the chunk */
+ if (ctx->state == BODY_CHUNK) {
+ if (!apr_isxdigit(c)) {
+ /*
+ * Detect invalid character at beginning. This also works for
+ * empty chunk size lines.
+ */
+ return APR_EINVAL;
+ }
+ else {
+ ctx->state = BODY_CHUNK_PART;
+ }
+ ctx->remaining = 0;
+ ctx->chunkbits = sizeof(apr_off_t) * 8;
+ ctx->chunk_used = 0;
+ ctx->chunk_bws = 0;
}
- if (len > 0) {
- break; /* we got the data we want */
+
+ if (c == LF) {
+ if (ctx->remaining) {
+ ctx->state = BODY_CHUNK_DATA;
+ }
+ else {
+ ctx->state = BODY_CHUNK_TRAILER;
+ }
}
- /* If we got a zero-length data bucket, we try the next one */
- }
- /* We had no data in this brigade */
- if (!len || e == APR_BRIGADE_SENTINEL(b)) {
- return APR_EAGAIN;
- }
- if (lineend[len - 1] != APR_ASCII_LF) {
- return APR_EAGAIN;
- }
- /* Line is complete. So reset ctx for next round. */
- ctx->linesize = 0;
- ctx->pos = ctx->chunk_ln;
- return APR_SUCCESS;
-}
+ else if (ctx->state == BODY_CHUNK_LF) {
+ /*
+ * LF expected.
+ */
+ return APR_EINVAL;
+ }
+ else if (c == CR) {
+ ctx->state = BODY_CHUNK_LF;
+ }
+ else if (c == ';') {
+ ctx->state = BODY_CHUNK_EXT;
+ }
+ else if (ctx->state == BODY_CHUNK_EXT) {
+ /*
+ * Control chars (but tabs) are invalid.
+ */
+ if (c != '\t' && apr_iscntrl(c)) {
+ return APR_EINVAL;
+ }
+ }
+ else if (c == ' ' || c == '\t') {
+ /* Be lenient up to 10 BWS (term from rfc7230 - 3.2.3).
+ */
+ ctx->state = BODY_CHUNK_CR;
+ if (++ctx->chunk_bws > 10) {
+ return APR_EINVAL;
+ }
+ }
+ else if (ctx->state == BODY_CHUNK_CR) {
+ /*
+ * ';', CR or LF expected.
+ */
+ return APR_EINVAL;
+ }
+ else if (ctx->state == BODY_CHUNK_PART) {
+ int xvalue;
-static apr_status_t get_chunk_line(http_ctx_t *ctx, apr_bucket_brigade *b,
- int linelimit)
-{
- apr_size_t len;
- int tmp_len;
- apr_status_t rv;
+ /* ignore leading zeros */
+ if (!ctx->remaining && c == '0') {
+ i++;
+ continue;
+ }
- tmp_len = sizeof(ctx->chunk_ln) - (ctx->pos - ctx->chunk_ln) - 1;
- /* Saveguard ourselves against underflows */
- if (tmp_len < 0) {
- len = 0;
- }
- else {
- len = (apr_size_t) tmp_len;
- }
- /*
- * Check if there is space left in ctx->chunk_ln. If not, then either
- * the chunk size is insane or we have chunk-extensions. Ignore both
- * by discarding the remaining part of the line via
- * get_remaining_chunk_line. Only bail out if the line is too long.
- */
- if (len > 0) {
- rv = apr_brigade_flatten(b, ctx->pos, &len);
- if (rv != APR_SUCCESS) {
- return rv;
+ ctx->chunkbits -= 4;
+ if (ctx->chunkbits < 0) {
+ /* overflow */
+ return APR_ENOSPC;
+ }
+
+ if (c >= '0' && c <= '9') {
+ xvalue = c - '0';
+ }
+ else if (c >= 'A' && c <= 'F') {
+ xvalue = c - 'A' + 0xa;
+ }
+ else if (c >= 'a' && c <= 'f') {
+ xvalue = c - 'a' + 0xa;
+ }
+ else {
+ /* bogus character */
+ return APR_EINVAL;
+ }
+
+ ctx->remaining = (ctx->remaining << 4) | xvalue;
+ if (ctx->remaining < 0) {
+ /* overflow */
+ return APR_ENOSPC;
+ }
}
- ctx->pos += len;
- ctx->linesize += len;
- *(ctx->pos) = '\0';
- /*
- * Check if we really got a full line. If yes the
- * last char in the just read buffer must be LF.
- * If not advance the buffer and return APR_EAGAIN.
- * We do not start processing until we have the
- * full line.
- */
- if (ctx->pos[-1] != APR_ASCII_LF) {
- /* Check if the remaining data in the brigade has the LF */
- return get_remaining_chunk_line(ctx, b, linelimit);
+ else {
+ /* Should not happen */
+ return APR_EGENERAL;
}
- /* Line is complete. So reset ctx->pos for next round. */
- ctx->pos = ctx->chunk_ln;
- return APR_SUCCESS;
+
+ i++;
}
- return get_remaining_chunk_line(ctx, b, linelimit);
-}
+ /* sanity check */
+ ctx->chunk_used += len;
+ if (ctx->chunk_used < 0 || ctx->chunk_used > linelimit) {
+ return APR_ENOSPC;
+ }
+
+ return APR_SUCCESS;
+}
static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
apr_bucket_brigade *b, int merge)
@@ -226,7 +285,6 @@ static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
r->status = HTTP_OK;
r->headers_in = r->trailers_in;
apr_table_clear(r->headers_in);
- ctx->state = BODY_NONE;
ap_get_mime_headers(r);
if(r->status == HTTP_OK) {
@@ -239,7 +297,7 @@ static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
else {
const char *error_notes = apr_table_get(r->notes,
"error-notes");
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02656)
"Error while reading HTTP trailer: %i%s%s",
r->status, error_notes ? ": " : "",
error_notes ? error_notes : "");
@@ -270,9 +328,9 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
apr_bucket *e;
http_ctx_t *ctx = f->ctx;
apr_status_t rv;
- apr_off_t totalread;
int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
apr_bucket_brigade *bb;
+ int again;
conf = (core_server_config *)
ap_get_module_config(f->r->server->module_config, &core_module);
@@ -286,7 +344,6 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
const char *tenc, *lenp;
f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
ctx->state = BODY_NONE;
- ctx->pos = ctx->chunk_ln;
ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
bb = ctx->bb;
@@ -306,25 +363,33 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
lenp = apr_table_get(f->r->headers_in, "Content-Length");
if (tenc) {
- if (!strcasecmp(tenc, "chunked")) {
+ if (strcasecmp(tenc, "chunked") == 0 /* fast path */
+ || ap_find_last_token(f->r->pool, tenc, "chunked")) {
ctx->state = BODY_CHUNK;
}
- /* test lenp, because it gives another case we can handle */
- else if (!lenp) {
- /* Something that isn't in HTTP, unless some future
+ else if (f->r->proxyreq == PROXYREQ_RESPONSE) {
+ /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ * Section 3.3.3.3: "If a Transfer-Encoding header field is
+ * present in a response and the chunked transfer coding is not
+ * the final encoding, the message body length is determined by
+ * reading the connection until it is closed by the server."
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(02555)
+ "Unknown Transfer-Encoding: %s; "
+ "using read-until-close", tenc);
+ tenc = NULL;
+ }
+ else {
+ /* Something that isn't a HTTP request, unless some future
* edition defines new transfer encodings, is unsupported.
*/
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01585)
"Unknown Transfer-Encoding: %s", tenc);
- return bail_out_on_error(ctx, f, HTTP_NOT_IMPLEMENTED);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, f->r, APLOGNO(01586)
- "Unknown Transfer-Encoding: %s; using Content-Length", tenc);
- tenc = NULL;
+ return bail_out_on_error(ctx, f, HTTP_BAD_REQUEST);
}
+ lenp = NULL;
}
- if (lenp && !tenc) {
+ if (lenp) {
char *endstr;
ctx->state = BODY_LENGTH;
@@ -339,7 +404,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01587)
"Invalid Content-Length");
- return bail_out_on_error(ctx, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
+ return bail_out_on_error(ctx, f, HTTP_BAD_REQUEST);
}
/* If we have a limit in effect and we know the C-L ahead of
@@ -381,7 +446,8 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
if (!ap_is_HTTP_SUCCESS(f->r->status)) {
ctx->state = BODY_NONE;
ctx->eos_sent = 1;
- } else {
+ }
+ else {
char *tmp;
int len;
@@ -389,7 +455,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
* in a state of expecting one.
*/
f->r->expecting_100 = 0;
- tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",
+ tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL " ",
ap_get_status_line(HTTP_CONTINUE), CRLF CRLF,
NULL);
len = strlen(tmp);
@@ -401,279 +467,205 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
e = apr_bucket_flush_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(f->c->output_filters, bb);
- }
- }
-
- /* We can't read the chunk until after sending 100 if required. */
- if (ctx->state == BODY_CHUNK) {
- apr_brigade_cleanup(bb);
-
- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- block, 0);
-
- /* for timeout */
- if (block == APR_NONBLOCK_READ &&
- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
- (APR_STATUS_IS_EAGAIN(rv)) )) {
- ctx->state = BODY_CHUNK_PART;
- return APR_EAGAIN;
- }
-
- if (rv == APR_SUCCESS) {
- rv = get_chunk_line(ctx, bb, f->r->server->limit_req_line);
- if (APR_STATUS_IS_EAGAIN(rv)) {
- apr_brigade_cleanup(bb);
- ctx->state = BODY_CHUNK_PART;
- return rv;
- }
- if (rv == APR_SUCCESS) {
- ctx->remaining = get_chunk_size(ctx->chunk_ln);
- if (ctx->remaining == INVALID_CHAR) {
- rv = APR_EGENERAL;
- http_error = HTTP_BAD_REQUEST;
- }
+ rv = ap_pass_brigade(f->c->output_filters, bb);
+ if (rv != APR_SUCCESS) {
+ return AP_FILTER_ERROR;
}
}
- apr_brigade_cleanup(bb);
-
- /* Detect chunksize error (such as overflow) */
- if (rv != APR_SUCCESS || ctx->remaining < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01589) "Error reading first chunk %s ",
- (ctx->remaining < 0) ? "(overflow)" : "");
- ctx->remaining = 0; /* Reset it in case we have to
- * come back here later */
- if (APR_STATUS_IS_TIMEUP(rv)) {
- http_error = HTTP_REQUEST_TIME_OUT;
- }
- return bail_out_on_error(ctx, f, http_error);
- }
-
- if (!ctx->remaining) {
- return read_chunked_trailers(ctx, f, b,
- conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
- }
}
}
- else {
- bb = ctx->bb;
- }
+ /* sanity check in case we're read twice */
if (ctx->eos_sent) {
e = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
}
- if (!ctx->remaining) {
+ do {
+ apr_brigade_cleanup(b);
+ again = 0; /* until further notice */
+
+ /* read and handle the brigade */
switch (ctx->state) {
- case BODY_NONE:
- break;
- case BODY_LENGTH:
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- ctx->eos_sent = 1;
- return APR_SUCCESS;
case BODY_CHUNK:
case BODY_CHUNK_PART:
- {
- apr_brigade_cleanup(bb);
+ case BODY_CHUNK_EXT:
+ case BODY_CHUNK_CR:
+ case BODY_CHUNK_LF:
+ case BODY_CHUNK_END:
+ case BODY_CHUNK_END_LF: {
- /* We need to read the CRLF after the chunk. */
- if (ctx->state == BODY_CHUNK) {
- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- block, 0);
- if (block == APR_NONBLOCK_READ &&
- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
- (APR_STATUS_IS_EAGAIN(rv)) )) {
- return APR_EAGAIN;
- }
- /* If we get an error, then leave */
- if (rv != APR_SUCCESS) {
- return rv;
- }
- /*
- * We really don't care whats on this line. If it is RFC
- * compliant it should be only \r\n. If there is more
- * before we just ignore it as long as we do not get over
- * the limit for request lines.
- */
- rv = get_remaining_chunk_line(ctx, bb,
- f->r->server->limit_req_line);
- apr_brigade_cleanup(bb);
- if (APR_STATUS_IS_EAGAIN(rv)) {
- return rv;
- }
- } else {
- rv = APR_SUCCESS;
- }
+ rv = ap_get_brigade(f->next, b, AP_MODE_GETLINE, block, 0);
+
+ /* for timeout */
+ if (block == APR_NONBLOCK_READ
+ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
+ || (APR_STATUS_IS_EAGAIN(rv)))) {
+ return APR_EAGAIN;
+ }
+
+ if (rv == APR_EOF) {
+ return APR_INCOMPLETE;
+ }
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ e = APR_BRIGADE_FIRST(b);
+ while (e != APR_BRIGADE_SENTINEL(b)) {
+ const char *buffer;
+ apr_size_t len;
+
+ if (!APR_BUCKET_IS_METADATA(e)) {
+ int parsing = 0;
+
+ rv = apr_bucket_read(e, &buffer, &len, APR_BLOCK_READ);
- if (rv == APR_SUCCESS) {
- /* Read the real chunk line. */
- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- block, 0);
- /* Test timeout */
- if (block == APR_NONBLOCK_READ &&
- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
- (APR_STATUS_IS_EAGAIN(rv)) )) {
- ctx->state = BODY_CHUNK_PART;
- return APR_EAGAIN;
- }
- ctx->state = BODY_CHUNK;
if (rv == APR_SUCCESS) {
- rv = get_chunk_line(ctx, bb, f->r->server->limit_req_line);
- if (APR_STATUS_IS_EAGAIN(rv)) {
- ctx->state = BODY_CHUNK_PART;
- apr_brigade_cleanup(bb);
- return rv;
- }
- if (rv == APR_SUCCESS) {
- ctx->remaining = get_chunk_size(ctx->chunk_ln);
- if (ctx->remaining == INVALID_CHAR) {
- rv = APR_EGENERAL;
+ parsing = 1;
+ rv = parse_chunk_size(ctx, buffer, len,
+ f->r->server->limit_req_fieldsize);
+ }
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01590)
+ "Error reading/parsing chunk %s ",
+ (APR_ENOSPC == rv) ? "(overflow)" : "");
+ if (parsing) {
+ if (rv != APR_ENOSPC) {
http_error = HTTP_BAD_REQUEST;
}
+ return bail_out_on_error(ctx, f, http_error);
}
+ return rv;
}
- apr_brigade_cleanup(bb);
}
- /* Detect chunksize error (such as overflow) */
- if (rv != APR_SUCCESS || ctx->remaining < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01590) "Error reading chunk %s ",
- (ctx->remaining < 0) ? "(overflow)" : "");
- ctx->remaining = 0; /* Reset it in case we have to
- * come back here later */
- if (APR_STATUS_IS_TIMEUP(rv)) {
- http_error = HTTP_REQUEST_TIME_OUT;
- }
- return bail_out_on_error(ctx, f, http_error);
- }
+ apr_bucket_delete(e);
+ e = APR_BRIGADE_FIRST(b);
+ }
+ again = 1; /* come around again */
- if (!ctx->remaining) {
- return read_chunked_trailers(ctx, f, b,
+ if (ctx->state == BODY_CHUNK_TRAILER) {
+ /* Treat UNSET as DISABLE - trailers aren't merged by default */
+ return read_chunked_trailers(ctx, f, b,
conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
- }
}
+
break;
}
- }
+ case BODY_NONE:
+ case BODY_LENGTH:
+ case BODY_CHUNK_DATA: {
- /* Ensure that the caller can not go over our boundary point. */
- if (ctx->state == BODY_LENGTH || ctx->state == BODY_CHUNK) {
- if (ctx->remaining < readbytes) {
- readbytes = ctx->remaining;
- }
- AP_DEBUG_ASSERT(readbytes > 0);
- }
+ /* Ensure that the caller can not go over our boundary point. */
+ if (ctx->state != BODY_NONE && ctx->remaining < readbytes) {
+ readbytes = ctx->remaining;
+ }
+ if (readbytes > 0) {
+ apr_off_t totalread;
- rv = ap_get_brigade(f->next, b, mode, block, readbytes);
+ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
- if (rv != APR_SUCCESS) {
- return rv;
- }
+ /* for timeout */
+ if (block == APR_NONBLOCK_READ
+ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
+ || (APR_STATUS_IS_EAGAIN(rv)))) {
+ return APR_EAGAIN;
+ }
- /* How many bytes did we just read? */
- apr_brigade_length(b, 0, &totalread);
+ if (rv == APR_EOF && ctx->state != BODY_NONE
+ && ctx->remaining > 0) {
+ return APR_INCOMPLETE;
+ }
- /* If this happens, we have a bucket of unknown length. Die because
- * it means our assumptions have changed. */
- AP_DEBUG_ASSERT(totalread >= 0);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
- if (ctx->state != BODY_NONE) {
- ctx->remaining -= totalread;
- if (ctx->remaining > 0) {
- e = APR_BRIGADE_LAST(b);
- if (APR_BUCKET_IS_EOS(e))
- return APR_EOF;
- }
- }
+ /* How many bytes did we just read? */
+ apr_brigade_length(b, 0, &totalread);
- /* If we have no more bytes remaining on a C-L request,
- * save the callter a roundtrip to discover EOS.
- */
- if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- }
+ /* If this happens, we have a bucket of unknown length. Die because
+ * it means our assumptions have changed. */
+ AP_DEBUG_ASSERT(totalread >= 0);
- /* We have a limit in effect. */
- if (ctx->limit) {
- /* FIXME: Note that we might get slightly confused on chunked inputs
- * as we'd need to compensate for the chunk lengths which may not
- * really count. This seems to be up for interpretation. */
- ctx->limit_used += totalread;
- if (ctx->limit < ctx->limit_used) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01591)
- "Read content-length of %" APR_OFF_T_FMT
- " is larger than the configured limit"
- " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);
- apr_brigade_cleanup(bb);
- e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
- f->r->pool,
- f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ctx->eos_sent = 1;
- return ap_pass_brigade(f->r->output_filters, bb);
- }
- }
+ if (ctx->state != BODY_NONE) {
+ ctx->remaining -= totalread;
+ if (ctx->remaining > 0) {
+ e = APR_BRIGADE_LAST(b);
+ if (APR_BUCKET_IS_EOS(e)) {
+ apr_bucket_delete(e);
+ return APR_INCOMPLETE;
+ }
+ }
+ else if (ctx->state == BODY_CHUNK_DATA) {
+ /* next chunk please */
+ ctx->state = BODY_CHUNK_END;
+ ctx->chunk_used = 0;
+ }
+ }
- return APR_SUCCESS;
-}
+ /* We have a limit in effect. */
+ if (ctx->limit) {
+ /* FIXME: Note that we might get slightly confused on
+ * chunked inputs as we'd need to compensate for the chunk
+ * lengths which may not really count. This seems to be up
+ * for interpretation.
+ */
+ ctx->limit_used += totalread;
+ if (ctx->limit < ctx->limit_used) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r,
+ APLOGNO(01591) "Read content length of "
+ "%" APR_OFF_T_FMT " is larger than the "
+ "configured limit of %" APR_OFF_T_FMT,
+ ctx->limit_used, ctx->limit);
+ return bail_out_on_error(ctx, f,
+ HTTP_REQUEST_ENTITY_TOO_LARGE);
+ }
+ }
+ }
-/**
- * Parse a chunk extension, detect overflow.
- * There are two error cases:
- * 1) If the conversion would require too many bits, a -1 is returned.
- * 2) If the conversion used the correct number of bits, but an overflow
- * caused only the sign bit to flip, then that negative number is
- * returned.
- * In general, any negative number can be considered an overflow error.
- */
-static long get_chunk_size(char *b)
-{
- long chunksize = 0;
- size_t chunkbits = sizeof(long) * 8;
+ /* If we have no more bytes remaining on a C-L request,
+ * save the caller a round trip to discover EOS.
+ */
+ if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ ctx->eos_sent = 1;
+ }
- ap_xlate_proto_from_ascii(b, strlen(b));
+ break;
+ }
+ case BODY_CHUNK_TRAILER: {
- if (!apr_isxdigit(*b)) {
- /*
- * Detect invalid character at beginning. This also works for empty
- * chunk size lines.
- */
- return INVALID_CHAR;
- }
- /* Skip leading zeros */
- while (*b == '0') {
- ++b;
- }
+ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
- while (apr_isxdigit(*b) && (chunkbits > 0)) {
- int xvalue = 0;
+ /* for timeout */
+ if (block == APR_NONBLOCK_READ
+ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
+ || (APR_STATUS_IS_EAGAIN(rv)))) {
+ return APR_EAGAIN;
+ }
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
- if (*b >= '0' && *b <= '9') {
- xvalue = *b - '0';
+ break;
}
- else if (*b >= 'A' && *b <= 'F') {
- xvalue = *b - 'A' + 0xa;
+ default: {
+ /* Should not happen */
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(02901)
+ "Unexpected body state (%i)", (int)ctx->state);
+ return APR_EGENERAL;
}
- else if (*b >= 'a' && *b <= 'f') {
- xvalue = *b - 'a' + 0xa;
}
- chunksize = (chunksize << 4) | xvalue;
- chunkbits -= 4;
- ++b;
- }
- if (apr_isxdigit(*b)) {
- /* overflow */
- return -1;
- }
+ } while (again);
- return chunksize;
+ return APR_SUCCESS;
}
typedef struct header_struct {
@@ -1385,6 +1377,39 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
return ap_pass_brigade(f->next, b);
}
+/*
+ * Map specific APR codes returned by the filter stack to HTTP error
+ * codes, or the default status code provided. Use it as follows:
+ *
+ * return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+ *
+ * If the filter has already handled the error, AP_FILTER_ERROR will
+ * be returned, which is cleanly passed through.
+ *
+ * These mappings imply that the filter stack is reading from the
+ * downstream client, the proxy will map these codes differently.
+ */
+AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status)
+{
+ switch (rv) {
+ case AP_FILTER_ERROR: {
+ return AP_FILTER_ERROR;
+ }
+ case APR_ENOSPC: {
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+ case APR_ENOTIMPL: {
+ return HTTP_NOT_IMPLEMENTED;
+ }
+ case APR_ETIMEDOUT: {
+ return HTTP_REQUEST_TIME_OUT;
+ }
+ default: {
+ return status;
+ }
+ }
+}
+
/* In HTTP/1.1, any method can have a body. However, most GET handlers
* wouldn't know what to do with a request body if they received one.
* This helper routine tests for and reads any message body in the request,
@@ -1402,7 +1427,8 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
AP_DECLARE(int) ap_discard_request_body(request_rec *r)
{
apr_bucket_brigade *bb;
- int rv, seen_eos;
+ int seen_eos;
+ apr_status_t rv;
/* Sometimes we'll get in a state where the input handling has
* detected an error where we want to drop the connection, so if
@@ -1425,21 +1451,8 @@ AP_DECLARE(int) ap_discard_request_body(request_rec *r)
APR_BLOCK_READ, HUGE_STRING_LEN);
if (rv != APR_SUCCESS) {
- /* FIXME: If we ever have a mapping from filters (apr_status_t)
- * to HTTP error codes, this would be a good place for them.
- *
- * If we received the special case AP_FILTER_ERROR, it means
- * that the filters have already handled this error.
- * Otherwise, we should assume we have a bad request.
- */
- if (rv == AP_FILTER_ERROR) {
- apr_brigade_destroy(bb);
- return rv;
- }
- else {
- apr_brigade_destroy(bb);
- return HTTP_BAD_REQUEST;
- }
+ apr_brigade_destroy(bb);
+ return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
}
for (bucket = APR_BRIGADE_FIRST(bb);
@@ -1608,6 +1621,13 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer,
/* We lose the failure code here. This is why ap_get_client_block should
* not be used.
*/
+ if (rv == AP_FILTER_ERROR) {
+ /* AP_FILTER_ERROR means a filter has responded already,
+ * we are DONE.
+ */
+ apr_brigade_destroy(bb);
+ return -1;
+ }
if (rv != APR_SUCCESS) {
/* if we actually fail here, we want to just return and
* stop trying to read data from the client.

175
SOURCES/httpd-2.4.6-CVE-2015-3185.patch

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
Index: server/request.c
===================================================================
--- a/server/request.c (revision 1684524)
+++ b/server/request.c (revision 1684525)
@@ -71,6 +71,7 @@
APR_HOOK_LINK(create_request)
APR_HOOK_LINK(post_perdir_config)
APR_HOOK_LINK(dirwalk_stat)
+ APR_HOOK_LINK(force_authn)
)
AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
@@ -97,6 +98,8 @@
AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t,dirwalk_stat,
(apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted),
(finfo, r, wanted), AP_DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(int,force_authn,
+ (request_rec *r), (r), DECLINED)
static int auth_internal_per_conf = 0;
static int auth_internal_per_conf_hooks = 0;
@@ -118,6 +121,39 @@
}
}
+AP_DECLARE(int) ap_some_authn_required(request_rec *r)
+{
+ int access_status;
+
+ switch (ap_satisfies(r)) {
+ case SATISFY_ALL:
+ case SATISFY_NOSPEC:
+ if ((access_status = ap_run_access_checker(r)) != OK) {
+ break;
+ }
+
+ access_status = ap_run_access_checker_ex(r);
+ if (access_status == DECLINED) {
+ return TRUE;
+ }
+
+ break;
+ case SATISFY_ANY:
+ if ((access_status = ap_run_access_checker(r)) == OK) {
+ break;
+ }
+
+ access_status = ap_run_access_checker_ex(r);
+ if (access_status == DECLINED) {
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
+
/* This is the master logic for processing requests. Do NOT duplicate
* this logic elsewhere, or the security model will be broken by future
* API changes. Each phase must be individually optimized to pick up
@@ -232,15 +268,8 @@
}
access_status = ap_run_access_checker_ex(r);
- if (access_status == OK) {
- ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
- "request authorized without authentication by "
- "access_checker_ex hook: %s", r->uri);
- }
- else if (access_status != DECLINED) {
- return decl_die(access_status, "check access", r);
- }
- else {
+ if (access_status == DECLINED
+ || (access_status == OK && ap_run_force_authn(r) == OK)) {
if ((access_status = ap_run_check_user_id(r)) != OK) {
return decl_die(access_status, "check user", r);
}
@@ -258,6 +287,14 @@
return decl_die(access_status, "check authorization", r);
}
}
+ else if (access_status == OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
+ "request authorized without authentication by "
+ "access_checker_ex hook: %s", r->uri);
+ }
+ else {
+ return decl_die(access_status, "check access", r);
+ }
break;
case SATISFY_ANY:
if ((access_status = ap_run_access_checker(r)) == OK) {
@@ -269,15 +306,8 @@
}
access_status = ap_run_access_checker_ex(r);
- if (access_status == OK) {
- ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
- "request authorized without authentication by "
- "access_checker_ex hook: %s", r->uri);
- }
- else if (access_status != DECLINED) {
- return decl_die(access_status, "check access", r);
- }
- else {
+ if (access_status == DECLINED
+ || (access_status == OK && ap_run_force_authn(r) == OK)) {
if ((access_status = ap_run_check_user_id(r)) != OK) {
return decl_die(access_status, "check user", r);
}
@@ -295,6 +325,14 @@
return decl_die(access_status, "check authorization", r);
}
}
+ else if (access_status == OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
+ "request authorized without authentication by "
+ "access_checker_ex hook: %s", r->uri);
+ }
+ else {
+ return decl_die(access_status, "check access", r);
+ }
break;
}
}
Index: include/http_request.h
===================================================================
--- a/include/http_request.h (revision 1684524)
+++ b/include/http_request.h (revision 1684525)
@@ -185,6 +185,8 @@
* is required for the current request
* @param r The current request
* @return 1 if authentication is required, 0 otherwise
+ * @bug Behavior changed in 2.4.x refactoring, API no longer usable
+ * @deprecated @see ap_some_authn_required()
*/
AP_DECLARE(int) ap_some_auth_required(request_rec *r);
@@ -539,6 +541,16 @@
AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r))
/**
+ * This hook allows a module to force authn to be required when
+ * processing a request.
+ * This hook should be registered with ap_hook_force_authn().
+ * @param r The current request
+ * @return OK (force authn), DECLINED (let later modules decide)
+ * @ingroup hooks
+ */
+AP_DECLARE_HOOK(int,force_authn,(request_rec *r))
+
+/**
* This hook allows modules to handle/emulate the apr_stat() calls
* needed for directory walk.
* @param r The current request
@@ -584,6 +596,17 @@
AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
request_rec *r);
+/**
+ * Can be used within any handler to determine if any authentication
+ * is required for the current request. Note that if used with an
+ * access_checker hook, an access_checker_ex hook or an authz provider; the
+ * caller should take steps to avoid a loop since this function is
+ * implemented by calling these hooks.
+ * @param r The current request
+ * @return TRUE if authentication is required, FALSE otherwise
+ */
+AP_DECLARE(int) ap_some_authn_required(request_rec *r);
+
#ifdef __cplusplus
}
#endif

325
SOURCES/httpd-2.4.6-CVE-2016-0736.patch

@ -0,0 +1,325 @@ @@ -0,0 +1,325 @@
diff --git a/modules/session/mod_session_crypto.c b/modules/session/mod_session_crypto.c
index 4d65bb8..9231a5e 100644
--- a/modules/session/mod_session_crypto.c
+++ b/modules/session/mod_session_crypto.c
@@ -18,6 +18,7 @@
#include "apu_version.h"
#include "apr_base64.h" /* for apr_base64_decode et al */
#include "apr_lib.h"
+#include "apr_md5.h"
#include "apr_strings.h"
#include "http_log.h"
#include "http_core.h"
@@ -57,6 +58,146 @@ typedef struct {
int library_set;
} session_crypto_conf;
+/* Wrappers around apr_siphash24() and apr_crypto_equals(),
+ * available in APU-1.6/APR-2.0 only.
+ */
+#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 6)
+
+#include "apr_siphash.h"
+
+#define AP_SIPHASH_DSIZE APR_SIPHASH_DSIZE
+#define AP_SIPHASH_KSIZE APR_SIPHASH_KSIZE
+#define ap_siphash24_auth apr_siphash24_auth
+
+#define ap_crypto_equals apr_crypto_equals
+
+#else
+
+#define AP_SIPHASH_DSIZE 8
+#define AP_SIPHASH_KSIZE 16
+
+#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
+
+#define U8TO64_LE(p) \
+ (((apr_uint64_t)((p)[0]) ) | \
+ ((apr_uint64_t)((p)[1]) << 8) | \
+ ((apr_uint64_t)((p)[2]) << 16) | \
+ ((apr_uint64_t)((p)[3]) << 24) | \
+ ((apr_uint64_t)((p)[4]) << 32) | \
+ ((apr_uint64_t)((p)[5]) << 40) | \
+ ((apr_uint64_t)((p)[6]) << 48) | \
+ ((apr_uint64_t)((p)[7]) << 56))
+
+#define U64TO8_LE(p, v) \
+do { \
+ (p)[0] = (unsigned char)((v) ); \
+ (p)[1] = (unsigned char)((v) >> 8); \
+ (p)[2] = (unsigned char)((v) >> 16); \
+ (p)[3] = (unsigned char)((v) >> 24); \
+ (p)[4] = (unsigned char)((v) >> 32); \
+ (p)[5] = (unsigned char)((v) >> 40); \
+ (p)[6] = (unsigned char)((v) >> 48); \
+ (p)[7] = (unsigned char)((v) >> 56); \
+} while (0)
+
+#define SIPROUND() \
+do { \
+ v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
+ v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
+ v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
+ v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
+} while(0)
+
+static apr_uint64_t ap_siphash24(const void *src, apr_size_t len,
+ const unsigned char key[AP_SIPHASH_KSIZE])
+{
+ const unsigned char *ptr, *end;
+ apr_uint64_t v0, v1, v2, v3, m;
+ apr_uint64_t k0, k1;
+ unsigned int rem;
+
+ k0 = U8TO64_LE(key + 0);
+ k1 = U8TO64_LE(key + 8);
+ v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL;
+ v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL;
+ v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL;
+ v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL;
+
+ rem = (unsigned int)(len & 0x7);
+ for (ptr = src, end = ptr + len - rem; ptr < end; ptr += 8) {
+ m = U8TO64_LE(ptr);
+ v3 ^= m;
+ SIPROUND();
+ SIPROUND();
+ v0 ^= m;
+ }
+ m = (apr_uint64_t)(len & 0xff) << 56;
+ switch (rem) {
+ case 7: m |= (apr_uint64_t)ptr[6] << 48;
+ case 6: m |= (apr_uint64_t)ptr[5] << 40;
+ case 5: m |= (apr_uint64_t)ptr[4] << 32;
+ case 4: m |= (apr_uint64_t)ptr[3] << 24;
+ case 3: m |= (apr_uint64_t)ptr[2] << 16;
+ case 2: m |= (apr_uint64_t)ptr[1] << 8;
+ case 1: m |= (apr_uint64_t)ptr[0];
+ case 0: break;
+ }
+ v3 ^= m;
+ SIPROUND();
+ SIPROUND();
+ v0 ^= m;
+
+ v2 ^= 0xff;
+ SIPROUND();
+ SIPROUND();
+ SIPROUND();
+ SIPROUND();
+
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+
+static void ap_siphash24_auth(unsigned char out[AP_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[AP_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = ap_siphash24(src, len, key);
+ U64TO8_LE(out, h);
+}
+
+static int ap_crypto_equals(const void *buf1, const void *buf2,
+ apr_size_t size)
+{
+ const unsigned char *p1 = buf1;
+ const unsigned char *p2 = buf2;
+ unsigned char diff = 0;
+ apr_size_t i;
+
+ for (i = 0; i < size; ++i) {
+ diff |= p1[i] ^ p2[i];
+ }
+
+ return 1 & ((diff - 1) >> 8);
+}
+
+#endif
+
+static void compute_auth(const void *src, apr_size_t len,
+ const char *passphrase, apr_size_t passlen,
+ unsigned char auth[AP_SIPHASH_DSIZE])
+{
+ unsigned char key[APR_MD5_DIGESTSIZE];
+
+ /* XXX: if we had a way to get the raw bytes from an apr_crypto_key_t
+ * we could use them directly (not available in APR-1.5.x).
+ * MD5 is 128bit too, so use it to get a suitable siphash key
+ * from the passphrase.
+ */
+ apr_md5(key, passphrase, passlen);
+
+ ap_siphash24_auth(auth, src, len, key);
+}
+
/**
* Initialise the encryption as per the current config.
*
@@ -128,21 +269,14 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
apr_crypto_block_t *block = NULL;
unsigned char *encrypt = NULL;
unsigned char *combined = NULL;
- apr_size_t encryptlen, tlen;
+ apr_size_t encryptlen, tlen, combinedlen;
char *base64;
apr_size_t blockSize = 0;
const unsigned char *iv = NULL;
apr_uuid_t salt;
apr_crypto_block_key_type_e *cipher;
const char *passphrase;
-
- /* by default, return an empty string */
- *out = "";
-
- /* don't attempt to encrypt an empty string, trying to do so causes a segfault */
- if (!in || !*in) {
- return APR_SUCCESS;
- }
+ apr_size_t passlen;
/* use a uuid as a salt value, and prepend it to our result */
apr_uuid_get(&salt);
@@ -152,9 +286,9 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
}
/* encrypt using the first passphrase in the list */
- passphrase = APR_ARRAY_IDX(dconf->passphrases, 0, char *);
- res = apr_crypto_passphrase(&key, &ivSize, passphrase,
- strlen(passphrase),
+ passphrase = APR_ARRAY_IDX(dconf->passphrases, 0, const char *);
+ passlen = strlen(passphrase);
+ res = apr_crypto_passphrase(&key, &ivSize, passphrase, passlen,
(unsigned char *) (&salt), sizeof(apr_uuid_t),
*cipher, APR_MODE_CBC, 1, 4096, f, r->pool);
if (APR_STATUS_IS_ENOKEY(res)) {
@@ -183,8 +317,9 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
}
/* encrypt the given string */
- res = apr_crypto_block_encrypt(&encrypt, &encryptlen, (unsigned char *)in,
- strlen(in), block);
+ res = apr_crypto_block_encrypt(&encrypt, &encryptlen,
+ (const unsigned char *)in, strlen(in),
+ block);
if (APR_SUCCESS != res) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, APLOGNO(01830)
"apr_crypto_block_encrypt failed");
@@ -198,18 +333,20 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
}
encryptlen += tlen;
- /* prepend the salt and the iv to the result */
- combined = apr_palloc(r->pool, ivSize + encryptlen + sizeof(apr_uuid_t));
- memcpy(combined, &salt, sizeof(apr_uuid_t));
- memcpy(combined + sizeof(apr_uuid_t), iv, ivSize);
- memcpy(combined + sizeof(apr_uuid_t) + ivSize, encrypt, encryptlen);
-
- /* base64 encode the result */
- base64 = apr_palloc(r->pool, apr_base64_encode_len(ivSize + encryptlen +
- sizeof(apr_uuid_t) + 1)
- * sizeof(char));
- apr_base64_encode(base64, (const char *) combined,
- ivSize + encryptlen + sizeof(apr_uuid_t));
+ /* prepend the salt and the iv to the result (keep room for the MAC) */
+ combinedlen = AP_SIPHASH_DSIZE + sizeof(apr_uuid_t) + ivSize + encryptlen;
+ combined = apr_palloc(r->pool, combinedlen);
+ memcpy(combined + AP_SIPHASH_DSIZE, &salt, sizeof(apr_uuid_t));
+ memcpy(combined + AP_SIPHASH_DSIZE + sizeof(apr_uuid_t), iv, ivSize);
+ memcpy(combined + AP_SIPHASH_DSIZE + sizeof(apr_uuid_t) + ivSize,
+ encrypt, encryptlen);
+ /* authenticate the whole salt+IV+ciphertext with a leading MAC */
+ compute_auth(combined + AP_SIPHASH_DSIZE, combinedlen - AP_SIPHASH_DSIZE,
+ passphrase, passlen, combined);
+
+ /* base64 encode the result (APR handles the trailing '\0') */
+ base64 = apr_palloc(r->pool, apr_base64_encode_len(combinedlen));
+ apr_base64_encode(base64, (const char *) combined, combinedlen);
*out = base64;
return res;
@@ -234,6 +371,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
char *decoded;
apr_size_t blockSize = 0;
apr_crypto_block_key_type_e *cipher;
+ unsigned char auth[AP_SIPHASH_DSIZE];
int i = 0;
/* strip base64 from the string */
@@ -241,6 +379,13 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
decodedlen = apr_base64_decode(decoded, in);
decoded[decodedlen] = '\0';
+ /* sanity check - decoded too short? */
+ if (decodedlen < (AP_SIPHASH_DSIZE + sizeof(apr_uuid_t))) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO()
+ "too short to decrypt, aborting");
+ return APR_ECRYPT;
+ }
+
res = crypt_init(r, f, &cipher, dconf);
if (res != APR_SUCCESS) {
return res;
@@ -249,14 +394,25 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
/* try each passphrase in turn */
for (; i < dconf->passphrases->nelts; i++) {
const char *passphrase = APR_ARRAY_IDX(dconf->passphrases, i, char *);
- apr_size_t len = decodedlen;
- char *slider = decoded;
+ apr_size_t passlen = strlen(passphrase);
+ apr_size_t len = decodedlen - AP_SIPHASH_DSIZE;
+ unsigned char *slider = (unsigned char *)decoded + AP_SIPHASH_DSIZE;
+
+ /* Verify authentication of the whole salt+IV+ciphertext by computing
+ * the MAC and comparing it (timing safe) with the one in the payload.
+ */
+ compute_auth(slider, len, passphrase, passlen, auth);
+ if (!ap_crypto_equals(auth, decoded, AP_SIPHASH_DSIZE)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO()
+ "auth does not match, skipping");
+ continue;
+ }
/* encrypt using the first passphrase in the list */
- res = apr_crypto_passphrase(&key, &ivSize, passphrase,
- strlen(passphrase),
- (unsigned char *)decoded, sizeof(apr_uuid_t),
- *cipher, APR_MODE_CBC, 1, 4096, f, r->pool);
+ res = apr_crypto_passphrase(&key, &ivSize, passphrase, passlen,
+ slider, sizeof(apr_uuid_t),
+ *cipher, APR_MODE_CBC, 1, 4096,
+ f, r->pool);
if (APR_STATUS_IS_ENOKEY(res)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01832)
"the passphrase '%s' was empty", passphrase);
@@ -279,7 +435,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
}
/* sanity check - decoded too short? */
- if (decodedlen < (sizeof(apr_uuid_t) + ivSize)) {
+ if (len < (sizeof(apr_uuid_t) + ivSize)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01836)
"too short to decrypt, skipping");
res = APR_ECRYPT;
@@ -290,8 +446,8 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
slider += sizeof(apr_uuid_t);
len -= sizeof(apr_uuid_t);
- res = apr_crypto_block_decrypt_init(&block, &blockSize, (unsigned char *)slider, key,
- r->pool);
+ res = apr_crypto_block_decrypt_init(&block, &blockSize, slider, key,
+ r->pool);
if (APR_SUCCESS != res) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01837)
"apr_crypto_block_decrypt_init failed");
@@ -304,7 +460,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
/* decrypt the given string */
res = apr_crypto_block_decrypt(&decrypted, &decryptedlen,
- (unsigned char *)slider, len, block);
+ slider, len, block);
if (res) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01838)
"apr_crypto_block_decrypt failed");

121
SOURCES/httpd-2.4.6-CVE-2016-2161.patch

@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
index 44b5fc8..6a50ba7 100644
--- a/modules/aaa/mod_auth_digest.c
+++ b/modules/aaa/mod_auth_digest.c
@@ -261,6 +261,26 @@ static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
cleanup_tables(NULL);
}
+/* RMM helper functions that behave like single-step malloc/free. */
+
+static void *rmm_malloc(apr_rmm_t *rmm, apr_size_t size)
+{
+ apr_rmm_off_t offset = apr_rmm_malloc(rmm, size);
+
+ if (!offset) {
+ return NULL;
+ }
+
+ return apr_rmm_addr_get(rmm, offset);
+}
+
+static apr_status_t rmm_free(apr_rmm_t *rmm, void *alloc)
+{
+ apr_rmm_off_t offset = apr_rmm_offset_get(rmm, alloc);
+
+ return apr_rmm_free(rmm, offset);
+}
+
#if APR_HAS_SHARED_MEMORY
static int initialize_tables(server_rec *s, apr_pool_t *ctx)
@@ -299,8 +319,8 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
return !OK;
}
- client_list = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*client_list) +
- sizeof(client_entry*)*num_buckets));
+ client_list = rmm_malloc(client_rmm, sizeof(*client_list) +
+ sizeof(client_entry *) * num_buckets);
if (!client_list) {
log_error_and_cleanup("failed to allocate shared memory", -1, s);
return !OK;
@@ -322,7 +342,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
/* setup opaque */
- opaque_cntr = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*opaque_cntr)));
+ opaque_cntr = rmm_malloc(client_rmm, sizeof(*opaque_cntr));
if (opaque_cntr == NULL) {
log_error_and_cleanup("failed to allocate shared memory", -1, s);
return !OK;
@@ -339,7 +359,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
/* setup one-time-nonce counter */
- otn_counter = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*otn_counter)));
+ otn_counter = rmm_malloc(client_rmm, sizeof(*otn_counter));
if (otn_counter == NULL) {
log_error_and_cleanup("failed to allocate shared memory", -1, s);
return !OK;
@@ -779,7 +799,7 @@ static client_entry *get_client(unsigned long key, const request_rec *r)
* last entry in each bucket and updates the counters. Returns the
* number of removed entries.
*/
-static long gc(void)
+static long gc(server_rec *s)
{
client_entry *entry, *prev;
unsigned long num_removed = 0, idx;
@@ -789,6 +809,12 @@ static long gc(void)
for (idx = 0; idx < client_list->tbl_len; idx++) {
entry = client_list->table[idx];
prev = NULL;
+
+ if (!entry) {
+ /* This bucket is empty. */
+ continue;
+ }
+
while (entry->next) { /* find last entry */
prev = entry;
entry = entry->next;
@@ -800,8 +826,16 @@ static long gc(void)
client_list->table[idx] = NULL;
}
if (entry) { /* remove entry */
- apr_rmm_free(client_rmm, apr_rmm_offset_get(client_rmm, entry));
+ apr_status_t err;
+
+ err = rmm_free(client_rmm, entry);
num_removed++;
+
+ if (err) {
+ /* Nothing we can really do but log... */
+ ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO()
+ "Failed to free auth_digest client allocation");
+ }
}
}
@@ -835,16 +869,16 @@ static client_entry *add_client(unsigned long key, client_entry *info,
/* try to allocate a new entry */
- entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
+ entry = rmm_malloc(client_rmm, sizeof(client_entry));
if (!entry) {
- long num_removed = gc();
+ long num_removed = gc(s);
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01766)
"gc'd %ld client entries. Total new clients: "
"%ld; Total removed clients: %ld; Total renewed clients: "
"%ld", num_removed,
client_list->num_created - client_list->num_renewed,
client_list->num_removed, client_list->num_renewed);
- entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
+ entry = rmm_malloc(client_rmm, sizeof(client_entry));
if (!entry) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01767)
"unable to allocate new auth_digest client");

16
SOURCES/httpd-2.4.6-CVE-2016-5387.patch

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@

https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-5387

--- httpd-2.4.6/server/util_script.c.cve5387
+++ httpd-2.4.6/server/util_script.c
@@ -190,6 +190,10 @@
continue;
}
#endif
+ else if (!strcasecmp(hdrs[i].key, "Proxy")) {
+ /* Don't pass through HTTP_PROXY */
+ continue;
+ }
else
add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
}

2124
SOURCES/httpd-2.4.6-CVE-2016-8743.patch

File diff suppressed because it is too large Load Diff

343
SOURCES/httpd-2.4.6-CVE-2017-3167.patch

@ -0,0 +1,343 @@ @@ -0,0 +1,343 @@
diff --git a/include/http_protocol.h b/include/http_protocol.h
index 5ac0ce3..f3a5137 100644
--- a/include/http_protocol.h
+++ b/include/http_protocol.h
@@ -558,7 +558,11 @@ AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r);
AP_DECLARE_HOOK(int, note_auth_failure, (request_rec *r, const char *auth_type))
/**
- * Get the password from the request headers
+ * Get the password from the request headers. This function has multiple side
+ * effects due to its prior use in the old authentication framework.
+ * ap_get_basic_auth_components() should be preferred.
+ *
+ * @deprecated @see ap_get_basic_auth_components
* @param r The current request
* @param pw The password as set in the headers
* @return 0 (OK) if it set the 'pw' argument (and assured
@@ -571,6 +575,25 @@ AP_DECLARE_HOOK(int, note_auth_failure, (request_rec *r, const char *auth_type))
*/
AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw);
+#define AP_GET_BASIC_AUTH_PW_NOTE "AP_GET_BASIC_AUTH_PW_NOTE"
+
+/**
+ * Get the username and/or password from the request's Basic authentication
+ * headers. Unlike ap_get_basic_auth_pw(), calling this function has no side
+ * effects on the passed request_rec.
+ *
+ * @param r The current request
+ * @param username If not NULL, set to the username sent by the client
+ * @param password If not NULL, set to the password sent by the client
+ * @return APR_SUCCESS if the credentials were successfully parsed and returned;
+ * APR_EINVAL if there was no authentication header sent or if the
+ * client was not using the Basic authentication scheme. username and
+ * password are unchanged on failure.
+ */
+AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r,
+ const char **username,
+ const char **password);
+
/**
* parse_uri: break apart the uri
* @warning Side Effects:
diff --git a/include/httpd.h b/include/httpd.h
index 652a212..176ef5e 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -2272,6 +2272,34 @@ AP_DECLARE(char *) ap_get_exec_line(apr_pool_t *p,
#define AP_NORESTART APR_OS_START_USEERR + 1
+/**
+ * Perform a case-insensitive comparison of two strings @a atr1 and @a atr2,
+ * treating upper and lower case values of the 26 standard C/POSIX alphabetic
+ * characters as equivalent. Extended latin characters outside of this set
+ * are treated as unique octets, irrespective of the current locale.
+ *
+ * Returns in integer greater than, equal to, or less than 0,
+ * according to whether @a str1 is considered greater than, equal to,
+ * or less than @a str2.
+ *
+ * @note Same code as apr_cstr_casecmp, which arrives in APR 1.6
+ */
+AP_DECLARE(int) ap_cstr_casecmp(const char *s1, const char *s2);
+
+/**
+ * Perform a case-insensitive comparison of two strings @a atr1 and @a atr2,
+ * treating upper and lower case values of the 26 standard C/POSIX alphabetic
+ * characters as equivalent. Extended latin characters outside of this set
+ * are treated as unique octets, irrespective of the current locale.
+ *
+ * Returns in integer greater than, equal to, or less than 0,
+ * according to whether @a str1 is considered greater than, equal to,
+ * or less than @a str2.
+ *
+ * @note Same code as apr_cstr_casecmpn, which arrives in APR 1.6
+ */
+AP_DECLARE(int) ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n);
+
#ifdef __cplusplus
}
#endif
diff --git a/server/protocol.c b/server/protocol.c
index 24355c7..868c3e3 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1567,6 +1567,7 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
t = ap_pbase64decode(r->pool, auth_line);
r->user = ap_getword_nulls (r->pool, &t, ':');
+ apr_table_setn(r->notes, AP_GET_BASIC_AUTH_PW_NOTE, "1");
r->ap_auth_type = "Basic";
*pw = t;
@@ -1574,6 +1575,53 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
return OK;
}
+AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r,
+ const char **username,
+ const char **password)
+{
+ const char *auth_header;
+ const char *credentials;
+ const char *decoded;
+ const char *user;
+
+ auth_header = (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
+ : "Authorization";
+ credentials = apr_table_get(r->headers_in, auth_header);
+
+ if (!credentials) {
+ /* No auth header. */
+ return APR_EINVAL;
+ }
+
+ if (ap_cstr_casecmp(ap_getword(r->pool, &credentials, ' '), "Basic")) {
+ /* These aren't Basic credentials. */
+ return APR_EINVAL;
+ }
+
+ while (*credentials == ' ' || *credentials == '\t') {
+ credentials++;
+ }
+
+ /* XXX Our base64 decoding functions don't actually error out if the string
+ * we give it isn't base64; they'll just silently stop and hand us whatever
+ * they've parsed up to that point.
+ *
+ * Since this function is supposed to be a drop-in replacement for the
+ * deprecated ap_get_basic_auth_pw(), don't fix this for 2.4.x.
+ */
+ decoded = ap_pbase64decode(r->pool, credentials);
+ user = ap_getword_nulls(r->pool, &decoded, ':');
+
+ if (username) {
+ *username = user;
+ }
+ if (password) {
+ *password = decoded;
+ }
+
+ return APR_SUCCESS;
+}
+
struct content_length_ctx {
int data_sent; /* true if the C-L filter has already sent at
* least one bucket on to the next output filter
diff --git a/server/request.c b/server/request.c
index 2711bed..4eef097 100644
--- a/server/request.c
+++ b/server/request.c
@@ -124,6 +124,8 @@ static int decl_die(int status, const char *phase, request_rec *r)
AP_DECLARE(int) ap_some_authn_required(request_rec *r)
{
int access_status;
+ char *olduser = r->user;
+ int rv = FALSE;
switch (ap_satisfies(r)) {
case SATISFY_ALL:
@@ -134,7 +136,7 @@ AP_DECLARE(int) ap_some_authn_required(request_rec *r)
access_status = ap_run_access_checker_ex(r);
if (access_status == DECLINED) {
- return TRUE;
+ rv = TRUE;
}
break;
@@ -145,13 +147,14 @@ AP_DECLARE(int) ap_some_authn_required(request_rec *r)
access_status = ap_run_access_checker_ex(r);
if (access_status == DECLINED) {
- return TRUE;
+ rv = TRUE;
}
break;
}
- return FALSE;
+ r->user = olduser;
+ return rv;
}
/* This is the master logic for processing requests. Do NOT duplicate
@@ -259,6 +262,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
r->ap_auth_type = r->main->ap_auth_type;
}
else {
+ /* A module using a confusing API (ap_get_basic_auth_pw) caused
+ ** r->user to be filled out prior to check_authn hook. We treat
+ ** it is inadvertent.
+ */
+ if (r->user && apr_table_get(r->notes, AP_GET_BASIC_AUTH_PW_NOTE)) {
+ r->user = NULL;
+ }
+
switch (ap_satisfies(r)) {
case SATISFY_ALL:
case SATISFY_NOSPEC:
diff --git a/server/util.c b/server/util.c
index db22b50..70fd662 100644
--- a/server/util.c
+++ b/server/util.c
@@ -96,7 +96,6 @@
#undef APLOG_MODULE_INDEX
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
-
/*
* Examine a field value (such as a media-/content-type) string and return
* it sans any parameters; e.g., strip off any ';charset=foo' and the like.
@@ -3036,3 +3035,128 @@ AP_DECLARE(char *) ap_get_exec_line(apr_pool_t *p,
return apr_pstrndup(p, buf, k);
}
+
+#if !APR_CHARSET_EBCDIC
+/*
+ * Our own known-fast translation table for casecmp by character.
+ * Only ASCII alpha characters 41-5A are folded to 61-7A, other
+ * octets (such as extended latin alphabetics) are never case-folded.
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+*/
+static const short ucharmap[] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+#else /* APR_CHARSET_EBCDIC */
+/*
+ * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
+ * provides unique identity of every char value (strict ISO-646
+ * conformance, arbitrary election of an ISO-8859-1 ordering, and
+ * very arbitrary control code assignments into C1 to achieve
+ * identity and a reversible mapping of code points),
+ * then folding the equivalences of ASCII 41-5A into 61-7A,
+ * presenting comparison results in a somewhat ISO/IEC 10646
+ * (ASCII-like) order, depending on the EBCDIC code page in use.
+ *
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+ */
+static const short ucharmap[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
+ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
+ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
+ 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+ 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+ 0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
+};
+#endif
+
+AP_DECLARE(int) ap_cstr_casecmp(const char *s1, const char *s2)
+{
+ const unsigned char *str1 = (const unsigned char *)s1;
+ const unsigned char *str2 = (const unsigned char *)s2;
+ for (;;)
+ {
+ const int c1 = (int)(*str1);
+ const int c2 = (int)(*str2);
+ const int cmp = ucharmap[c1] - ucharmap[c2];
+ /* Not necessary to test for !c2, this is caught by cmp */
+ if (cmp || !c1)
+ return cmp;
+ str1++;
+ str2++;
+ }
+}
+
+AP_DECLARE(int) ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
+{
+ const unsigned char *str1 = (const unsigned char *)s1;
+ const unsigned char *str2 = (const unsigned char *)s2;
+ while (n--)
+ {
+ const int c1 = (int)(*str1);
+ const int c2 = (int)(*str2);
+ const int cmp = ucharmap[c1] - ucharmap[c2];
+ /* Not necessary to test for !c2, this is caught by cmp */
+ if (cmp || !c1)
+ return cmp;
+ str1++;
+ str2++;
+ }
+ return 0;
+}

64
SOURCES/httpd-2.4.6-CVE-2017-3169.patch

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 85c6ce7..4a9fc9a 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -834,19 +834,20 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
* establish an outgoing SSL connection. */
#define MODSSL_ERROR_BAD_GATEWAY (APR_OS_START_USERERR + 1)
-static void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f)
+static void ssl_io_filter_disable(SSLConnRec *sslconn,
+ bio_filter_in_ctx_t *inctx)
{
- bio_filter_in_ctx_t *inctx = f->ctx;
SSL_free(inctx->ssl);
sslconn->ssl = NULL;
inctx->ssl = NULL;
inctx->filter_ctx->pssl = NULL;
}
-static apr_status_t ssl_io_filter_error(ap_filter_t *f,
+static apr_status_t ssl_io_filter_error(bio_filter_in_ctx_t *inctx,
apr_bucket_brigade *bb,
apr_status_t status)
{
+ ap_filter_t *f = inctx->f;
SSLConnRec *sslconn = myConnConfig(f->c);
apr_bucket *bucket;
int send_eos = 1;
@@ -860,7 +861,7 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f,
ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server);
sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP;
- ssl_io_filter_disable(sslconn, f);
+ ssl_io_filter_disable(sslconn, inctx);
/* fake the request line */
bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
@@ -1342,7 +1343,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f,
* rather than have SSLEngine On configured.
*/
if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) {
- return ssl_io_filter_error(f, bb, status);
+ return ssl_io_filter_error(inctx, bb, status);
}
if (is_init) {
@@ -1396,7 +1397,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f,
/* Handle custom errors. */
if (status != APR_SUCCESS) {
- return ssl_io_filter_error(f, bb, status);
+ return ssl_io_filter_error(inctx, bb, status);
}
/* Create a transient bucket out of the decrypted data. */
@@ -1613,7 +1614,7 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f,
inctx->block = APR_BLOCK_READ;
if ((status = ssl_io_filter_handshake(filter_ctx)) != APR_SUCCESS) {
- return ssl_io_filter_error(f, bb, status);
+ return ssl_io_filter_error(inctx, bb, status);
}
while (!APR_BRIGADE_EMPTY(bb)) {

15
SOURCES/httpd-2.4.6-CVE-2017-7668.patch

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
--- a/server/util.c 2017/05/30 12:27:41 1796855
+++ b/server/util.c 2017/05/30 12:28:20 1796856
@@ -1679,10 +1679,8 @@
s = (const unsigned char *)line;
for (;;) {
- /* find start of token, skip all stop characters, note NUL
- * isn't a token stop, so we don't need to test for it
- */
- while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
+ /* find start of token, skip all stop characters */
+ while (*s && TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
++s;
}
if (!*s) {

14
SOURCES/httpd-2.4.6-CVE-2017-7679.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
--- a/modules/http/mod_mime.c 2017/06/05 12:10:05 1797652
+++ b/modules/http/mod_mime.c 2017/06/05 12:12:31 1797653
@@ -528,9 +528,9 @@
int res = -1;
int c;
- if (((s + 1) != NULL) && (*s == '\\')) {
+ if (*s == '\\') {
c = (int) *(s + 1);
- if (apr_isascii(c)) {
+ if (c && apr_isascii(c)) {
res = 1;
}
}

29
SOURCES/httpd-2.4.6-CVE-2017-9788.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
index 0ff47f7..cbb4434 100644
--- a/modules/aaa/mod_auth_digest.c
+++ b/modules/aaa/mod_auth_digest.c
@@ -956,13 +956,13 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp)
/* find value */
+ vv = 0;
if (auth_line[0] == '=') {
auth_line++;
while (apr_isspace(auth_line[0])) {
auth_line++;
}
- vv = 0;
if (auth_line[0] == '\"') { /* quoted string */
auth_line++;
while (auth_line[0] != '\"' && auth_line[0] != '\0') {
@@ -981,8 +981,8 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp)
value[vv++] = *auth_line++;
}
}
- value[vv] = '\0';
}
+ value[vv] = '\0';
while (auth_line[0] != ',' && auth_line[0] != '\0') {
auth_line++;

17
SOURCES/httpd-2.4.6-CVE-2017-9798.patch

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
diff --git a/server/core.c b/server/core.c
index f60e8fa..245fcb6 100644
--- a/server/core.c
+++ b/server/core.c
@@ -2061,6 +2061,12 @@ AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd,
/* method has not been registered yet, but resorce restriction
* is always checked before method handling, so register it.
*/
+ if (cmd->pool == cmd->temp_pool) {
+ /* In .htaccess, we can't globally register new methods. */
+ return apr_psprintf(cmd->pool, "Could not register method '%s' "
+ "for %s from .htaccess configuration",
+ method, cmd->cmd->name);
+ }
methnum = ap_method_register(cmd->pool,
apr_pstrdup(cmd->pool, method));
}

20
SOURCES/httpd-2.4.6-ab-overflow.patch

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
--- a/support/ab.c 2014/08/14 12:12:38 1617912
+++ b/support/ab.c 2014/08/14 12:15:31 1617913
@@ -1029,7 +1029,7 @@
ap_round_ms(stats[done - 1].time));
else
printf(" %d%% %5" APR_TIME_T_FMT "\n", percs[i],
- ap_round_ms(stats[(int) (done * percs[i] / 100)].time));
+ ap_round_ms(stats[(unsigned long)done * percs[i] / 100].time));
}
}
if (csvperc) {
@@ -1046,7 +1046,7 @@
else if (i == 100)
t = ap_double_ms(stats[done - 1].time);
else
- t = ap_double_ms(stats[(int) (0.5 + done * i / 100.0)].time);
+ t = ap_double_ms(stats[(unsigned long) (0.5 + (double)done * i / 100.0)].time);
fprintf(out, "%d,%.3f\n", i, t);
}
fclose(out);

27
SOURCES/httpd-2.4.6-ab-ssl-error.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
diff --git a/support/ab.c b/support/ab.c
index bf76406..80c1b74 100644
--- a/support/ab.c
+++ b/support/ab.c
@@ -1346,11 +1346,21 @@ static void read_connection(struct connection * c)
&& good == 0) {
return;
}
+ else if (scode == SSL_ERROR_SYSCALL
+ && status == 0
+ && c->read != 0) {
+ /* connection closed, but in violation of the protocol, after
+ * some data has already been read; this commonly happens, so
+ * let the length check catch any response errors
+ */
+ good++;
+ close_connection(c);
+ }
else if (scode != SSL_ERROR_WANT_WRITE
&& scode != SSL_ERROR_WANT_READ) {
/* some fatal error: */
c->read = 0;
- BIO_printf(bio_err, "SSL read failed (%d) - closing connection\n", scode);
+ BIO_printf(bio_err, "SSL read failed (%d) - closing connection\n", scode);
ERR_print_errors(bio_err);
close_connection(c);
}

139
SOURCES/httpd-2.4.6-ap-ipv6.patch

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
diff --git a/support/ab.c b/support/ab.c
index f54c402..93c9066 100644
--- a/support/ab.c
+++ b/support/ab.c
@@ -344,6 +344,7 @@ apr_time_t start, lasttime, stoptime;
char _request[2048];
char *request = _request;
apr_size_t reqlen;
+int requests_initialized = 0;
/* one global throw-away buffer to read stuff into */
char buffer[8192];
@@ -1253,12 +1254,18 @@ static void start_connect(struct connection * c)
else {
set_conn_state(c, STATE_UNCONNECTED);
apr_socket_close(c->aprsock);
- err_conn++;
- if (bad++ > 10) {
+ if (good == 0 && destsa->next) {
+ destsa = destsa->next;
+ err_conn = 0;
+ }
+ else if (bad++ > 10) {
fprintf(stderr,
"\nTest aborted after 10 failures\n\n");
apr_err("apr_socket_connect()", rv);
}
+ else {
+ err_conn++;
+ }
start_connect(c);
return;
@@ -1339,6 +1346,7 @@ static void read_connection(struct connection * c)
apr_status_t status;
char *part;
char respcode[4]; /* 3 digits and null */
+ int i;
r = sizeof(buffer);
#ifdef USE_SSL
@@ -1362,6 +1370,13 @@ static void read_connection(struct connection * c)
good++;
close_connection(c);
}
+ else if (scode == SSL_ERROR_SYSCALL
+ && c->read == 0
+ && destsa->next
+ && c->state == STATE_CONNECTING
+ && good == 0) {
+ return;
+ }
else if (scode != SSL_ERROR_WANT_WRITE
&& scode != SSL_ERROR_WANT_READ) {
/* some fatal error: */
@@ -1387,8 +1402,8 @@ static void read_connection(struct connection * c)
}
/* catch legitimate fatal apr_socket_recv errors */
else if (status != APR_SUCCESS) {
- err_recv++;
if (recverrok) {
+ err_recv++;
bad++;
close_connection(c);
if (verbosity >= 1) {
@@ -1396,7 +1411,12 @@ static void read_connection(struct connection * c)
fprintf(stderr,"%s: %s (%d)\n", "apr_socket_recv", apr_strerror(status, buf, sizeof buf), status);
}
return;
- } else {
+ } else if (destsa->next && c->state == STATE_CONNECTING
+ && c->read == 0 && good == 0) {
+ return;
+ }
+ else {
+ err_recv++;
apr_err("apr_socket_recv", status);
}
}
@@ -1523,6 +1543,16 @@ static void read_connection(struct connection * c)
}
c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
totalbread += c->bread;
+
+ /* We have received the header, so we know this destination socket
+ * address is working, so initialize all remaining requests. */
+ if (!requests_initialized) {
+ for (i = 1; i < concurrency; i++) {
+ con[i].socknum = i;
+ start_connect(&con[i]);
+ }
+ requests_initialized = 1;
+ }
}
}
else {
@@ -1734,11 +1764,10 @@ static void test(void)
apr_signal(SIGINT, output_results);
#endif
- /* initialise lots of requests */
- for (i = 0; i < concurrency; i++) {
- con[i].socknum = i;
- start_connect(&con[i]);
- }
+ /* initialise first connection to determine destination socket address
+ * which should be used for next connections. */
+ con[0].socknum = 0;
+ start_connect(&con[0]);
do {
apr_int32_t n;
@@ -1786,14 +1815,20 @@ static void test(void)
if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP))
read_connection(c);
if ((rtnev & APR_POLLERR) || (rtnev & APR_POLLNVAL)) {
- bad++;
- err_except++;
- /* avoid apr_poll/EINPROGRESS loop on HP-UX, let recv discover ECONNREFUSED */
- if (c->state == STATE_CONNECTING) {
- read_connection(c);
+ if (destsa->next && c->state == STATE_CONNECTING && good == 0) {
+ destsa = destsa->next;
+ start_connect(c);
}
else {
- start_connect(c);
+ bad++;
+ err_except++;
+ /* avoid apr_poll/EINPROGRESS loop on HP-UX, let recv discover ECONNREFUSED */
+ if (c->state == STATE_CONNECTING) {
+ read_connection(c);
+ }
+ else {
+ start_connect(c);
+ }
}
continue;
}

38
SOURCES/httpd-2.4.6-apachectl-httpd-env.patch

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
diff --git a/docs/man/apachectl.8 b/docs/man/apachectl.8
index 054550f..4bfc7cb 100644
--- a/docs/man/apachectl.8
+++ b/docs/man/apachectl.8
@@ -77,7 +77,7 @@ status
Displays a brief status report\&. Similar to the fullstatus option, except that the list of requests currently being served is omitted\&.
.TP
graceful
-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 configtest before initiating the restart to make sure Apache doesn't die\&. This is equivalent to apachectl -k graceful\&.
+Gracefully restarts the Apache httpd daemon\&. If the daemon is not running, it is not 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 configtest before initiating the restart to make sure Apache doesn't die\&. This is equivalent to apachectl -k graceful\&.
.TP
graceful-stop
Gracefully stops the Apache httpd daemon\&. This differs from a normal stop in that currently open connections are not aborted\&. A side effect is that old log files will not be closed immediately\&. This is equivalent to apachectl -k graceful-stop\&.
diff --git a/support/apachectl.in b/support/apachectl.in
index 2d59623..10fc280 100644
--- a/support/apachectl.in
+++ b/support/apachectl.in
@@ -93,9 +93,9 @@ function testconfig() {
# httpd is denied terminal access in SELinux, so run in the
# current context to get stdout from $HTTPD -t.
if test -x /usr/sbin/selinuxenabled && /usr/sbin/selinuxenabled; then
- runcon -- `id -Z` $HTTPD $OPTIONS -t
+ runcon -- `id -Z` /usr/sbin/httpd $OPTIONS -t
else
- $HTTPD $OPTIONS -t
+ /usr/sbin/httpd $OPTIONS -t
fi
ERROR=$?
}
@@ -134,7 +134,7 @@ fullstatus)
$LYNX $STATUSURL
;;
*)
- $HTTPD $OPTIONS "$@"
+ /usr/sbin/httpd $OPTIONS "$@"
ERROR=$?
esac

13
SOURCES/httpd-2.4.6-apachectl-status.patch

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
diff --git a/docs/man/apachectl.8 b/docs/man/apachectl.8
index 4bfc7cb..372c08e 100644
--- a/docs/man/apachectl.8
+++ b/docs/man/apachectl.8
@@ -74,7 +74,7 @@ fullstatus
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 lynx available on your system\&. The URL used to access the status report can be set by editing the STATUSURL variable in the script\&.
.TP
status
-Displays a brief status report\&. Similar to the fullstatus option, except that the list of requests currently being served is omitted\&.
+Displays a brief status report using systemd\&.
.TP
graceful
Gracefully restarts the Apache httpd daemon\&. If the daemon is not running, it is not 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 configtest before initiating the restart to make sure Apache doesn't die\&. This is equivalent to apachectl -k graceful\&.

14
SOURCES/httpd-2.4.6-bomb.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
diff --git a/docs/conf/extra/httpd-autoindex.conf.in b/docs/conf/extra/httpd-autoindex.conf.in
index 0e8b626..dd6f2c6 100644
--- a/docs/conf/extra/httpd-autoindex.conf.in
+++ b/docs/conf/extra/httpd-autoindex.conf.in
@@ -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

31
SOURCES/httpd-2.4.6-dhparams-free.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index ee46db4..c560422 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -915,7 +915,7 @@ static void ssl_init_server_certs(server_rec *s,
const char *rsa_id, *dsa_id;
#ifndef OPENSSL_NO_EC
const char *ecc_id;
- EC_GROUP *ecparams;
+ EC_GROUP *ecparams = NULL;
int nid;
EC_KEY *eckey = NULL;
#endif
@@ -988,6 +988,7 @@ static void ssl_init_server_certs(server_rec *s,
"Custom DH parameters (%d bits) for %s loaded from %s",
BN_num_bits(dhparams->p), vhost_id,
mctx->pks->cert_files[0]);
+ DH_free(dhparams);
}
#ifndef OPENSSL_NO_EC
@@ -1012,6 +1013,9 @@ static void ssl_init_server_certs(server_rec *s,
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
#endif
}
+ if (ecparams) {
+ EC_GROUP_free(ecparams);
+ }
EC_KEY_free(eckey);
#endif
}

48
SOURCES/httpd-2.4.6-full-release.patch

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
diff --git a/server/core.c b/server/core.c
index fb5e34a..e71f716 100644
--- a/server/core.c
+++ b/server/core.c
@@ -3115,7 +3115,8 @@ 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_PRODUCT_ONLY /* eg: Apache */
+ 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;
@@ -3191,7 +3192,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 ")");
}
@@ -3199,7 +3203,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 ")";
@@ -3232,8 +3236,11 @@ static const char *set_serv_tokens(cmd_parms *cmd, void *dummy,
else if (!strcasecmp(arg1, "Full")) {
ap_server_tokens = SrvTk_FULL;
}
+ else if (!strcasecmp(arg1, "Full-Release")) {
+ ap_server_tokens = SrvTk_FULL_RELEASE;
+ }
else {
- return "ServerTokens takes 1 argument, 'Prod', 'Major', 'Minor', 'Min', 'OS', or 'Full'";
+ return "ServerTokens takes 1 argument, 'Prod', 'Major', 'Minor', 'Min', 'OS', 'Full' or 'Full-Release'";
}
return NULL;

17
SOURCES/httpd-2.4.6-http-protocol-options-define.patch

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
diff --git a/server/main.c b/server/main.c
index 28d1872..544882d 100644
--- a/server/main.c
+++ b/server/main.c
@@ -478,6 +478,12 @@ int main(int argc, const char * const argv[])
ap_server_post_read_config = apr_array_make(pcommands, 1, sizeof(char *));
ap_server_config_defines = apr_array_make(pcommands, 1, sizeof(char *));
+ {
+ char **new = (char **)apr_array_push(ap_server_config_defines);
+
+ *new = "_RH_HAS_HTTPPROTOCOLOPTIONS";
+ }
+
error = ap_setup_prelinked_modules(process);
if (error) {
ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_EMERG, 0, NULL, APLOGNO(00012)

73
SOURCES/httpd-2.4.6-ldaprefer.patch

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ldap/util_ldap.c?r1=1517388&r2=1517387&pathrev=1517388&view=patch

--- trunk/modules/ldap/util_ldap.c 2013/08/25 21:46:27 1517387
+++ trunk/modules/ldap/util_ldap.c 2013/08/25 22:42:29 1517388
@@ -60,6 +60,7 @@
#endif
#define AP_LDAP_HOPLIMIT_UNSET -1
+#define AP_LDAP_CHASEREFERRALS_SDKDEFAULT -1
#define AP_LDAP_CHASEREFERRALS_OFF 0
#define AP_LDAP_CHASEREFERRALS_ON 1
@@ -371,7 +372,7 @@
ldap_option = ldc->deref;
ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
- if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ if (ldc->ChaseReferrals != AP_LDAP_CHASEREFERRALS_SDKDEFAULT) {
/* Set options for rebind and referrals. */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01278)
"LDAP: Setting referrals to %s.",
@@ -391,7 +392,9 @@
uldap_connection_unbind(ldc);
return(result->rc);
}
+ }
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
if ((ldc->ReferralHopLimit != AP_LDAP_HOPLIMIT_UNSET) && ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
/* Referral hop limit - only if referrals are enabled and a hop limit is explicitly requested */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01280)
@@ -2584,15 +2587,25 @@
static const char *util_ldap_set_chase_referrals(cmd_parms *cmd,
void *config,
- int mode)
+ const char *arg)
{
util_ldap_config_t *dc = config;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01311)
- "LDAP: Setting referral chasing %s",
- (mode == AP_LDAP_CHASEREFERRALS_ON) ? "ON" : "OFF");
+ "LDAP: Setting referral chasing %s", arg);
- dc->ChaseReferrals = mode;
+ if (0 == strcasecmp(arg, "on")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_ON;
+ }
+ else if (0 == strcasecmp(arg, "off")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_OFF;
+ }
+ else if (0 == strcasecmp(arg, "default")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_SDKDEFAULT;
+ }
+ else {
+ return "LDAPReferrals must be 'on', 'off', or 'default'";
+ }
return(NULL);
}
@@ -3116,9 +3129,9 @@
"Specify the LDAP socket connection timeout in seconds "
"(default: 10)"),
- AP_INIT_FLAG("LDAPReferrals", util_ldap_set_chase_referrals,
+ AP_INIT_TAKE1("LDAPReferrals", util_ldap_set_chase_referrals,
NULL, OR_AUTHCFG,
- "Choose whether referrals are chased ['ON'|'OFF']. Default 'ON'"),
+ "Choose whether referrals are chased ['ON'|'OFF'|'DEFAULT']. Default 'ON'"),
AP_INIT_TAKE1("LDAPReferralHopLimit", util_ldap_set_referral_hop_limit,
NULL, OR_AUTHCFG,

55
SOURCES/httpd-2.4.6-mod_authz_dbd-missing-query.patch

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
diff --git a/modules/aaa/mod_authz_dbd.c b/modules/aaa/mod_authz_dbd.c
index 1a456fe..6a0f705 100644
--- a/modules/aaa/mod_authz_dbd.c
+++ b/modules/aaa/mod_authz_dbd.c
@@ -116,7 +116,7 @@ static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg,
const char *newuri = NULL;
int nrows;
const char *message;
- ap_dbd_t *dbd = dbd_handle(r);
+ ap_dbd_t *dbd;
apr_dbd_prepared_t *query;
apr_dbd_results_t *res = NULL;
apr_dbd_row_t *row = NULL;
@@ -126,6 +126,16 @@ static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg,
"No query configured for %s!", action);
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ dbd = dbd_handle(r);
+ if (dbd == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02902)
+ "No db handle available for %s! "
+ "Check your database access",
+ action);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
if (query == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01643)
@@ -202,7 +212,7 @@ static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg,
/* SELECT group FROM authz WHERE user = %s */
int rv;
const char *message;
- ap_dbd_t *dbd = dbd_handle(r);
+ ap_dbd_t *dbd;
apr_dbd_prepared_t *query;
apr_dbd_results_t *res = NULL;
apr_dbd_row_t *row = NULL;
@@ -212,6 +222,15 @@ static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg,
"No query configured for dbd-group!");
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ dbd = dbd_handle(r);
+ if (dbd == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02903)
+ "No db handle available for dbd-query! "
+ "Check your database access");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
if (query == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01650)

10
SOURCES/httpd-2.4.6-mpm-segfault.patch

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
--- a/server/mpm/event/event.c
+++ a/server/mpm/event/event.c
@@ -2735,6 +2735,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
/* we've been told to restart */
apr_signal(SIGHUP, SIG_IGN);
+ apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
if (one_process) {
/* not worth thinking about */

140
SOURCES/httpd-2.4.6-pre_htaccess.patch

@ -0,0 +1,140 @@ @@ -0,0 +1,140 @@
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 89c4140..82a0acb 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -418,6 +418,7 @@
* ap_proxy_pass_brigade()
* 20120211.22 (2.4.5-dev) No longer prevent usage of strtoul()
* 20120211.23 (2.4.5-dev) Add ap_proxy_clear_connection()
+ * 20120211.24 (2.4.7-dev) add open_htaccess hook.
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -425,7 +426,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 23 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 24 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/include/http_config.h b/include/http_config.h
index 7ee3760..c93c3b2 100644
--- a/include/http_config.h
+++ b/include/http_config.h
@@ -1322,6 +1322,31 @@ AP_DECLARE_HOOK(int,quick_handler,(request_rec *r, int lookup_uri))
AP_DECLARE_HOOK(void,optional_fn_retrieve,(void))
/**
+ * Allow modules to open htaccess files or perform operations before doing so
+ * @param r The current request
+ * @param dir_name The directory for which the htaccess file should be opened
+ * @param access_name The filename for which the htaccess file should be opened
+ * @param conffile Where the pointer to the opened ap_configfile_t must be
+ * stored
+ * @param full_name Where the full file name of the htaccess file must be
+ * stored.
+ * @return APR_SUCCESS on success,
+ * APR_ENOENT or APR_ENOTDIR if no htaccess file exists,
+ * AP_DECLINED to let later modules do the opening,
+ * any other error code on error.
+ */
+AP_DECLARE_HOOK(apr_status_t,open_htaccess,
+ (request_rec *r, const char *dir_name, const char *access_name,
+ ap_configfile_t **conffile, const char **full_name))
+
+/**
+ * Core internal function, use ap_run_open_htaccess() instead.
+ */
+apr_status_t ap_open_htaccess(request_rec *r, const char *dir_name,
+ const char *access_name, ap_configfile_t **conffile,
+ const char **full_name);
+
+/**
* A generic pool cleanup that will reset a pointer to NULL. For use with
* apr_pool_cleanup_register.
* @param data The address of the pointer
diff --git a/server/config.c b/server/config.c
index c1aae17..265744e 100644
--- a/server/config.c
+++ b/server/config.c
@@ -80,6 +80,7 @@ APR_HOOK_STRUCT(
APR_HOOK_LINK(quick_handler)
APR_HOOK_LINK(optional_fn_retrieve)
APR_HOOK_LINK(test_config)
+ APR_HOOK_LINK(open_htaccess)
)
AP_IMPLEMENT_HOOK_RUN_ALL(int, header_parser,
@@ -171,6 +172,12 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, handler, (request_rec *r),
AP_IMPLEMENT_HOOK_RUN_FIRST(int, quick_handler, (request_rec *r, int lookup),
(r, lookup), DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, open_htaccess,
+ (request_rec *r, const char *dir_name, const char *access_name,
+ ap_configfile_t **conffile, const char **full_name),
+ (r, dir_name, access_name, conffile, full_name),
+ AP_DECLINED)
+
/* hooks with no args are implemented last, after disabling APR hook probes */
#if defined(APR_HOOK_PROBES_ENABLED)
#undef APR_HOOK_PROBES_ENABLED
@@ -2073,14 +2080,23 @@ AP_DECLARE(int) ap_process_config_tree(server_rec *s,
return OK;
}
+apr_status_t ap_open_htaccess(request_rec *r, const char *dir_name,
+ const char *access_name,
+ ap_configfile_t **conffile,
+ const char **full_name)
+{
+ *full_name = ap_make_full_path(r->pool, dir_name, access_name);
+ return ap_pcfg_openfile(conffile, r->pool, *full_name);
+}
+
AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
request_rec *r, int override,
int override_opts, apr_table_t *override_list,
- const char *d, const char *access_name)
+ const char *d, const char *access_names)
{
ap_configfile_t *f = NULL;
cmd_parms parms;
- char *filename = NULL;
+ const char *filename;
const struct htaccess_result *cache;
struct htaccess_result *new;
ap_conf_vector_t *dc = NULL;
@@ -2104,15 +2120,11 @@ AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
parms.path = apr_pstrdup(r->pool, d);
/* loop through the access names and find the first one */
- while (access_name[0]) {
- /* AFAICT; there is no use of the actual 'filename' against
- * any canonicalization, so we will simply take the given
- * name, ignoring case sensitivity and aliases
- */
- filename = ap_make_full_path(r->pool, d,
- ap_getword_conf(r->pool, &access_name));
- status = ap_pcfg_openfile(&f, r->pool, filename);
+ while (access_names[0]) {
+ const char *access_name = ap_getword_conf(r->pool, &access_names);
+ filename = NULL;
+ status = ap_run_open_htaccess(r, d, access_name, &f, &filename);
if (status == APR_SUCCESS) {
const char *errmsg;
ap_directive_t *temptree = NULL;
diff --git a/server/core.c b/server/core.c
index f3965ca..85f876b 100644
--- a/server/core.c
+++ b/server/core.c
@@ -4930,6 +4930,7 @@ static void register_hooks(apr_pool_t *p)
ap_hook_insert_network_bucket(core_insert_network_bucket, NULL, NULL,
APR_HOOK_REALLY_LAST);
ap_hook_dirwalk_stat(core_dirwalk_stat, NULL, NULL, APR_HOOK_REALLY_LAST);
+ ap_hook_open_htaccess(ap_open_htaccess, NULL, NULL, APR_HOOK_REALLY_LAST);
/* register the core's insert_filter hook and register core-provided
* filters

313
SOURCES/httpd-2.4.6-r1332643+.patch

@ -0,0 +1,313 @@ @@ -0,0 +1,313 @@
# ./pullrev.sh 1332643 1345599 1487772

https://bugzilla.redhat.com//show_bug.cgi?id=809599

http://svn.apache.org/viewvc?view=revision&revision=1332643
http://svn.apache.org/viewvc?view=revision&revision=1345599
http://svn.apache.org/viewvc?view=revision&revision=1487772

--- httpd-2.4.6/modules/ssl/mod_ssl.c.r1332643+
+++ httpd-2.4.6/modules/ssl/mod_ssl.c
@@ -413,6 +413,37 @@ int ssl_engine_disable(conn_rec *c)
return 1;
}
+static int modssl_register_npn(conn_rec *c,
+ ssl_npn_advertise_protos advertisefn,
+ ssl_npn_proto_negotiated negotiatedfn)
+{
+#ifdef HAVE_TLS_NPN
+ SSLConnRec *sslconn = myConnConfig(c);
+
+ if (!sslconn) {
+ return DECLINED;
+ }
+
+ if (!sslconn->npn_advertfns) {
+ sslconn->npn_advertfns =
+ apr_array_make(c->pool, 5, sizeof(ssl_npn_advertise_protos));
+ sslconn->npn_negofns =
+ apr_array_make(c->pool, 5, sizeof(ssl_npn_proto_negotiated));
+ }
+
+ if (advertisefn)
+ APR_ARRAY_PUSH(sslconn->npn_advertfns, ssl_npn_advertise_protos) =
+ advertisefn;
+ if (negotiatedfn)
+ APR_ARRAY_PUSH(sslconn->npn_negofns, ssl_npn_proto_negotiated) =
+ negotiatedfn;
+
+ return OK;
+#else
+ return DECLINED;
+#endif
+}
+
int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
{
SSLSrvConfigRec *sc;
@@ -584,6 +615,7 @@ static void ssl_register_hooks(apr_pool_
APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
+ APR_REGISTER_OPTIONAL_FN(modssl_register_npn);
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
AUTHZ_PROVIDER_VERSION,
--- httpd-2.4.6/modules/ssl/mod_ssl.h.r1332643+
+++ httpd-2.4.6/modules/ssl/mod_ssl.h
@@ -63,5 +63,40 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_e
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
+/** The npn_advertise_protos callback allows another modules to add
+ * entries to the list of protocol names advertised by the server
+ * during the Next Protocol Negotiation (NPN) portion of the SSL
+ * handshake. The callback is given the connection and an APR array;
+ * it should push one or more char*'s pointing to NUL-terminated
+ * strings (such as "http/1.1" or "spdy/2") onto the array and return
+ * OK. To prevent further processing of (other modules') callbacks,
+ * return DONE. */
+typedef int (*ssl_npn_advertise_protos)(conn_rec *connection,
+ apr_array_header_t *protos);
+
+/** The npn_proto_negotiated callback allows other modules to discover
+ * the name of the protocol that was chosen during the Next Protocol
+ * Negotiation (NPN) portion of the SSL handshake. Note that this may
+ * be the empty string (in which case modules should probably assume
+ * HTTP), or it may be a protocol that was never even advertised by
+ * the server. The callback is given the connection, a
+ * non-NUL-terminated string containing the protocol name, and the
+ * length of the string; it should do something appropriate
+ * (i.e. insert or remove filters) and return OK. To prevent further
+ * processing of (other modules') callbacks, return DONE. */
+typedef int (*ssl_npn_proto_negotiated)(conn_rec *connection,
+ const char *proto_name,
+ apr_size_t proto_name_len);
+
+/* An optional function which can be used to register a pair of
+ * callbacks for NPN handling. This optional function should be
+ * invoked from a pre_connection hook which runs *after* mod_ssl.c's
+ * pre_connection hook. The function returns OK if the callbacks are
+ * register, or DECLINED otherwise (for example if mod_ssl does not
+l * support NPN). */
+APR_DECLARE_OPTIONAL_FN(int, modssl_register_npn, (conn_rec *conn,
+ ssl_npn_advertise_protos advertisefn,
+ ssl_npn_proto_negotiated negotiatedfn));
+
#endif /* __MOD_SSL_H__ */
/** @} */
--- httpd-2.4.6/modules/ssl/ssl_engine_init.c.r1332643+
+++ httpd-2.4.6/modules/ssl/ssl_engine_init.c
@@ -725,6 +725,11 @@ static void ssl_init_ctx_callbacks(serve
#endif
SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
+
+#ifdef HAVE_TLS_NPN
+ SSL_CTX_set_next_protos_advertised_cb(
+ ctx, ssl_callback_AdvertiseNextProtos, NULL);
+#endif
}
static void ssl_init_ctx_verify(server_rec *s,
--- httpd-2.4.6/modules/ssl/ssl_engine_io.c.r1332643+
+++ httpd-2.4.6/modules/ssl/ssl_engine_io.c
@@ -297,6 +297,7 @@ typedef struct {
apr_pool_t *pool;
char buffer[AP_IOBUFSIZE];
ssl_filter_ctx_t *filter_ctx;
+ int npn_finished; /* 1 if NPN has finished, 0 otherwise */
} bio_filter_in_ctx_t;
/*
@@ -1400,6 +1401,37 @@ static apr_status_t ssl_io_filter_input(
APR_BRIGADE_INSERT_TAIL(bb, bucket);
}
+#ifdef HAVE_TLS_NPN
+ /* By this point, Next Protocol Negotiation (NPN) should be completed (if
+ * our version of OpenSSL supports it). If we haven't already, find out
+ * which protocol was decided upon and inform other modules by calling
+ * npn_proto_negotiated_hook. */
+ if (!inctx->npn_finished) {
+ SSLConnRec *sslconn = myConnConfig(f->c);
+ const unsigned char *next_proto = NULL;
+ unsigned next_proto_len = 0;
+ int n;
+
+ if (sslconn->npn_negofns) {
+ SSL_get0_next_proto_negotiated(
+ inctx->ssl, &next_proto, &next_proto_len);
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
+ APLOGNO(02306) "SSL NPN negotiated protocol: '%*s'",
+ next_proto_len, (const char*)next_proto);
+
+ for (n = 0; n < sslconn->npn_negofns->nelts; n++) {
+ ssl_npn_proto_negotiated fn =
+ APR_ARRAY_IDX(sslconn->npn_negofns, n, ssl_npn_proto_negotiated);
+
+ if (fn(f->c, (const char *)next_proto, next_proto_len) == DONE)
+ break;
+ }
+ }
+
+ inctx->npn_finished = 1;
+ }
+#endif
+
return APR_SUCCESS;
}
@@ -1881,6 +1913,7 @@ static void ssl_io_input_add_filter(ssl_
inctx->block = APR_BLOCK_READ;
inctx->pool = c->pool;
inctx->filter_ctx = filter_ctx;
+ inctx->npn_finished = 0;
}
/* The request_rec pointer is passed in here only to ensure that the
--- httpd-2.4.6/modules/ssl/ssl_engine_kernel.c.r1332643+
+++ httpd-2.4.6/modules/ssl/ssl_engine_kernel.c
@@ -2161,6 +2161,97 @@ int ssl_callback_SessionTicket(SSL *ssl,
}
#endif /* HAVE_TLS_SESSION_TICKETS */
+#ifdef HAVE_TLS_NPN
+/*
+ * This callback function is executed when SSL needs to decide what protocols
+ * to advertise during Next Protocol Negotiation (NPN). It must produce a
+ * string in wire format -- a sequence of length-prefixed strings -- indicating
+ * the advertised protocols. Refer to SSL_CTX_set_next_protos_advertised_cb
+ * in OpenSSL for reference.
+ */
+int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out,
+ unsigned int *size_out, void *arg)
+{
+ conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
+ SSLConnRec *sslconn = myConnConfig(c);
+ apr_array_header_t *protos;
+ int num_protos;
+ unsigned int size;
+ int i;
+ unsigned char *data;
+ unsigned char *start;
+
+ *data_out = NULL;
+ *size_out = 0;
+
+ /* If the connection object is not available, or there are no NPN
+ * hooks registered, then there's nothing for us to do. */
+ if (c == NULL || sslconn->npn_advertfns == NULL) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+
+ /* Invoke our npn_advertise_protos hook, giving other modules a chance to
+ * add alternate protocol names to advertise. */
+ protos = apr_array_make(c->pool, 0, sizeof(char *));
+ for (i = 0; i < sslconn->npn_advertfns->nelts; i++) {
+ ssl_npn_advertise_protos fn =
+ APR_ARRAY_IDX(sslconn->npn_advertfns, i, ssl_npn_advertise_protos);
+
+ if (fn(c, protos) == DONE)
+ break;
+ }
+ num_protos = protos->nelts;
+
+ /* We now have a list of null-terminated strings; we need to concatenate
+ * them together into a single string, where each protocol name is prefixed
+ * by its length. First, calculate how long that string will be. */
+ size = 0;
+ for (i = 0; i < num_protos; ++i) {
+ const char *string = APR_ARRAY_IDX(protos, i, const char*);
+ unsigned int length = strlen(string);
+ /* If the protocol name is too long (the length must fit in one byte),
+ * then log an error and skip it. */
+ if (length > 255) {
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02307)
+ "SSL NPN protocol name too long (length=%u): %s",
+ length, string);
+ continue;
+ }
+ /* Leave room for the length prefix (one byte) plus the protocol name
+ * itself. */
+ size += 1 + length;
+ }
+
+ /* If there is nothing to advertise (either because no modules added
+ * anything to the protos array, or because all strings added to the array
+ * were skipped), then we're done. */
+ if (size == 0) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+
+ /* Now we can build the string. Copy each protocol name string into the
+ * larger string, prefixed by its length. */
+ data = apr_palloc(c->pool, size * sizeof(unsigned char));
+ start = data;
+ for (i = 0; i < num_protos; ++i) {
+ const char *string = APR_ARRAY_IDX(protos, i, const char*);
+ apr_size_t length = strlen(string);
+ if (length > 255)
+ continue;
+ *start = (unsigned char)length;
+ ++start;
+ memcpy(start, string, length * sizeof(unsigned char));
+ start += length;
+ }
+
+ /* Success. */
+ *data_out = data;
+ *size_out = size;
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#endif /* HAVE_TLS_NPN */
+
#ifndef OPENSSL_NO_SRP
int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
--- httpd-2.4.6/modules/ssl/ssl_private.h.r1332643+
+++ httpd-2.4.6/modules/ssl/ssl_private.h
@@ -98,6 +98,8 @@
#include <openssl/x509_vfy.h>
#include <openssl/ocsp.h>
+#include "mod_ssl.h"
+
/* Avoid tripping over an engine build installed globally and detected
* when the user points at an explicit non-engine flavor of OpenSSL
*/
@@ -139,6 +141,11 @@
#define HAVE_FIPS
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) \
+ && !defined(OPENSSL_NO_TLSEXT)
+#define HAVE_TLS_NPN
+#endif
+
#if (OPENSSL_VERSION_NUMBER >= 0x10000000)
#define MODSSL_SSL_CIPHER_CONST const
#define MODSSL_SSL_METHOD_CONST const
@@ -487,6 +494,12 @@ typedef struct {
* connection */
} reneg_state;
+#ifdef HAVE_TLS_NPN
+ /* Poor man's inter-module optional hooks for NPN. */
+ apr_array_header_t *npn_advertfns; /* list of ssl_npn_advertise_protos callbacks */
+ apr_array_header_t *npn_negofns; /* list of ssl_npn_proto_negotiated callbacks. */
+#endif
+
server_rec *server;
} SSLConnRec;
@@ -842,6 +855,7 @@ int ssl_callback_ServerNameIndi
int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *,
EVP_CIPHER_CTX *, HMAC_CTX *, int);
#endif
+int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg);
/** Session Cache Support */
void ssl_scache_init(server_rec *, apr_pool_t *);

77
SOURCES/httpd-2.4.6-r1348019.patch

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 2121892..6f904b2 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -2838,33 +2838,48 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
connected = 1;
}
- /*
- * Put the entire worker to error state if
- * the PROXY_WORKER_IGNORE_ERRORS flag is not set.
- * Altrough some connections may be alive
- * no further connections to the worker could be made
- */
- if (!connected && PROXY_WORKER_IS_USABLE(worker) &&
- !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
- worker->s->error_time = apr_time_now();
- worker->s->status |= PROXY_WORKER_IN_ERROR;
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00959)
- "ap_proxy_connect_backend disabling worker for (%s) for %"
- APR_TIME_T_FMT "s",
- worker->s->hostname, apr_time_sec(worker->s->retry));
+
+ if (PROXY_WORKER_IS_USABLE(worker)) {
+ /*
+ * Put the entire worker to error state if
+ * the PROXY_WORKER_IGNORE_ERRORS flag is not set.
+ * Although some connections may be alive
+ * no further connections to the worker could be made
+ */
+ if (!connected) {
+ if (!(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
+ worker->s->error_time = apr_time_now();
+ worker->s->status |= PROXY_WORKER_IN_ERROR;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00959)
+ "ap_proxy_connect_backend disabling worker for (%s) for %"
+ APR_TIME_T_FMT "s",
+ worker->s->hostname, apr_time_sec(worker->s->retry));
+ }
+ }
+ else {
+ if (worker->s->retries) {
+ /*
+ * A worker came back. So here is where we need to
+ * either reset all params to initial conditions or
+ * apply some sort of aging
+ */
+ }
+ worker->s->error_time = 0;
+ worker->s->retries = 0;
+ }
+ return connected ? OK : DECLINED;
}
else {
- if (worker->s->retries) {
- /*
- * A worker came back. So here is where we need to
- * either reset all params to initial conditions or
- * apply some sort of aging
- */
- }
- worker->s->error_time = 0;
- worker->s->retries = 0;
+ /*
+ * The worker is in error likely done by a different thread / process
+ * e.g. for a timeout or bad status. We should respect this and should
+ * not continue with a connection via this worker even if we got one.
+ */
+ if (connected) {
+ socket_cleanup(conn);
+ }
+ return DECLINED;
}
- return connected ? OK : DECLINED;
}
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,

154
SOURCES/httpd-2.4.6-r1420184.patch

@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
Index: modules/aaa/mod_authz_owner.c
===================================================================
--- a/modules/aaa/mod_authz_owner.c (revision 1420183)
+++ b/modules/aaa/mod_authz_owner.c (revision 1420184)
@@ -28,9 +28,8 @@
#include "http_request.h"
#include "mod_auth.h"
+#include "mod_authz_owner.h"
-APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
-
static const command_rec authz_owner_cmds[] =
{
{NULL}
Index: modules/aaa/mod_authz_owner.h
===================================================================
--- a/modules/aaa/mod_authz_owner.h (revision 0)
+++ b/modules/aaa/mod_authz_owner.h (revision 1420184)
@@ -0,0 +1,27 @@
+/* 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.
+ */
+
+#ifndef MOD_AUTHZ_OWNER_H
+#define MOD_AUTHZ_OWNER_H
+
+#include "http_request.h"
+
+/* mod_authz_owner exports an optional function which retrieves the
+ * group name of the file identified by r->filename, if available, or
+ * else returns NULL. */
+APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
+
+#endif /* MOD_AUTHZ_OWNER_H */
Index: modules/aaa/mod_authz_groupfile.c
===================================================================
--- a/modules/aaa/mod_authz_groupfile.c (revision 1420183)
+++ b/modules/aaa/mod_authz_groupfile.c (revision 1420184)
@@ -55,13 +55,12 @@
#include "util_varbuf.h"
#include "mod_auth.h"
+#include "mod_authz_owner.h"
typedef struct {
char *groupfile;
} authz_groupfile_config_rec;
-APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
-
static void *create_authz_groupfile_dir_config(apr_pool_t *p, char *d)
{
authz_groupfile_config_rec *conf = apr_palloc(p, sizeof(*conf));
@@ -200,7 +199,7 @@
return AUTHZ_DENIED;
}
-APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
+static APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
static authz_status filegroup_check_authorization(request_rec *r,
const char *require_args,
@@ -279,10 +278,14 @@
NULL,
};
-static void register_hooks(apr_pool_t *p)
+
+static void authz_groupfile_getfns(void)
{
authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
+}
+static void register_hooks(apr_pool_t *p)
+{
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "group",
AUTHZ_PROVIDER_VERSION,
&authz_group_provider,
@@ -291,6 +294,7 @@
AUTHZ_PROVIDER_VERSION,
&authz_filegroup_provider,
AP_AUTH_INTERNAL_PER_CONF);
+ ap_hook_optional_fn_retrieve(authz_groupfile_getfns, NULL, NULL, APR_HOOK_MIDDLE);
}
AP_DECLARE_MODULE(authz_groupfile) =
Index: modules/aaa/mod_authz_dbm.c
===================================================================
--- a/modules/aaa/mod_authz_dbm.c (revision 1420183)
+++ b/modules/aaa/mod_authz_dbm.c (revision 1420184)
@@ -29,6 +29,7 @@
#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/
#include "mod_auth.h"
+#include "mod_authz_owner.h"
typedef struct {
const char *grpfile;
@@ -35,9 +36,7 @@
const char *dbmtype;
} authz_dbm_config_rec;
-APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
-
/* This should go into APR; perhaps with some nice
* caching/locking/flocking of the open dbm file.
*/
@@ -199,7 +198,7 @@
return AUTHZ_DENIED;
}
-APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
+static APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
static authz_status dbmfilegroup_check_authorization(request_rec *r,
const char *require_args,
@@ -279,11 +278,13 @@
NULL,
};
+static void authz_dbm_getfns(void)
+{
+ authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
+}
static void register_hooks(apr_pool_t *p)
{
- authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
-
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-group",
AUTHZ_PROVIDER_VERSION,
&authz_dbmgroup_provider,
@@ -292,6 +293,7 @@
AUTHZ_PROVIDER_VERSION,
&authz_dbmfilegroup_provider,
AP_AUTH_INTERNAL_PER_CONF);
+ ap_hook_optional_fn_retrieve(authz_dbm_getfns, NULL, NULL, APR_HOOK_MIDDLE);
}
AP_DECLARE_MODULE(authz_dbm) =

13
SOURCES/httpd-2.4.6-r1506474.patch

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
--- a/server/core.c 2013/07/24 09:49:38 1506473
+++ b/server/core.c 2013/07/24 09:51:14 1506474
@@ -1481,7 +1481,9 @@
conf->ap_document_root = arg;
}
else {
- return "DocumentRoot must be a directory";
+ return apr_psprintf(cmd->pool,
+ "DocumentRoot '%s' is not a directory, or is not readable",
+ arg);
}
}
return NULL;

62
SOURCES/httpd-2.4.6-r1507681+.patch

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
# ./pullrev.sh 1507681 1533447

https://bugzilla.redhat.com/show_bug.cgi?id=1004046

http://svn.apache.org/viewvc?view=revision&revision=1507681
http://svn.apache.org/viewvc?view=revision&revision=1533447

--- httpd-2.4.6/modules/dav/main/mod_dav.c
+++ httpd-2.4.6/modules/dav/main/mod_dav.c
@@ -2756,7 +2756,7 @@
* The multistatus responses will contain the information about any
* resource that fails the validation.
*
- * We check the parent resource, too, since this is a MOVE. Moving the
+ * We check the parent resource, too, if this is a MOVE. Moving the
* resource effectively removes it from the parent collection, so we
* must ensure that we have met the appropriate conditions.
*
@@ -2765,7 +2765,9 @@
*/
if ((err = dav_validate_request(r, resource, depth, NULL,
&multi_response,
- DAV_VALIDATE_PARENT
+ (is_move ? DAV_VALIDATE_PARENT
+ : DAV_VALIDATE_RESOURCE
+ | DAV_VALIDATE_NO_MODIFY)
| DAV_VALIDATE_USE_424,
NULL)) != NULL) {
err = dav_push_error(r->pool, err->status, 0,
--- httpd-2.4.6/modules/dav/main/util.c
+++ httpd-2.4.6/modules/dav/main/util.c
@@ -954,13 +954,16 @@
/*
** For methods other than LOCK:
**
- ** If we have no locks, then <seen_locktoken> can be set to true --
+ ** If we have no locks or if the resource is not being modified
+ ** (per RFC 4918 the lock token is not required on resources
+ ** we are not changing), then <seen_locktoken> can be set to true --
** pretending that we've already met the requirement of seeing one
** of the resource's locks in the If: header.
**
** Otherwise, it must be cleared and we'll look for one.
*/
- seen_locktoken = (lock_list == NULL);
+ seen_locktoken = (lock_list == NULL
+ || flags & DAV_VALIDATE_NO_MODIFY);
}
/*
--- httpd-2.4.6/modules/dav/main/mod_dav.h
+++ httpd-2.4.6/modules/dav/main/mod_dav.h
@@ -1297,6 +1297,9 @@
the 424 DAV:response */
#define DAV_VALIDATE_USE_424 0x0080 /* return 424 status, not 207 */
#define DAV_VALIDATE_IS_PARENT 0x0100 /* for internal use */
+#define DAV_VALIDATE_NO_MODIFY 0x0200 /* resource is not being modified
+ so allow even if lock token
+ is not provided */
/* Lock-null related public lock functions */
DAV_DECLARE(int) dav_get_resource_state(request_rec *r,

20
SOURCES/httpd-2.4.6-r1524368.patch

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
--- a/modules/proxy/mod_proxy_fcgi.c 2013/09/18 11:17:28 1524367
+++ b/modules/proxy/mod_proxy_fcgi.c 2013/09/18 11:18:02 1524368
@@ -429,15 +429,13 @@
ob = apr_brigade_create(r->pool, c->bucket_alloc);
while (! done) {
- apr_interval_time_t timeout = conn->worker->s->timeout;
+ apr_interval_time_t timeout;
apr_size_t len;
int n;
/* We need SOME kind of timeout here, or virtually anything will
* cause timeout errors. */
- if (! conn->worker->s->timeout_set) {
- timeout = apr_time_from_sec(30);
- }
+ apr_socket_timeout_get(conn->sock, &timeout);
rv = apr_poll(&pfd, 1, &n, timeout);
if (rv != APR_SUCCESS) {

62
SOURCES/httpd-2.4.6-r1526189.patch

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 81fd14c..cd1710f 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -856,6 +856,17 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
proxy_conn_rec *conn,
conn_rec *c, server_rec *s);
+
+/**
+ * Determine if proxy connection can potentially be reused at the
+ * end of this request.
+ * @param conn proxy connection
+ * @return non-zero if reusable, 0 otherwise
+ * @note Even if this function returns non-zero, the connection may
+ * be subsequently marked for closure.
+ */
+PROXY_DECLARE(int) ap_proxy_connection_reusable(proxy_conn_rec *conn);
+
/**
* Signal the upstream chain that the connection to the backend broke in the
* middle of the response. This is done by sending an error bucket with
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 0f84416..c57696a 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -247,7 +247,7 @@ static apr_status_t send_begin_request(proxy_conn_rec *conn, int request_id)
brb.roleB1 = ((FCGI_RESPONDER >> 8) & 0xff);
brb.roleB0 = ((FCGI_RESPONDER) & 0xff);
- brb.flags = FCGI_KEEP_CONN;
+ brb.flags = ap_proxy_connection_reusable(conn) ? FCGI_KEEP_CONN : 0;
brb.reserved[0] = 0;
brb.reserved[1] = 0;
brb.reserved[2] = 0;
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 8bc9fab..ca70ae4 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1333,6 +1333,13 @@ static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
worker->cp = cp;
}
+PROXY_DECLARE(int) ap_proxy_connection_reusable(proxy_conn_rec *conn)
+{
+ proxy_worker *worker = conn->worker;
+
+ return ! (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse);
+}
+
static apr_status_t connection_cleanup(void *theconn)
{
proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
@@ -1361,7 +1368,7 @@ static apr_status_t connection_cleanup(void *theconn)
}
/* determine if the connection need to be closed */
- if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
+ if (!ap_proxy_connection_reusable(conn)) {
apr_pool_t *p = conn->pool;
apr_pool_clear(p);
conn = apr_pcalloc(p, sizeof(proxy_conn_rec));

21
SOURCES/httpd-2.4.6-r1527509.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
diff -Npru httpd-2.4.6.orig/modules/dav/main/mod_dav.c httpd-2.4.6/modules/dav/main/mod_dav.c
--- httpd-2.4.6.orig/modules/dav/main/mod_dav.c 2015-06-24 12:24:47.920000000 -0400
+++ httpd-2.4.6/modules/dav/main/mod_dav.c 2015-06-24 12:27:19.706000000 -0400
@@ -316,6 +316,8 @@ static int dav_error_response(request_re
{
r->status = status;
+ r->status_line = ap_get_status_line(status);
+
ap_set_content_type(r, "text/html; charset=ISO-8859-1");
/* begin the response now... */
@@ -347,6 +349,8 @@ static int dav_error_response_tag(reques
{
r->status = err->status;
+ r->status_line = ap_get_status_line(err->status);
+
ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
ap_rputs(DAV_XML_HEADER DEBUG_CR

23
SOURCES/httpd-2.4.6-r1528556.patch

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
Index: modules/mappers/mod_rewrite.c
===================================================================
--- a/modules/mappers/mod_rewrite.c (revision 1499025)
+++ b/modules/mappers/mod_rewrite.c (revision 1528556)
@@ -589,6 +589,18 @@
return 7;
}
break;
+
+ case 'w':
+ case 'W':
+ if (!strncasecmp(uri, "s://", 4)) { /* ws:// */
+ *sqs = 1;
+ return 5;
+ }
+ else if (!strncasecmp(uri, "ss://", 5)) { /* wss:// */
+ *sqs = 1;
+ return 6;
+ }
+ break;
}
return 0;

46
SOURCES/httpd-2.4.6-r1528958.patch

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
--- a/server/vhost.c 2013/07/15 11:50:50 1503188
+++ b/server/vhost.c 2013/10/03 18:31:22 1528958
@@ -577,14 +577,22 @@
*/
for (s = main_s->next; s; s = s->next) {
+ server_addr_rec *sar_prev = NULL;
has_default_vhost_addr = 0;
for (sar = s->addrs; sar; sar = sar->next) {
ipaddr_chain *ic;
char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */
-
+ /* XXX: this treats 0.0.0.0 as a "default" server which matches no-exact-match for IPv6 */
if (!memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) {
ic = find_default_server(sar->host_port);
- if (!ic || sar->host_port != ic->sar->host_port) {
+
+ if (ic && sar->host_port == ic->sar->host_port) { /* we're a match for an existing "default server" */
+ if (!sar_prev || memcmp(sar_prev->host_addr->ipaddr_ptr, inaddr_any, sar_prev->host_addr->ipaddr_len)
+ || sar_prev->host_port != sar->host_port) {
+ add_name_vhost_config(p, main_s, s, sar, ic);
+ }
+ }
+ else {
/* No default server, or we found a default server but
** exactly one of us is a wildcard port, which means we want
** two ip-based vhosts not an NVH with two names
@@ -592,6 +600,7 @@
ic = new_ipaddr_chain(p, s, sar);
ic->next = default_list;
default_list = ic;
+ add_name_vhost_config(p, main_s, s, sar, ic);
}
has_default_vhost_addr = 1;
}
@@ -609,8 +618,9 @@
ic->next = *iphash_table_tail[bucket];
*iphash_table_tail[bucket] = ic;
}
+ add_name_vhost_config(p, main_s, s, sar, ic);
}
- add_name_vhost_config(p, main_s, s, sar, ic);
+ sar_prev = sar;
}
/* Ok now we want to set up a server_hostname if the user was

59
SOURCES/httpd-2.4.6-r1530280.patch

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
--- a/modules/http/http_filters.c 2013/10/08 14:17:33 1530279
+++ b/modules/http/http_filters.c 2013/10/08 14:18:44 1530280
@@ -825,7 +825,7 @@
* handler.
* Zap r->status_line if bad.
*/
-static void validate_status_line(request_rec *r)
+static apr_status_t validate_status_line(request_rec *r)
{
char *end;
@@ -836,15 +836,19 @@
|| (end - 3) != r->status_line
|| (len >= 4 && ! apr_isspace(r->status_line[3]))) {
r->status_line = NULL;
+ return APR_EGENERAL;
}
/* Since we passed the above check, we know that length three
* is equivalent to only a 3 digit numeric http status.
* RFC2616 mandates a trailing space, let's add it.
*/
- else if (len == 3) {
+ if (len == 3) {
r->status_line = apr_pstrcat(r->pool, r->status_line, " ", NULL);
+ return APR_EGENERAL;
}
+ return APR_SUCCESS;
}
+ return APR_EGENERAL;
}
/*
@@ -856,15 +860,25 @@
static void basic_http_header_check(request_rec *r,
const char **protocol)
{
+ apr_status_t rv;
+
if (r->assbackwards) {
/* no such thing as a response protocol */
return;
}
- validate_status_line(r);
+ rv = validate_status_line(r);
if (!r->status_line) {
r->status_line = ap_get_status_line(r->status);
+ } else if (rv != APR_SUCCESS) {
+ /* Status line is OK but our own reason phrase
+ * would be preferred if defined
+ */
+ const char *tmp = ap_get_status_line(r->status);
+ if (!strncmp(tmp, r->status_line, 3)) {
+ r->status_line = tmp;
+ }
}
/* Note that we must downgrade before checking for force responses. */

19
SOURCES/httpd-2.4.6-r1530999.patch

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
# ./pullrev.sh 1530999

http://svn.apache.org/viewvc?view=revision&revision=1530999

https://bugzilla.redhat.com/show_bug.cgi?id=1557785

--- httpd-2.4.6/server/core_filters.c
+++ httpd-2.4.6/server/core_filters.c
@@ -745,7 +745,9 @@
pollset.reqevents = APR_POLLOUT;
pollset.desc.s = s;
apr_socket_timeout_get(s, &timeout);
- rv = apr_poll(&pollset, 1, &nsds, timeout);
+ do {
+ rv = apr_poll(&pollset, 1, &nsds, timeout);
+ } while (APR_STATUS_IS_EINTR(rv));
if (rv != APR_SUCCESS) {
break;
}

155
SOURCES/httpd-2.4.6-r1533448.patch

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
Index: modules/dav/fs/repos.c
===================================================================
--- a/modules/dav/fs/repos.c (revision 1533447)
+++ b/modules/dav/fs/repos.c (revision 1533448)
@@ -717,13 +717,13 @@
resource->pool = r->pool;
/* make sure the URI does not have a trailing "/" */
- len = strlen(r->uri);
- if (len > 1 && r->uri[len - 1] == '/') {
- s = apr_pstrmemdup(r->pool, r->uri, len-1);
+ len = strlen(r->unparsed_uri);
+ if (len > 1 && r->unparsed_uri[len - 1] == '/') {
+ s = apr_pstrmemdup(r->pool, r->unparsed_uri, len-1);
resource->uri = s;
}
else {
- resource->uri = r->uri;
+ resource->uri = r->unparsed_uri;
}
if (r->finfo.filetype != APR_NOFILE) {
@@ -1482,6 +1482,18 @@
return dav_fs_deleteset(info->pool, resource);
}
+/* Take an unescaped path component and escape it and append it onto a
+ * dav_buffer for a URI */
+static apr_size_t dav_fs_append_uri(apr_pool_t *p, dav_buffer *pbuf,
+ const char *path, apr_size_t pad)
+{
+ const char *epath = ap_escape_uri(p, path);
+ apr_size_t epath_len = strlen(epath);
+
+ dav_buffer_place_mem(p, pbuf, epath, epath_len + 1, pad);
+ return epath_len;
+}
+
/* ### move this to dav_util? */
/* Walk recursively down through directories, *
* including lock-null resources as we go. */
@@ -1537,6 +1549,7 @@
}
while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
apr_size_t len;
+ apr_size_t escaped_len;
len = strlen(dirent.name);
@@ -1579,7 +1592,7 @@
/* copy the file to the URI, too. NOTE: we will pad an extra byte
for the trailing slash later. */
- dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
+ escaped_len = dav_fs_append_uri(pool, &fsctx->uri_buf, dirent.name, 1);
/* if there is a secondary path, then do that, too */
if (fsctx->path2.buf != NULL) {
@@ -1612,7 +1625,7 @@
fsctx->path2.cur_len += len;
/* adjust URI length to incorporate subdir and a slash */
- fsctx->uri_buf.cur_len += len + 1;
+ fsctx->uri_buf.cur_len += escaped_len + 1;
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
@@ -1678,8 +1691,8 @@
*/
dav_buffer_place_mem(pool, &fsctx->path1,
fsctx->locknull_buf.buf + offset, len + 1, 0);
- dav_buffer_place_mem(pool, &fsctx->uri_buf,
- fsctx->locknull_buf.buf + offset, len + 1, 0);
+ dav_fs_append_uri(pool, &fsctx->uri_buf,
+ fsctx->locknull_buf.buf + offset, 0);
if (fsctx->path2.buf != NULL) {
dav_buffer_place_mem(pool, &fsctx->path2,
fsctx->locknull_buf.buf + offset,
Index: modules/dav/main/mod_dav.c
===================================================================
--- a/modules/dav/main/mod_dav.c (revision 1533447)
+++ b/modules/dav/main/mod_dav.c (revision 1533448)
@@ -396,11 +396,9 @@
*/
static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
{
- const char *e_uri = ap_escape_uri(p, uri);
-
/* check the easy case... */
- if (ap_strchr_c(e_uri, '&') == NULL)
- return e_uri;
+ if (ap_strchr_c(uri, '&') == NULL)
+ return uri;
/* there was a '&', so more work is needed... sigh. */
@@ -408,7 +406,7 @@
* Note: this is a teeny bit of overkill since we know there are no
* '<' or '>' characters, but who cares.
*/
- return apr_xml_quote_string(p, e_uri, 0);
+ return apr_xml_quote_string(p, uri, 0);
}
@@ -604,7 +602,8 @@
return DONE;
}
-/* handy function for return values of methods that (may) create things */
+/* handy function for return values of methods that (may) create things.
+ * locn if provided is assumed to be escaped. */
static int dav_created(request_rec *r, const char *locn, const char *what,
int replaced)
{
@@ -612,8 +611,6 @@
if (locn == NULL) {
locn = r->unparsed_uri;
- } else {
- locn = ap_escape_uri(r->pool, locn);
}
/* did the target resource already exist? */
@@ -3004,7 +3001,7 @@
}
/* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
- return dav_created(r, lookup.rnew->uri, "Destination",
+ return dav_created(r, lookup.rnew->unparsed_uri, "Destination",
resnew_state == DAV_RESOURCE_EXISTS);
}
@@ -4610,7 +4607,7 @@
/* return an appropriate response (HTTP_CREATED) */
/* ### spec doesn't say what happens when destination was replaced */
- return dav_created(r, lookup.rnew->uri, "Binding", 0);
+ return dav_created(r, lookup.rnew->unparsed_uri, "Binding", 0);
}
Index: modules/dav/main/mod_dav.h
===================================================================
--- a/modules/dav/main/mod_dav.h (revision 1533447)
+++ b/modules/dav/main/mod_dav.h (revision 1533448)
@@ -386,7 +386,7 @@
* REGULAR and WORKSPACE resources,
* and is always 1 for WORKING */
- const char *uri; /* the URI for this resource */
+ const char *uri; /* the escaped URI for this resource */
dav_resource_private *info; /* the provider's private info */

38
SOURCES/httpd-2.4.6-r1537535.patch

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
# ./pullrev.sh 1537535

http://svn.apache.org/viewvc?view=revision&revision=1537535

--- httpd-2.4.6/modules/ssl/ssl_engine_config.c.r1537535
+++ httpd-2.4.6/modules/ssl/ssl_engine_config.c
@@ -198,7 +198,7 @@ static SSLSrvConfigRec *ssl_config_serve
SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
sc->mc = NULL;
- sc->enabled = SSL_ENABLED_FALSE;
+ sc->enabled = SSL_ENABLED_UNSET;
sc->proxy_enabled = UNSET;
sc->vhost_id = NULL; /* set during module init */
sc->vhost_id_len = 0; /* set during module init */
--- httpd-2.4.6/modules/ssl/ssl_engine_init.c.r1537535
+++ httpd-2.4.6/modules/ssl/ssl_engine_init.c
@@ -289,13 +289,16 @@ int ssl_init_Module(apr_pool_t *p, apr_p
sc->vhost_id = ssl_util_vhostid(p, s);
sc->vhost_id_len = strlen(sc->vhost_id);
- if (ap_get_server_protocol(s) &&
- strcmp("https", ap_get_server_protocol(s)) == 0) {
+ /* Default to enabled if SSLEngine is not set explicitly, and
+ * the protocol is https. */
+ if (ap_get_server_protocol(s)
+ && strcmp("https", ap_get_server_protocol(s)) == 0
+ && sc->enabled == SSL_ENABLED_UNSET) {
sc->enabled = SSL_ENABLED_TRUE;
}
- /* If sc->enabled is UNSET, then SSL is optional on this vhost */
- /* Fix up stuff that may not have been set */
+ /* Fix up stuff that may not have been set. If sc->enabled is
+ * UNSET, then SSL is disabled on this vhost. */
if (sc->enabled == SSL_ENABLED_UNSET) {
sc->enabled = SSL_ENABLED_FALSE;
}

868
SOURCES/httpd-2.4.6-r1542327.patch

@ -0,0 +1,868 @@ @@ -0,0 +1,868 @@
# ./pullrev.sh 1542327
http://svn.apache.org/viewvc?view=revision&revision=1542327

--- httpd-2.4.6/LAYOUT.r1542327
+++ httpd-2.4.6/LAYOUT
@@ -108,7 +108,6 @@ modules/ ................ Manditory and
mod_ssl.c ............... main source file containing API structures
mod_ssl.h ............... common header file of mod_ssl
ssl_engine_config.c ..... module configuration handling
- ssl_engine_dh.c ......... DSA/DH support
ssl_engine_init.c ....... module initialization
ssl_engine_io.c ......... I/O support
ssl_engine_kernel.c ..... SSL engine kernel
--- httpd-2.4.6/modules/ssl/config.m4.r1542327
+++ httpd-2.4.6/modules/ssl/config.m4
@@ -20,7 +20,6 @@ dnl # list of module object files
ssl_objs="dnl
mod_ssl.lo dnl
ssl_engine_config.lo dnl
-ssl_engine_dh.lo dnl
ssl_engine_init.lo dnl
ssl_engine_io.lo dnl
ssl_engine_kernel.lo dnl
--- httpd-2.4.6/modules/ssl/mod_ssl.c.r1542327
+++ httpd-2.4.6/modules/ssl/mod_ssl.c
@@ -515,15 +515,6 @@ int ssl_init_ssl_connection(conn_rec *c,
sslconn->ssl = ssl;
- /*
- * Configure callbacks for SSL connection
- */
- SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
- SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
-#ifndef OPENSSL_NO_EC
- SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH);
-#endif
-
SSL_set_verify_result(ssl, X509_V_OK);
ssl_io_filter_init(c, r, ssl);
--- httpd-2.4.6/modules/ssl/mod_ssl.dsp.r1542327
+++ httpd-2.4.6/modules/ssl/mod_ssl.dsp
@@ -112,10 +112,6 @@ SOURCE=.\ssl_engine_config.c
# End Source File
# Begin Source File
-SOURCE=.\ssl_engine_dh.c
-# End Source File
-# Begin Source File
-
SOURCE=.\ssl_engine_init.c
# End Source File
# Begin Source File
--- httpd-2.4.6/modules/ssl/ssl_engine_config.c.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_engine_config.c
@@ -76,8 +76,6 @@ SSLModConfigRec *ssl_config_global_creat
mc->stapling_mutex = NULL;
#endif
- memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
-
apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
apr_pool_cleanup_null,
pool);
--- httpd-2.4.6/modules/ssl/ssl_engine_dh.c.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_engine_dh.c
@@ -1,244 +0,0 @@
-#if 0
-=pod
-#endif
-
-/* 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.
- */
-
-/* _ _
- * _ __ ___ ___ __| | ___ ___| | mod_ssl
- * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
- * | | | | | | (_) | (_| | \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- * |_____|
- * ssl_engine_dh.c
- * Diffie-Hellman Built-in Temporary Parameters
- */
-
-#include "ssl_private.h"
-
-/* ----BEGIN GENERATED SECTION-------- */
-
-/*
-** Diffie-Hellman-Parameters: (512 bit)
-** prime:
-** 00:9f:db:8b:8a:00:45:44:f0:04:5f:17:37:d0:ba:
-** 2e:0b:27:4c:df:1a:9f:58:82:18:fb:43:53:16:a1:
-** 6e:37:41:71:fd:19:d8:d8:f3:7c:39:bf:86:3f:d6:
-** 0e:3e:30:06:80:a3:03:0c:6e:4c:37:57:d0:8f:70:
-** e6:aa:87:10:33
-** generator: 2 (0x2)
-** Diffie-Hellman-Parameters: (1024 bit)
-** prime:
-** 00:d6:7d:e4:40:cb:bb:dc:19:36:d6:93:d3:4a:fd:
-** 0a:d5:0c:84:d2:39:a4:5f:52:0b:b8:81:74:cb:98:
-** bc:e9:51:84:9f:91:2e:63:9c:72:fb:13:b4:b4:d7:
-** 17:7e:16:d5:5a:c1:79:ba:42:0b:2a:29:fe:32:4a:
-** 46:7a:63:5e:81:ff:59:01:37:7b:ed:dc:fd:33:16:
-** 8a:46:1a:ad:3b:72:da:e8:86:00:78:04:5b:07:a7:
-** db:ca:78:74:08:7d:15:10:ea:9f:cc:9d:dd:33:05:
-** 07:dd:62:db:88:ae:aa:74:7d:e0:f4:d6:e2:bd:68:
-** b0:e7:39:3e:0f:24:21:8e:b3
-** generator: 2 (0x2)
-*/
-
-static unsigned char dh512_p[] = {
- 0x9F, 0xDB, 0x8B, 0x8A, 0x00, 0x45, 0x44, 0xF0, 0x04, 0x5F, 0x17, 0x37,
- 0xD0, 0xBA, 0x2E, 0x0B, 0x27, 0x4C, 0xDF, 0x1A, 0x9F, 0x58, 0x82, 0x18,
- 0xFB, 0x43, 0x53, 0x16, 0xA1, 0x6E, 0x37, 0x41, 0x71, 0xFD, 0x19, 0xD8,
- 0xD8, 0xF3, 0x7C, 0x39, 0xBF, 0x86, 0x3F, 0xD6, 0x0E, 0x3E, 0x30, 0x06,
- 0x80, 0xA3, 0x03, 0x0C, 0x6E, 0x4C, 0x37, 0x57, 0xD0, 0x8F, 0x70, 0xE6,
- 0xAA, 0x87, 0x10, 0x33,
-};
-static unsigned char dh512_g[] = {
- 0x02,
-};
-
-static DH *get_dh512(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
- dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-
-static unsigned char dh1024_p[] = {
- 0xD6, 0x7D, 0xE4, 0x40, 0xCB, 0xBB, 0xDC, 0x19, 0x36, 0xD6, 0x93, 0xD3,
- 0x4A, 0xFD, 0x0A, 0xD5, 0x0C, 0x84, 0xD2, 0x39, 0xA4, 0x5F, 0x52, 0x0B,
- 0xB8, 0x81, 0x74, 0xCB, 0x98, 0xBC, 0xE9, 0x51, 0x84, 0x9F, 0x91, 0x2E,
- 0x63, 0x9C, 0x72, 0xFB, 0x13, 0xB4, 0xB4, 0xD7, 0x17, 0x7E, 0x16, 0xD5,
- 0x5A, 0xC1, 0x79, 0xBA, 0x42, 0x0B, 0x2A, 0x29, 0xFE, 0x32, 0x4A, 0x46,
- 0x7A, 0x63, 0x5E, 0x81, 0xFF, 0x59, 0x01, 0x37, 0x7B, 0xED, 0xDC, 0xFD,
- 0x33, 0x16, 0x8A, 0x46, 0x1A, 0xAD, 0x3B, 0x72, 0xDA, 0xE8, 0x86, 0x00,
- 0x78, 0x04, 0x5B, 0x07, 0xA7, 0xDB, 0xCA, 0x78, 0x74, 0x08, 0x7D, 0x15,
- 0x10, 0xEA, 0x9F, 0xCC, 0x9D, 0xDD, 0x33, 0x05, 0x07, 0xDD, 0x62, 0xDB,
- 0x88, 0xAE, 0xAA, 0x74, 0x7D, 0xE0, 0xF4, 0xD6, 0xE2, 0xBD, 0x68, 0xB0,
- 0xE7, 0x39, 0x3E, 0x0F, 0x24, 0x21, 0x8E, 0xB3,
-};
-static unsigned char dh1024_g[] = {
- 0x02,
-};
-
-static DH *get_dh1024(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-
-/* ----END GENERATED SECTION---------- */
-
-DH *ssl_dh_GetTmpParam(int nKeyLen)
-{
- DH *dh;
-
- if (nKeyLen == 512)
- dh = get_dh512();
- else if (nKeyLen == 1024)
- dh = get_dh1024();
- else
- dh = get_dh1024();
- return dh;
-}
-
-DH *ssl_dh_GetParamFromFile(char *file)
-{
- DH *dh = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(file, "r")) == NULL)
- return NULL;
- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- BIO_free(bio);
- return (dh);
-}
-
-/*
-=cut
-##
-## Embedded Perl script for generating the temporary DH parameters
-##
-
-require 5.003;
-use strict;
-
-# configuration
-my $file = $0;
-my $begin = '----BEGIN GENERATED SECTION--------';
-my $end = '----END GENERATED SECTION----------';
-
-# read ourself and keep a backup
-open(FP, "<$file") || die;
-my $source = '';
-$source .= $_ while (<FP>);
-close(FP);
-open(FP, ">$file.bak") || die;
-print FP $source;
-close(FP);
-
-# generate the DH parameters
-print "1. Generate 512 and 1024 bit Diffie-Hellman parameters (p, g)\n";
-my $rand = '';
-foreach $file (qw(/var/log/messages /var/adm/messages
- /kernel /vmunix /vmlinuz /etc/hosts /etc/resolv.conf)) {
- if (-f $file) {
- $rand = $file if ($rand eq '');
- $rand .= ":$file" if ($rand ne '');
- }
-}
-$rand = "-rand $rand" if ($rand ne '');
-system("openssl gendh $rand -out dh512.pem 512");
-system("openssl gendh $rand -out dh1024.pem 1024");
-
-# generate DH param info
-my $dhinfo = '';
-open(FP, "openssl dh -noout -text -in dh512.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -text -in dh1024.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-$dhinfo =~ s|^|** |mg;
-$dhinfo = "\n\/\*\n$dhinfo\*\/\n\n";
-
-my $indent_args = "-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1";
-
-# generate C source from DH params
-my $dhsource = '';
-open(FP, "openssl dh -noout -C -in dh512.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -C -in dh1024.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-$dhsource =~ s|(DH\s+\*get_dh)(\d+)[^}]*\n}|static $1$2(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh$2_p, sizeof(dh$2_p), NULL);
- dh->g = BN_bin2bn(dh$2_g, sizeof(dh$2_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-|sg;
-
-# generate output
-my $o = $dhinfo . $dhsource;
-
-# insert the generated code at the target location
-$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
-
-# and update the source on disk
-print "Updating file `$file'\n";
-open(FP, ">$file") || die;
-print FP $source;
-close(FP);
-
-# cleanup
-unlink("dh512.pem");
-unlink("dh1024.pem");
-
-=pod
-*/
--- httpd-2.4.6/modules/ssl/ssl_engine_init.c.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_engine_init.c
@@ -56,180 +56,6 @@ static void ssl_add_version_components(a
modver, AP_SERVER_BASEVERSION, incver);
}
-
-/*
- * Handle the Temporary RSA Keys and DH Params
- */
-
-#define MODSSL_TMP_KEY_FREE(mc, type, idx) \
- if (mc->pTmpKeys[idx]) { \
- type##_free((type *)mc->pTmpKeys[idx]); \
- mc->pTmpKeys[idx] = NULL; \
- }
-
-#define MODSSL_TMP_KEYS_FREE(mc, type) \
- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_512); \
- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_1024)
-
-static void ssl_tmp_keys_free(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
- MODSSL_TMP_KEYS_FREE(mc, RSA);
- MODSSL_TMP_KEYS_FREE(mc, DH);
-#ifndef OPENSSL_NO_EC
- MODSSL_TMP_KEY_FREE(mc, EC_KEY, SSL_TMP_KEY_EC_256);
-#endif
-}
-
-static int ssl_tmp_key_init_rsa(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
-#ifdef HAVE_FIPS
-
- if (FIPS_mode() && bits < 1024) {
- mc->pTmpKeys[idx] = NULL;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01877)
- "Init: Skipping generating temporary "
- "%d bit RSA private key in FIPS mode", bits);
- return OK;
- }
-
-#endif
-#ifdef HAVE_GENERATE_EX
- {
- RSA *tkey;
- BIGNUM *bn_f4;
- if (!(tkey = RSA_new())
- || !(bn_f4 = BN_new())
- || !BN_set_word(bn_f4, RSA_F4)
- || !RSA_generate_key_ex(tkey, bits, bn_f4, NULL))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01878)
- "Init: Failed to generate temporary "
- "%d bit RSA private key", bits);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- return !OK;
- }
- BN_free(bn_f4);
- mc->pTmpKeys[idx] = tkey;
- }
-#else
- if (!(mc->pTmpKeys[idx] =
- RSA_generate_key(bits, RSA_F4, NULL, NULL)))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01879)
- "Init: Failed to generate temporary "
- "%d bit RSA private key", bits);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- return !OK;
- }
-#endif
-
- return OK;
-}
-
-static int ssl_tmp_key_init_dh(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
-#ifdef HAVE_FIPS
-
- if (FIPS_mode() && bits < 1024) {
- mc->pTmpKeys[idx] = NULL;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01880)
- "Init: Skipping generating temporary "
- "%d bit DH parameters in FIPS mode", bits);
- return OK;
- }
-
-#endif
-
- if (!(mc->pTmpKeys[idx] =
- ssl_dh_GetTmpParam(bits)))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01881)
- "Init: Failed to generate temporary "
- "%d bit DH parameters", bits);
- return !OK;
- }
-
- return OK;
-}
-
-#ifndef OPENSSL_NO_EC
-static int ssl_tmp_key_init_ec(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
- EC_KEY *ecdh = NULL;
-
- /* XXX: Are there any FIPS constraints we should enforce? */
-
- if (bits != 256) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02298)
- "Init: Failed to generate temporary "
- "%d bit EC parameters, only 256 bits supported", bits);
- return !OK;
- }
-
- if ((ecdh = EC_KEY_new()) == NULL ||
- EC_KEY_set_group(ecdh, EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 1)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02299)
- "Init: Failed to generate temporary "
- "%d bit EC parameters", bits);
- return !OK;
- }
-
- mc->pTmpKeys[idx] = ecdh;
- return OK;
-}
-
-#define MODSSL_TMP_KEY_INIT_EC(s, bits) \
- ssl_tmp_key_init_ec(s, bits, SSL_TMP_KEY_EC_##bits)
-
-#endif
-
-#define MODSSL_TMP_KEY_INIT_RSA(s, bits) \
- ssl_tmp_key_init_rsa(s, bits, SSL_TMP_KEY_RSA_##bits)
-
-#define MODSSL_TMP_KEY_INIT_DH(s, bits) \
- ssl_tmp_key_init_dh(s, bits, SSL_TMP_KEY_DH_##bits)
-
-static int ssl_tmp_keys_init(server_rec *s)
-{
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary RSA private keys (512/1024 bits)");
-
- if (MODSSL_TMP_KEY_INIT_RSA(s, 512) ||
- MODSSL_TMP_KEY_INIT_RSA(s, 1024)) {
- return !OK;
- }
-
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary DH parameters (512/1024 bits)");
-
- if (MODSSL_TMP_KEY_INIT_DH(s, 512) ||
- MODSSL_TMP_KEY_INIT_DH(s, 1024)) {
- return !OK;
- }
-
-#ifndef OPENSSL_NO_EC
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary EC parameters (256 bits)");
-
- if (MODSSL_TMP_KEY_INIT_EC(s, 256)) {
- return !OK;
- }
-#endif
-
- return OK;
-}
-
/*
* Per-module initialization
*/
@@ -370,10 +196,6 @@ int ssl_init_Module(apr_pool_t *p, apr_p
*/
ssl_pphrase_Handle(base_server, ptemp);
- if (ssl_tmp_keys_init(base_server)) {
- return !OK;
- }
-
/*
* initialize the mutex handling
*/
@@ -681,6 +503,9 @@ static void ssl_init_ctx_protocol(server
* Configure additional context ingredients
*/
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
+#ifndef OPENSSL_NO_EC
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
/*
@@ -721,11 +546,7 @@ static void ssl_init_ctx_callbacks(serve
{
SSL_CTX *ctx = mctx->ssl_ctx;
- SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
-#ifndef OPENSSL_NO_EC
- SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH);
-#endif
SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
@@ -1165,12 +986,16 @@ static void ssl_init_server_certs(server
modssl_ctx_t *mctx)
{
const char *rsa_id, *dsa_id;
-#ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
const char *ecc_id;
+ EC_GROUP *ecparams;
+ int nid;
+ EC_KEY *eckey;
#endif
const char *vhost_id = mctx->sc->vhost_id;
int i;
int have_rsa, have_dsa;
+ DH *dhparams;
#ifndef OPENSSL_NO_EC
int have_ecc;
#endif
@@ -1217,6 +1042,40 @@ static void ssl_init_server_certs(server
"Oops, no " KEYTYPES " server private key found?!");
ssl_die(s);
}
+
+ /*
+ * Try to read DH parameters from the (first) SSLCertificateFile
+ */
+ if ((mctx->pks->cert_files[0] != NULL) &&
+ (dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) {
+ 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",
+ BN_num_bits(dhparams->p), vhost_id,
+ mctx->pks->cert_files[0]);
+ }
+
+#ifndef OPENSSL_NO_EC
+ /*
+ * Similarly, try to read the ECDH curve name from SSLCertificateFile...
+ */
+ if ((mctx->pks->cert_files[0] != NULL) &&
+ (ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) &&
+ (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",
+ OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]);
+ }
+ /*
+ * ...otherwise, configure NIST P-256 (required to enable ECDHE)
+ */
+ else {
+ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
+ EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ }
+#endif
}
#ifdef HAVE_TLS_SESSION_TICKETS
@@ -1754,11 +1613,6 @@ apr_status_t ssl_init_ModuleKill(void *d
ssl_scache_kill(base_server);
/*
- * Destroy the temporary keys and params
- */
- ssl_tmp_keys_free(base_server);
-
- /*
* Free the non-pool allocated structures
* in the per-server configurations
*/
--- httpd-2.4.6/modules/ssl/ssl_engine_kernel.c.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_engine_kernel.c
@@ -1289,117 +1289,70 @@ const authz_provider ssl_authz_provider_
*/
/*
- * Handle out temporary RSA private keys on demand
- *
- * The background of this as the TLSv1 standard explains it:
- *
- * | D.1. Temporary RSA keys
- * |
- * | US Export restrictions limit RSA keys used for encryption to 512
- * | bits, but do not place any limit on lengths of RSA keys used for
- * | signing operations. Certificates often need to be larger than 512
- * | bits, since 512-bit RSA keys are not secure enough for high-value
- * | transactions or for applications requiring long-term security. Some
- * | certificates are also designated signing-only, in which case they
- * | cannot be used for key exchange.
- * |
- * | When the public key in the certificate cannot be used for encryption,
- * | the server signs a temporary RSA key, which is then exchanged. In
- * | exportable applications, the temporary RSA key should be the maximum
- * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are
- * | relatively insecure, they should be changed often. For typical
- * | electronic commerce applications, it is suggested that keys be
- * | changed daily or every 500 transactions, and more often if possible.
- * | Note that while it is acceptable to use the same temporary key for
- * | multiple transactions, it must be signed each time it is used.
- * |
- * | RSA key generation is a time-consuming process. In many cases, a
- * | low-priority process can be assigned the task of key generation.
- * | Whenever a new key is completed, the existing temporary key can be
- * | replaced with the new one.
- *
- * XXX: base on comment above, if thread support is enabled,
- * we should spawn a low-priority thread to generate new keys
- * on the fly.
- *
- * So we generated 512 and 1024 bit temporary keys on startup
- * which we now just hand out on demand....
+ * Grab well-defined DH parameters from OpenSSL, see <openssl/bn.h>
+ * (get_rfc*) for all available primes.
*/
-
-RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen)
-{
- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary %d bit RSA key", keylen);
-
- /* doesn't matter if export flag is on,
- * we won't be asked for keylen > 512 in that case.
- * if we are asked for a keylen > 1024, it is too expensive
- * to generate on the fly.
- * XXX: any reason not to generate 2048 bit keys at startup?
- */
-
- switch (keylen) {
- case 512:
- idx = SSL_TMP_KEY_RSA_512;
- break;
-
- case 1024:
- default:
- idx = SSL_TMP_KEY_RSA_1024;
- }
-
- return (RSA *)mc->pTmpKeys[idx];
+#define make_get_dh(rfc,size,gen) \
+static DH *get_dh##size(void) \
+{ \
+ DH *dh; \
+ if (!(dh = DH_new())) { \
+ return NULL; \
+ } \
+ dh->p = get_##rfc##_prime_##size(NULL); \
+ BN_dec2bn(&dh->g, #gen); \
+ if (!dh->p || !dh->g) { \
+ DH_free(dh); \
+ return NULL; \
+ } \
+ return dh; \
}
/*
- * Hand out the already generated DH parameters...
+ * Prepare DH parameters from 1024 to 4096 bits, in 1024-bit increments
+ */
+make_get_dh(rfc2409, 1024, 2)
+make_get_dh(rfc3526, 2048, 2)
+make_get_dh(rfc3526, 3072, 2)
+make_get_dh(rfc3526, 4096, 2)
+
+/*
+ * Hand out standard DH parameters, based on the authentication strength
*/
DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
{
conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary %d bit DH key", keylen);
+ EVP_PKEY *pkey = SSL_get_privatekey(ssl);
+ int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
- switch (keylen) {
- case 512:
- idx = SSL_TMP_KEY_DH_512;
- break;
-
- case 1024:
- default:
- idx = SSL_TMP_KEY_DH_1024;
+ /*
+ * OpenSSL will call us with either keylen == 512 or keylen == 1024
+ * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
+ * Adjust the DH parameter length according to the size of the
+ * RSA/DSA private key used for the current connection, and always
+ * use at least 1024-bit parameters.
+ * Note: This may cause interoperability issues with implementations
+ * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
+ * In this case, SSLCertificateFile can be used to specify fixed
+ * 1024-bit DH parameters (with the effect that OpenSSL skips this
+ * callback).
+ */
+ if ((type == EVP_PKEY_RSA) || (type == EVP_PKEY_DSA)) {
+ keylen = EVP_PKEY_bits(pkey);
}
- return (DH *)mc->pTmpKeys[idx];
-}
-
-#ifndef OPENSSL_NO_EC
-EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen)
-{
- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- /* XXX Uses 256-bit key for now. TODO: support other sizes. */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary 256 bit ECC key");
-
- switch (keylen) {
- case 256:
- default:
- idx = SSL_TMP_KEY_EC_256;
- }
+ "handing out built-in DH parameters for %d-bit authenticated connection", keylen);
- return (EC_KEY *)mc->pTmpKeys[idx];
+ if (keylen >= 4096)
+ return get_dh4096();
+ else if (keylen >= 3072)
+ return get_dh3072();
+ else if (keylen >= 2048)
+ return get_dh2048();
+ else
+ return get_dh1024();
}
-#endif
/*
* This OpenSSL callback function is called when OpenSSL
--- httpd-2.4.6/modules/ssl/ssl_private.h.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_private.h
@@ -310,22 +310,6 @@ typedef int ssl_algo_t;
#define SSL_AIDX_MAX (2)
#endif
-
-/**
- * Define IDs for the temporary RSA keys and DH params
- */
-
-#define SSL_TMP_KEY_RSA_512 (0)
-#define SSL_TMP_KEY_RSA_1024 (1)
-#define SSL_TMP_KEY_DH_512 (2)
-#define SSL_TMP_KEY_DH_1024 (3)
-#ifndef OPENSSL_NO_EC
-#define SSL_TMP_KEY_EC_256 (4)
-#define SSL_TMP_KEY_MAX (5)
-#else
-#define SSL_TMP_KEY_MAX (4)
-#endif
-
/**
* Define the SSL options
*/
@@ -547,7 +531,6 @@ typedef struct {
apr_global_mutex_t *pMutex;
apr_array_header_t *aRandSeed;
apr_hash_t *tVHostKeys;
- void *pTmpKeys[SSL_TMP_KEY_MAX];
/* Two hash tables of pointers to ssl_asn1_t structures. The
* structures are used to store certificates and private keys
@@ -837,11 +820,7 @@ extern const authz_provider ssl_authz_pr
extern const authz_provider ssl_authz_provider_verify_client;
/** OpenSSL callbacks */
-RSA *ssl_callback_TmpRSA(SSL *, int, int);
DH *ssl_callback_TmpDH(SSL *, int, int);
-#ifndef OPENSSL_NO_EC
-EC_KEY *ssl_callback_TmpECDH(SSL *, int, int);
-#endif
int ssl_callback_SSLVerify(int, X509_STORE_CTX *);
int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *);
int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
@@ -921,8 +900,10 @@ int ssl_init_ssl_connection(con
void ssl_pphrase_Handle(server_rec *, apr_pool_t *);
/** Diffie-Hellman Parameter Support */
-DH *ssl_dh_GetTmpParam(int);
-DH *ssl_dh_GetParamFromFile(char *);
+DH *ssl_dh_GetParamFromFile(const char *);
+#ifndef OPNESSL_NO_EC
+EC_GROUP *ssl_ec_GetParamFromFile(const char *);
+#endif
unsigned char *ssl_asn1_table_set(apr_hash_t *table,
const char *key,
--- httpd-2.4.6/modules/ssl/ssl_util_ssl.c.r1542327
+++ httpd-2.4.6/modules/ssl/ssl_util_ssl.c
@@ -483,6 +483,38 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t
/* _________________________________________________________________
**
+** Custom (EC)DH parameter support
+** _________________________________________________________________
+*/
+
+DH *ssl_dh_GetParamFromFile(const char *file)
+{
+ DH *dh = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(file, "r")) == NULL)
+ return NULL;
+ dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return (dh);
+}
+
+#ifndef OPENSSL_NO_EC
+EC_GROUP *ssl_ec_GetParamFromFile(const char *file)
+{
+ EC_GROUP *group = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(file, "r")) == NULL)
+ return NULL;
+ group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return (group);
+}
+#endif
+
+/* _________________________________________________________________
+**
** Extra Server Certificate Chain Support
** _________________________________________________________________
*/

28
SOURCES/httpd-2.4.6-r1553540.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
# ./pullrev.sh 1553540

https://bugzilla.redhat.com/show_bug.cgi?id=1040447

http://svn.apache.org/viewvc?view=revision&revision=1553540

--- httpd-2.4.6/modules/proxy/mod_proxy_http.c
+++ httpd-2.4.6/modules/proxy/mod_proxy_http.c
@@ -710,7 +710,7 @@
force10 = 0;
}
- header_brigade = apr_brigade_create(p, origin->bucket_alloc);
+ header_brigade = apr_brigade_create(p, bucket_alloc);
rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
worker, conf, uri, url, server_portstr,
&old_cl_val, &old_te_val);
@@ -1813,6 +1813,10 @@
}
} while (interim_response && (interim_response < AP_MAX_INTERIM_RESPONSES));
+ /* We have to cleanup bb brigade, because buckets inserted to it could be
+ * created from scpool and this pool can be freed before this brigade. */
+ apr_brigade_cleanup(bb);
+
/* See define of AP_MAX_INTERIM_RESPONSES for why */
if (interim_response >= AP_MAX_INTERIM_RESPONSES) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,

31
SOURCES/httpd-2.4.6-r1556473.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
# ./pullrev.sh 1556473

https://bugzilla.redhat.com/show_bug.cgi?id=1036666

http://svn.apache.org/viewvc?view=revision&revision=1556473

--- httpd-2.4.6/modules/ssl/ssl_engine_config.c
+++ httpd-2.4.6/modules/ssl/ssl_engine_config.c
@@ -699,9 +699,20 @@
#ifndef SSL_OP_NO_COMPRESSION
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err)
- return "This version of openssl does not support configuring "
- "compression within <VirtualHost> sections.";
+ return "This version of OpenSSL does not support enabling "
+ "SSLCompression within <VirtualHost> sections.";
#endif
+ if (flag) {
+ /* Some (packaged) versions of OpenSSL do not support
+ * compression by default. Enabling this directive would not
+ * have the desired effect, so fail with an error. */
+ STACK_OF(SSL_COMP) *meths = SSL_COMP_get_compression_methods();
+
+ if (sk_SSL_COMP_num(meths) == 0) {
+ return "This version of OpenSSL does not have any compression methods "
+ "available, cannot enable SSLCompression.";
+ }
+ }
sc->compression = flag ? TRUE : FALSE;
return NULL;
#else

26
SOURCES/httpd-2.4.6-r1556818.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
# ./pullrev.sh r1556818
http://svn.apache.org/viewvc?view=revision&revision=r1556818
--- httpd-2.4.6/modules/aaa/mod_authn_core.c 2014/01/09 14:30:23 1556817
+++ httpd-2.4.6/modules/aaa/mod_authn_core.c 2014/01/09 14:32:47 1556818
@@ -179,6 +179,12 @@
return (void *) authcfg;
}
+/* Only per-server directive we have is GLOBAL_ONLY */
+static void *merge_authn_alias_svr_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+ return basev;
+}
+
static const authn_provider authn_alias_provider =
{
&authn_alias_check_password,
@@ -373,7 +379,7 @@
create_authn_core_dir_config, /* dir config creater */
merge_authn_core_dir_config, /* dir merger --- default is to override */
create_authn_alias_svr_config, /* server config */
- NULL, /* merge server config */
+ merge_authn_alias_svr_config, /* merge server config */
authn_cmds,
register_hooks /* register hooks */
};

16
SOURCES/httpd-2.4.6-r1560093.patch

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
# ./pullrev.sh 1560093

https://bugzilla.redhat.com/show_bug.cgi?id=1331341

http://svn.apache.org/viewvc?view=revision&revision=1560093

--- httpd-2.4.6/modules/cache/mod_cache.c
+++ httpd-2.4.6/modules/cache/mod_cache.c
@@ -1130,7 +1130,6 @@
"Content-Range")))
|| ((reason = cache_header_cmp(r->pool, left, right,
"Content-Type")))
- || ((reason = cache_header_cmp(r->pool, left, right, "Expires")))
|| ((reason = cache_header_cmp(r->pool, left, right, "ETag")))
|| ((reason = cache_header_cmp(r->pool, left, right,
"Last-Modified")))) {

19
SOURCES/httpd-2.4.6-r1569006.patch

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
--- a/modules/metadata/mod_remoteip.c 2014/02/17 14:11:38 1569005
+++ b/modules/metadata/mod_remoteip.c 2014/02/17 14:12:30 1569006
@@ -246,14 +246,14 @@
while (remote) {
- /* verify c->client_addr is trusted if there is a trusted proxy list
+ /* verify user agent IP against the trusted proxy list
*/
if (config->proxymatch_ip) {
int i;
remoteip_proxymatch_t *match;
match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts;
for (i = 0; i < config->proxymatch_ip->nelts; ++i) {
- if (apr_ipsubnet_test(match[i].ip, c->client_addr)) {
+ if (apr_ipsubnet_test(match[i].ip, temp_sa)) {
internal = match[i].internal;
break;
}

20
SOURCES/httpd-2.4.6-r1570327.patch

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
# ./pullrev.sh 1570327
http://svn.apache.org/viewvc?view=revision&revision=1570327

https://bugzilla.redhat.com/show_bug.cgi?id=1327624

--- httpd-2.4.6/server/mpm_unix.c
+++ httpd-2.4.6/server/mpm_unix.c
@@ -742,7 +742,12 @@
* readers stranded (a number of them could be tied up for
* a while serving time-consuming requests)
*/
+ /* Recall: we only worry about IDLE child processes here */
for (i = 0; i < num && rv == APR_SUCCESS; i++) {
+ if (ap_scoreboard_image->servers[i][0].status != SERVER_READY ||
+ ap_scoreboard_image->servers[i][0].pid == 0) {
+ continue;
+ }
rv = dummy_connection(pod);
}
}

29
SOURCES/httpd-2.4.6-r1573626.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
--- a/modules/proxy/mod_proxy.c 2014/03/03 17:28:10 1573625
+++ b/modules/proxy/mod_proxy.c 2014/03/03 17:28:17 1573626
@@ -927,8 +927,25 @@
struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts;
/* is this for us? */
- if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
+ if (!r->filename) {
return DECLINED;
+ }
+
+ if (!r->proxyreq) {
+ /* We may have forced the proxy handler via config or .htaccess */
+ if (r->handler &&
+ strncmp(r->handler, "proxy:", 6) == 0 &&
+ strncmp(r->filename, "proxy:", 6) != 0) {
+ r->proxyreq = PROXYREQ_REVERSE;
+ r->filename = apr_pstrcat(r->pool, r->handler, r->filename, NULL);
+ apr_table_setn(r->notes, "rewrite-proxy", "1");
+ }
+ else {
+ return DECLINED;
+ }
+ } else if (strncmp(r->filename, "proxy:", 6) != 0) {
+ return DECLINED;
+ }
/* handle max-forwards / OPTIONS / TRACE */
if ((str = apr_table_get(r->headers_in, "Max-Forwards"))) {

92
SOURCES/httpd-2.4.6-r1587053.patch

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index 525109a..eb34eee 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -103,10 +103,12 @@ static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o,
rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES,
APR_NONBLOCK_READ, AP_IOBUFSIZE);
if (rv == APR_SUCCESS) {
- if (c_o->aborted)
+ if (c_o->aborted) {
return APR_EPIPE;
- if (APR_BRIGADE_EMPTY(bb))
+ }
+ if (APR_BRIGADE_EMPTY(bb)){
break;
+ }
#ifdef DEBUGGING
len = -1;
apr_brigade_length(bb, 0, &len);
@@ -178,7 +180,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
conn_rec *c = r->connection;
apr_socket_t *sock = conn->sock;
conn_rec *backconn = conn->connection;
- int client_error = 0;
char *buf;
apr_bucket_brigade *header_brigade;
apr_bucket *e;
@@ -224,7 +225,7 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
pollfd.p = p;
pollfd.desc_type = APR_POLL_SOCKET;
- pollfd.reqevents = APR_POLLIN;
+ pollfd.reqevents = APR_POLLIN | APR_POLLHUP;
pollfd.desc.s = sock;
pollfd.client_data = NULL;
apr_pollset_add(pollset, &pollfd);
@@ -237,6 +238,9 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
r->proto_output_filters = c->output_filters;
r->input_filters = c->input_filters;
r->proto_input_filters = c->input_filters;
+ /* This handler should take care of the entire connection; make it so that
+ * nothing else is attempted on the connection after returning. */
+ c->keepalive = AP_CONN_CLOSE;
remove_reqtimeout(r->input_filters);
@@ -257,26 +261,28 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
if (cur->desc.s == sock) {
pollevent = cur->rtnevents;
- if (pollevent & APR_POLLIN) {
+ if (pollevent & (APR_POLLIN | APR_POLLHUP)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02446)
"sock was readable");
rv = proxy_wstunnel_transfer(r, backconn, c, bb, "sock");
}
- else if ((pollevent & APR_POLLERR)
- || (pollevent & APR_POLLHUP)) {
+ else if (pollevent & APR_POLLERR) {
rv = APR_EPIPE;
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447)
- "err/hup on backconn");
+ "err on backconn");
}
- if (rv != APR_SUCCESS)
- client_error = 1;
}
else if (cur->desc.s == client_socket) {
pollevent = cur->rtnevents;
- if (pollevent & APR_POLLIN) {
+ if (pollevent & (APR_POLLIN | APR_POLLHUP)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02448)
"client was readable");
rv = proxy_wstunnel_transfer(r, c, backconn, bb, "client");
+ } else if (pollevent & APR_POLLERR) {
+ rv = APR_EPIPE;
+ c->aborted = 1;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02607)
+ "error on client conn");
}
}
else {
@@ -294,9 +300,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
"finished with poll() - cleaning up");
- if (client_error) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
return OK;
}

35
SOURCES/httpd-2.4.6-r1593002.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
--- a/modules/ssl/ssl_util_stapling.c 2014/05/07 12:51:38 1593001
+++ b/modules/ssl/ssl_util_stapling.c 2014/05/07 12:52:13 1593002
@@ -145,14 +145,15 @@
X509_digest(x, EVP_sha1(), cinf->idx, NULL);
aia = X509_get1_ocsp(x);
- if (aia)
+ if (aia) {
cinf->uri = sk_OPENSSL_STRING_pop(aia);
+ X509_email_free(aia);
+ }
if (!cinf->uri && !mctx->stapling_force_url) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02218)
"ssl_stapling_init_cert: no responder URL");
+ return 0;
}
- if (aia)
- X509_email_free(aia);
return 1;
}
@@ -403,6 +404,13 @@
else
ocspuri = cinf->uri;
+ if (!ocspuri) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02621)
+ "stapling_renew_response: no uri for responder");
+ rv = FALSE;
+ goto done;
+ }
+
/* Create a temporary pool to constrain memory use */
apr_pool_create(&vpool, conn->pool);

25
SOURCES/httpd-2.4.6-r1594625.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
Index: modules/proxy/mod_proxy_wstunnel.c
===================================================================
--- a/modules/proxy/mod_proxy_wstunnel.c (revision 1593857)
+++ b/modules/proxy/mod_proxy_wstunnel.c (revision 1594625)
@@ -477,9 +477,11 @@
conn_rec *c = r->connection;
apr_pool_t *p = r->pool;
apr_uri_t *uri;
+ int is_ssl = 0;
if (strncasecmp(url, "wss:", 4) == 0) {
scheme = "WSS";
+ is_ssl = 1;
}
else if (strncasecmp(url, "ws:", 3) == 0) {
scheme = "WS";
@@ -503,7 +505,7 @@
return status;
}
- backend->is_ssl = 0;
+ backend->is_ssl = is_ssl;
backend->close = 0;
retry = 0;

22
SOURCES/httpd-2.4.6-r1604460.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
--- a/modules/filters/mod_deflate.c 2014/02/26 15:24:07 1572091
+++ b/modules/filters/mod_deflate.c 2014/02/26 15:30:25 1572092
@@ -1125,7 +1125,8 @@
}
ctx->stream.next_in += 4;
compLen = getLong(ctx->stream.next_in);
- if (ctx->stream.total_out != compLen) {
+ /* gzip stores original size only as 4 byte value */
+ if ((ctx->stream.total_out & 0xFFFFFFFF) != compLen) {
inflateEnd(&ctx->stream);
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01395)
"Zlib: Length %ld of inflated data does "
@@ -1322,7 +1323,8 @@
}
ctx->validation_buffer += VALIDATION_SIZE / 2;
compLen = getLong(ctx->validation_buffer);
- if (ctx->stream.total_out != compLen) {
+ /* gzip stores original size only as 4 byte value */
+ if ((ctx->stream.total_out & 0xFFFFFFFF) != compLen) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01400)
"Zlib: Length of inflated stream invalid");
return APR_EGENERAL;

141
SOURCES/httpd-2.4.6-r1610013.patch

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
Index: modules/dav/main/mod_dav.c
===================================================================
--- a/modules/dav/main/mod_dav.c (revision 1610012)
+++ b/modules/dav/main/mod_dav.c (revision 1610013)
@@ -396,9 +396,11 @@
*/
static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
{
+ const char *e_uri = ap_escape_uri(p, uri);
+
/* check the easy case... */
- if (ap_strchr_c(uri, '&') == NULL)
- return uri;
+ if (ap_strchr_c(e_uri, '&') == NULL)
+ return e_uri;
/* there was a '&', so more work is needed... sigh. */
@@ -406,7 +408,7 @@
* Note: this is a teeny bit of overkill since we know there are no
* '<' or '>' characters, but who cares.
*/
- return apr_xml_quote_string(p, uri, 0);
+ return apr_xml_quote_string(p, e_uri, 0);
}
Index: modules/dav/main/mod_dav.h
===================================================================
--- a/modules/dav/main/mod_dav.h (revision 1610012)
+++ b/modules/dav/main/mod_dav.h (revision 1610013)
@@ -386,7 +386,9 @@
* REGULAR and WORKSPACE resources,
* and is always 1 for WORKING */
- const char *uri; /* the escaped URI for this resource */
+ const char *uri; /* the URI for this resource;
+ * currently has an ABI flaw where sometimes it is
+ * assumed to be encoded and sometimes not */
dav_resource_private *info; /* the provider's private info */
Index: modules/dav/main/props.c
===================================================================
--- a/modules/dav/main/props.c (revision 1610012)
+++ b/modules/dav/main/props.c (revision 1610013)
@@ -321,10 +321,14 @@
/* do a sub-request to fetch properties for the target resource's URI. */
static void dav_do_prop_subreq(dav_propdb *propdb)
{
+ /* need to escape the uri that's in the resource struct because during
+ * the property walker it's not encoded. */
+ const char *e_uri = ap_escape_uri(propdb->resource->pool,
+ propdb->resource->uri);
+
/* perform a "GET" on the resource's URI (note that the resource
may not correspond to the current request!). */
- propdb->subreq = ap_sub_req_lookup_uri(propdb->resource->uri, propdb->r,
- NULL);
+ propdb->subreq = ap_sub_req_lookup_uri(e_uri, propdb->r, NULL);
}
static dav_error * dav_insert_coreprop(dav_propdb *propdb,
Index: modules/dav/fs/repos.c
===================================================================
--- a/modules/dav/fs/repos.c (revision 1610012)
+++ b/modules/dav/fs/repos.c (revision 1610013)
@@ -717,13 +717,13 @@
resource->pool = r->pool;
/* make sure the URI does not have a trailing "/" */
- len = strlen(r->unparsed_uri);
- if (len > 1 && r->unparsed_uri[len - 1] == '/') {
- s = apr_pstrmemdup(r->pool, r->unparsed_uri, len-1);
+ len = strlen(r->uri);
+ if (len > 1 && r->uri[len - 1] == '/') {
+ s = apr_pstrmemdup(r->pool, r->uri, len-1);
resource->uri = s;
}
else {
- resource->uri = r->unparsed_uri;
+ resource->uri = r->uri;
}
if (r->finfo.filetype != APR_NOFILE) {
@@ -1482,18 +1482,6 @@
return dav_fs_deleteset(info->pool, resource);
}
-/* Take an unescaped path component and escape it and append it onto a
- * dav_buffer for a URI */
-static apr_size_t dav_fs_append_uri(apr_pool_t *p, dav_buffer *pbuf,
- const char *path, apr_size_t pad)
-{
- const char *epath = ap_escape_uri(p, path);
- apr_size_t epath_len = strlen(epath);
-
- dav_buffer_place_mem(p, pbuf, epath, epath_len + 1, pad);
- return epath_len;
-}
-
/* ### move this to dav_util? */
/* Walk recursively down through directories, *
* including lock-null resources as we go. */
@@ -1549,7 +1537,6 @@
}
while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
apr_size_t len;
- apr_size_t escaped_len;
len = strlen(dirent.name);
@@ -1592,7 +1579,7 @@
/* copy the file to the URI, too. NOTE: we will pad an extra byte
for the trailing slash later. */
- escaped_len = dav_fs_append_uri(pool, &fsctx->uri_buf, dirent.name, 1);
+ dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
/* if there is a secondary path, then do that, too */
if (fsctx->path2.buf != NULL) {
@@ -1625,7 +1612,7 @@
fsctx->path2.cur_len += len;
/* adjust URI length to incorporate subdir and a slash */
- fsctx->uri_buf.cur_len += escaped_len + 1;
+ fsctx->uri_buf.cur_len += len + 1;
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
@@ -1691,8 +1678,8 @@
*/
dav_buffer_place_mem(pool, &fsctx->path1,
fsctx->locknull_buf.buf + offset, len + 1, 0);
- dav_fs_append_uri(pool, &fsctx->uri_buf,
- fsctx->locknull_buf.buf + offset, 0);
+ dav_buffer_place_mem(pool, &fsctx->uri_buf,
+ fsctx->locknull_buf.buf + offset, len + 1, 0);
if (fsctx->path2.buf != NULL) {
dav_buffer_place_mem(pool, &fsctx->path2,
fsctx->locknull_buf.buf + offset,

189
SOURCES/httpd-2.4.6-r1610396.patch

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
Index: modules/ldap/util_ldap.c
===================================================================
--- a/modules/ldap/util_ldap.c (revision 1610395)
+++ b/modules/ldap/util_ldap.c (revision 1610396)
@@ -157,10 +157,12 @@
*/
if (!ldc->keep) {
uldap_connection_unbind(ldc);
+ ldc->r = NULL;
}
else {
/* mark our connection as available for reuse */
ldc->freed = apr_time_now();
+ ldc->r = NULL;
#if APR_HAS_THREADS
apr_thread_mutex_unlock(ldc->lock);
#endif
@@ -179,6 +181,9 @@
if (ldc) {
if (ldc->ldap) {
+ if (ldc->r) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, ldc->r, "LDC %pp unbind", ldc);
+ }
ldap_unbind_s(ldc->ldap);
ldc->ldap = NULL;
}
@@ -319,6 +324,8 @@
return(result->rc);
}
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "LDC %pp init", ldc);
+
if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
/* Now that we have an ldap struct, add it to the referral list for rebinds. */
rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);
@@ -516,6 +523,10 @@
ldc->reason = "LDAP: ldap_simple_bind() parse result failed";
return uldap_ld_errno(ldc);
}
+ else {
+ ldc->last_backend_conn = ldc->r->request_time;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, ldc->r, "LDC %pp bind", ldc);
+ }
return rc;
}
@@ -540,7 +551,7 @@
/* If the connection is already bound, return
*/
- if (ldc->bound)
+ if (ldc->bound && !ldc->must_rebind)
{
ldc->reason = "LDAP: connection open successful (already bound)";
return LDAP_SUCCESS;
@@ -621,6 +632,7 @@
}
else {
ldc->bound = 1;
+ ldc->must_rebind = 0;
ldc->reason = "LDAP: connection open successful";
}
@@ -718,13 +730,17 @@
&& !compare_client_certs(dc->client_certs, l->client_certs))
{
if (st->connection_pool_ttl > 0) {
- if (l->bound && (now - l->freed) > st->connection_pool_ttl) {
+ if (l->bound && (now - l->last_backend_conn) > st->connection_pool_ttl) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"Removing LDAP connection last used %" APR_TIME_T_FMT " seconds ago",
- (now - l->freed) / APR_USEC_PER_SEC);
+ (now - l->last_backend_conn) / APR_USEC_PER_SEC);
+ l->r = r;
uldap_connection_unbind(l);
/* Go ahead (by falling through) and use it, so we don't create more just to unbind some other old ones */
}
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
+ "Reuse %s LDC %pp",
+ l->bound ? "bound" : "unbound", l);
}
break;
}
@@ -751,12 +767,25 @@
(l->deref == deref) && (l->secure == secureflag) &&
!compare_client_certs(dc->client_certs, l->client_certs))
{
+ if (st->connection_pool_ttl > 0) {
+ if (l->bound && (now - l->last_backend_conn) > st->connection_pool_ttl) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "Removing LDAP connection last used %" APR_TIME_T_FMT " seconds ago",
+ (now - l->last_backend_conn) / APR_USEC_PER_SEC);
+ l->r = r;
+ uldap_connection_unbind(l);
+ /* Go ahead (by falling through) and use it, so we don't create more just to unbind some other old ones */
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
+ "Reuse %s LDC %pp (will rebind)",
+ l->bound ? "bound" : "unbound", l);
+ }
+
/* the bind credentials have changed */
- /* no check for connection_pool_ttl, since we are unbinding any way */
- uldap_connection_unbind(l);
-
+ l->must_rebind = 1;
util_ldap_strdup((char**)&(l->binddn), binddn);
util_ldap_strdup((char**)&(l->bindpw), bindpw);
+
break;
}
#if APR_HAS_THREADS
@@ -846,6 +875,7 @@
#if APR_HAS_THREADS
apr_thread_mutex_unlock(st->mutex);
#endif
+ l->r = r;
return l;
}
@@ -965,6 +995,7 @@
return result;
}
+ ldc->last_backend_conn = r->request_time;
entry = ldap_first_entry(ldc->ldap, res);
searchdn = ldap_get_dn(ldc->ldap, entry);
@@ -1116,6 +1147,7 @@
goto start_over;
}
+ ldc->last_backend_conn = r->request_time;
ldc->reason = "Comparison complete";
if ((LDAP_COMPARE_TRUE == result) ||
(LDAP_COMPARE_FALSE == result) ||
@@ -1241,6 +1273,7 @@
return res;
}
+ ldc->last_backend_conn = r->request_time;
entry = ldap_first_entry(ldc->ldap, sga_res);
/*
@@ -1723,6 +1756,7 @@
* We should have found exactly one entry; to find a different
* number is an error.
*/
+ ldc->last_backend_conn = r->request_time;
count = ldap_count_entries(ldc->ldap, res);
if (count != 1)
{
@@ -1788,10 +1822,10 @@
/*
* We have just bound the connection to a different user and password
* combination, which might be reused unintentionally next time this
- * connection is used from the connection pool. To ensure no confusion,
- * we mark the connection as unbound.
+ * connection is used from the connection pool.
*/
- ldc->bound = 0;
+ ldc->must_rebind = 0;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "LDC %pp used for authn, must be rebound", ldc);
}
/*
@@ -1983,6 +2017,7 @@
* We should have found exactly one entry; to find a different
* number is an error.
*/
+ ldc->last_backend_conn = r->request_time;
count = ldap_count_entries(ldc->ldap, res);
if (count != 1)
{
Index: include/util_ldap.h
===================================================================
--- a/include/util_ldap.h (revision 1610395)
+++ b/include/util_ldap.h (revision 1610396)
@@ -133,6 +133,9 @@
int ReferralHopLimit; /* # of referral hops to follow (default = AP_LDAP_DEFAULT_HOPLIMIT) */
apr_time_t freed; /* the time this conn was placed back in the pool */
apr_pool_t *rebind_pool; /* frequently cleared pool for rebind data */
+ int must_rebind; /* The connection was last bound with other then binddn/bindpw */
+ request_rec *r; /* request_rec used to find this util_ldap_connection_t */
+ apr_time_t last_backend_conn; /* the approximate time of the last backend LDAP requst */
} util_ldap_connection_t;
typedef struct util_ldap_config_t {

28
SOURCES/httpd-2.4.6-r1618851.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
# ./pullrev.sh r1618851
http://svn.apache.org/viewvc?view=revision&revision=r1618851

--- httpd-2.4.6/modules/aaa/mod_authz_core.c
+++ httpd-2.4.6/modules/aaa/mod_authz_core.c
@@ -168,6 +168,13 @@
return (void*)conf;
}
+/* Only per-server directive we have is GLOBAL_ONLY */
+static void *merge_authz_core_svr_config(apr_pool_t *p,
+ void *basev, void *newv)
+{
+ return basev;
+}
+
static void *create_authz_core_svr_config(apr_pool_t *p, server_rec *s)
{
authz_core_srv_conf *authcfg;
@@ -1140,7 +1148,7 @@ AP_DECLARE_MODULE(authz_core) =
create_authz_core_dir_config, /* dir config creater */
merge_authz_core_dir_config, /* dir merger */
create_authz_core_svr_config, /* server config */
- NULL, /* merge server config */
+ merge_authz_core_svr_config , /* merge server config */
authz_cmds,
register_hooks /* register hooks */
};

21
SOURCES/httpd-2.4.6-r1621601.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
--- a/modules/proxy/mod_proxy_http.c 2014/08/31 16:06:36 1621600
+++ b/modules/proxy/mod_proxy_http.c 2014/08/31 16:07:45 1621601
@@ -1652,6 +1652,18 @@
if (!r->header_only && /* not HEAD request */
(proxy_status != HTTP_NO_CONTENT) && /* not 204 */
(proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */
+ const char *tmp;
+ /* Add minimal headers needed to allow http_in filter
+ * detecting end of body without waiting for a timeout. */
+ if ((tmp = apr_table_get(r->headers_out, "Transfer-Encoding"))) {
+ apr_table_set(backend->r->headers_in, "Transfer-Encoding", tmp);
+ }
+ else if ((tmp = apr_table_get(r->headers_out, "Content-Length"))) {
+ apr_table_set(backend->r->headers_in, "Content-Length", tmp);
+ }
+ else if (te) {
+ apr_table_set(backend->r->headers_in, "Transfer-Encoding", te);
+ }
ap_discard_request_body(backend->r);
}
return proxy_status;

21
SOURCES/httpd-2.4.6-r1624349.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
diff --git a/server/scoreboard.c b/server/scoreboard.c
index bef2b90..c8ef6a3 100644
--- a/server/scoreboard.c
+++ b/server/scoreboard.c
@@ -484,8 +484,14 @@ static int update_child_status_internal(int child_num,
ws->conn_bytes = 0;
}
if (r) {
- apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
- REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
+ const char *client = ap_get_remote_host(c, r->per_dir_config,
+ REMOTE_NOLOOKUP, NULL);
+ if (!client || !strcmp(client, c->client_ip)) {
+ apr_cpystrn(ws->client, r->useragent_ip, sizeof(ws->client));
+ }
+ else {
+ apr_cpystrn(ws->client, client, sizeof(ws->client));
+ }
copy_request(ws->request, sizeof(ws->request), r);
if (r->server) {
apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",

16
SOURCES/httpd-2.4.6-r1631119.patch

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
# ./pullrev.sh 1631119
http://svn.apache.org/viewvc?view=revision&revision=1631119

https://bugzilla.redhat.com/show_bug.cgi?id=1415257

--- httpd-2.4.6/modules/ldap/util_ldap.c
+++ httpd-2.4.6/modules/ldap/util_ldap.c
@@ -1824,7 +1824,7 @@
* combination, which might be reused unintentionally next time this
* connection is used from the connection pool.
*/
- ldc->must_rebind = 0;
+ ldc->must_rebind = 1;
ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "LDC %pp used for authn, must be rebound", ldc);
}

14
SOURCES/httpd-2.4.6-r1633085.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
--- a/modules/ssl/ssl_engine_io.c 2014/10/20 09:11:19 1633084
+++ b/modules/ssl/ssl_engine_io.c 2014/10/20 09:18:22 1633085
@@ -1322,6 +1322,11 @@
"\"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 ?

275
SOURCES/httpd-2.4.6-r1634529.patch

@ -0,0 +1,275 @@ @@ -0,0 +1,275 @@
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index 9811af8..568627f 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -276,7 +276,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
return HTTP_INTERNAL_SERVER_ERROR;
}
#ifdef HAVE_OCSP_STAPLING
- ssl_stapling_ex_init();
+ ssl_stapling_certinfo_hash_init(p);
#endif
/*
@@ -899,6 +899,8 @@ static void ssl_init_ctx(server_rec *s,
}
static int ssl_server_import_cert(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
modssl_ctx_t *mctx,
const char *id,
int idx)
@@ -933,7 +935,7 @@ static int ssl_server_import_cert(server_rec *s,
#ifdef HAVE_OCSP_STAPLING
if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) {
- if (!ssl_stapling_init_cert(s, mctx, cert)) {
+ if (!ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02235)
"Unable to configure server certificate for stapling");
}
@@ -1081,10 +1083,10 @@ static void ssl_init_server_certs(server_rec *s,
ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC);
#endif
- have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA);
- have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA);
+ have_rsa = ssl_server_import_cert(s, p, ptemp, mctx, rsa_id, SSL_AIDX_RSA);
+ have_dsa = ssl_server_import_cert(s, p, ptemp, mctx, dsa_id, SSL_AIDX_DSA);
#ifndef OPENSSL_NO_EC
- have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
+ have_ecc = ssl_server_import_cert(s, p, ptemp, mctx, ecc_id, SSL_AIDX_ECC);
#endif
if (!(have_rsa || have_dsa
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 80e1e8e..0cc6d3f 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -132,6 +132,13 @@
#if OPENSSL_VERSION_NUMBER >= 0x00908080 && !defined(OPENSSL_NO_OCSP) \
&& !defined(OPENSSL_NO_TLSEXT)
#define HAVE_OCSP_STAPLING
+/* backward compatibility with OpenSSL < 1.0 */
+#ifndef sk_OPENSSL_STRING_num
+#define sk_OPENSSL_STRING_num sk_num
+#endif
+#ifndef sk_OPENSSL_STRING_value
+#define sk_OPENSSL_STRING_value sk_value
+#endif
#if (OPENSSL_VERSION_NUMBER < 0x10000000)
#define sk_OPENSSL_STRING_pop sk_pop
#endif
@@ -862,10 +869,10 @@ const char *ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms *, void *, const char
const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *, void *, int);
const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *, void *, int);
const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *, void *, const char *);
-const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *);
+const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *);
void modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *);
-void ssl_stapling_ex_init(void);
-int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x);
+void ssl_stapling_certinfo_hash_init(apr_pool_t *);
+int ssl_stapling_init_cert(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *, X509 *);
#endif
#ifndef OPENSSL_NO_SRP
int ssl_callback_SRPServerParams(SSL *, int *, void *);
diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c
index 2be2c36..2387ae1 100644
--- a/modules/ssl/ssl_util_stapling.c
+++ b/modules/ssl/ssl_util_stapling.c
@@ -43,36 +43,32 @@
#define MAX_STAPLING_DER 10240
-/* Cached info stored in certificate ex_info. */
+/* Cached info stored in the global stapling_certinfo hash. */
typedef struct {
- /* Index in session cache SHA1 hash of certificate */
- UCHAR idx[20];
- /* Certificate ID for OCSP requests or NULL if ID cannot be determined */
+ /* Index in session cache (SHA-1 digest of DER encoded certificate) */
+ UCHAR idx[SHA_DIGEST_LENGTH];
+ /* Certificate ID for OCSP request */
OCSP_CERTID *cid;
- /* Responder details */
+ /* URI of the OCSP responder */
char *uri;
} certinfo;
-static void certinfo_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int idx, long argl, void *argp)
+static apr_status_t ssl_stapling_certid_free(void *data)
{
- certinfo *cinf = ptr;
+ OCSP_CERTID *cid = data;
- if (!cinf)
- return;
- if (cinf->uri)
- OPENSSL_free(cinf->uri);
- OPENSSL_free(cinf);
+ if (cid) {
+ OCSP_CERTID_free(cid);
+ }
+
+ return APR_SUCCESS;
}
-static int stapling_ex_idx = -1;
+static apr_hash_t *stapling_certinfo;
-void ssl_stapling_ex_init(void)
+void ssl_stapling_certinfo_hash_init(apr_pool_t *p)
{
- if (stapling_ex_idx != -1)
- return;
- stapling_ex_idx = X509_get_ex_new_index(0, "X509 cached OCSP info", 0, 0,
- certinfo_free);
+ stapling_certinfo = apr_hash_make(p);
}
static X509 *stapling_get_issuer(modssl_ctx_t *mctx, X509 *x)
@@ -106,70 +102,97 @@ static X509 *stapling_get_issuer(modssl_ctx_t *mctx, X509 *x)
}
-int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x)
+int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
+ modssl_ctx_t *mctx, X509 *x)
{
- certinfo *cinf;
+ UCHAR idx[SHA_DIGEST_LENGTH];
+ certinfo *cinf = NULL;
X509 *issuer = NULL;
+ OCSP_CERTID *cid = NULL;
STACK_OF(OPENSSL_STRING) *aia = NULL;
- if (x == NULL)
+ if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
return 0;
- cinf = X509_get_ex_data(x, stapling_ex_idx);
+
+ cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
if (cinf) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02215)
- "ssl_stapling_init_cert: certificate already initialized!");
- return 0;
- }
- cinf = OPENSSL_malloc(sizeof(certinfo));
- if (!cinf) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02216)
- "ssl_stapling_init_cert: error allocating memory!");
- return 0;
+ /*
+ * We already parsed the certificate, and no OCSP URI was found.
+ * The certificate might be used for multiple vhosts, though,
+ * so we check for a ForceURL for this vhost.
+ */
+ if (!cinf->uri && !mctx->stapling_force_url) {
+ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x,
+ APLOGNO(02814) "ssl_stapling_init_cert: no OCSP URI "
+ "in certificate and no SSLStaplingForceURL "
+ "configured for server %s", mctx->sc->vhost_id);
+ return 0;
+ }
+ return 1;
}
- cinf->cid = NULL;
- cinf->uri = NULL;
- X509_set_ex_data(x, stapling_ex_idx, cinf);
-
- issuer = stapling_get_issuer(mctx, x);
- if (issuer == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02217)
- "ssl_stapling_init_cert: Can't retrieve issuer certificate!");
+ 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;
}
- cinf->cid = OCSP_cert_to_id(NULL, x, issuer);
+ cid = OCSP_cert_to_id(NULL, x, issuer);
X509_free(issuer);
- if (!cinf->cid)
+ if (!cid) {
+ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02815)
+ "ssl_stapling_init_cert: can't create CertID "
+ "for OCSP request");
return 0;
- X509_digest(x, EVP_sha1(), cinf->idx, NULL);
+ }
aia = X509_get1_ocsp(x);
- if (aia) {
- cinf->uri = sk_OPENSSL_STRING_pop(aia);
- X509_email_free(aia);
- }
- if (!cinf->uri && !mctx->stapling_force_url) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02218)
- "ssl_stapling_init_cert: no responder URL");
+
+ if (!aia && !mctx->stapling_force_url) {
+ OCSP_CERTID_free(cid);
+ ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x,
+ APLOGNO(02218) "ssl_stapling_init_cert: no OCSP URI "
+ "in certificate and no SSLStaplingForceURL set");
return 0;
}
+
+ /* At this point, we have determined that there's something to store */
+ cinf = apr_pcalloc(p, sizeof(certinfo));
+ memcpy (cinf->idx, idx, sizeof(idx));
+ cinf->cid = cid;
+ /* make sure cid is also freed at pool cleanup */
+ apr_pool_cleanup_register(p, cid, ssl_stapling_certid_free,
+ apr_pool_cleanup_null);
+ if (aia) {
+ /* allocate uri from the pconf pool */
+ cinf->uri = apr_pstrdup(p, sk_OPENSSL_STRING_value(aia, 0));
+ X509_email_free(aia);
+ }
+
+ ssl_log_xerror(SSLLOG_MARK, APLOG_TRACE1, 0, ptemp, s, x,
+ "ssl_stapling_init_cert: storing certinfo for server %s",
+ mctx->sc->vhost_id);
+
+ apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf);
+
return 1;
}
-static certinfo *stapling_get_cert_info(server_rec *s, modssl_ctx_t *mctx,
+static certinfo *stapling_get_certinfo(server_rec *s, modssl_ctx_t *mctx,
SSL *ssl)
{
certinfo *cinf;
X509 *x;
+ UCHAR idx[SHA_DIGEST_LENGTH];
x = SSL_get_certificate(ssl);
- if (x == NULL)
+ if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
return NULL;
- cinf = X509_get_ex_data(x, stapling_ex_idx);
+ cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
if (cinf && cinf->cid)
return cinf;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01926)
- "stapling_get_cert_info: stapling not supported for certificate");
+ "stapling_get_certinfo: stapling not supported for certificate");
return NULL;
}
@@ -585,7 +608,7 @@ static int stapling_cb(SSL *ssl, void *arg)
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
"stapling_cb: OCSP Stapling callback called");
- cinf = stapling_get_cert_info(s, mctx, ssl);
+ cinf = stapling_get_certinfo(s, mctx, ssl);
if (cinf == NULL) {
return SSL_TLSEXT_ERR_NOACK;
}

132
SOURCES/httpd-2.4.6-r1650310.patch

@ -0,0 +1,132 @@ @@ -0,0 +1,132 @@
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
index ca178ab..4580f1c 100644
--- a/docs/manual/mod/mod_ssl.html.en
+++ b/docs/manual/mod/mod_ssl.html.en
@@ -57,6 +57,7 @@ to provide the cryptography engine.</p>
<li><img alt="" src="../images/down.gif" /> <a href="#sslcertificatekeyfile">SSLCertificateKeyFile</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sslciphersuite">SSLCipherSuite</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sslcompression">SSLCompression</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#sslsessiontickets">SSLSessionTickets</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sslcryptodevice">SSLCryptoDevice</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sslengine">SSLEngine</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#sslfips">SSLFIPS</a></li>
@@ -797,6 +798,26 @@ CRIME attack).</p>
</div>
</div>
+
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+<div class="directive-section"><h2><a name="SSLSessionTickets" id="SSLSessionTickets">SSLSessionTickets</a> <a name="sslsessiontickets" id="sslsessiontickets">Directive</a></h2>
+<table class="directive">
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Enable or disable use of TLS session tickets</td></tr>
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>SSLSessionTickets on|off</code></td></tr>
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>SSLCompression 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>Extension</td></tr>
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_ssl</td></tr>
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available.</td></tr>
+</table>
+<p>This directive allows to enable or disable the use of TLS session tickets(RFC 5077).</p>
+<div class="warning">
+<p>TLS session tickets are enabled by default. Using them without restarting
+the web server with an appropriate frequency (e.g. daily) compromises perfect
+forward secrecy.</p>
+</div>
+
+</div>
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="SSLCryptoDevice" id="SSLCryptoDevice">SSLCryptoDevice</a> <a name="sslcryptodevice" id="sslcryptodevice">Directive</a></h2>
<table class="directive">
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index bbe1d20..4a8b661 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -141,6 +141,9 @@ static const command_rec ssl_config_cmds[] = {
SSL_CMD_SRV(Compression, FLAG,
"Enable SSL level compression"
"(`on', `off')")
+ SSL_CMD_SRV(SessionTickets, FLAG,
+ "Enable or disable TLS session tickets"
+ "(`on', `off')")
SSL_CMD_SRV(InsecureRenegotiation, FLAG,
"Enable support for insecure renegotiation")
SSL_CMD_ALL(UserName, TAKE1,
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 9530fcc..86a7f0f 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -216,6 +216,7 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
#ifndef OPENSSL_NO_COMP
sc->compression = UNSET;
#endif
+ sc->session_tickets = UNSET;
modssl_ctx_init_proxy(sc, p);
@@ -346,6 +347,7 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
#ifndef OPENSSL_NO_COMP
cfgMergeBool(compression);
#endif
+ cfgMergeBool(session_tickets);
modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
@@ -720,6 +722,17 @@ const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag)
#endif
}
+const char *ssl_cmd_SSLSessionTickets(cmd_parms *cmd, void *dcfg, int flag)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+#ifndef SSL_OP_NO_TICKET
+ return "This version of OpenSSL does not support using "
+ "SSLSessionTickets.";
+#endif
+ sc->session_tickets = flag ? TRUE : FALSE;
+ return NULL;
+}
+
const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag)
{
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index 568627f..672760c 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -566,6 +566,16 @@ static void ssl_init_ctx_protocol(server_rec *s,
}
#endif
+#ifdef SSL_OP_NO_TICKET
+ /*
+ * Configure using RFC 5077 TLS session tickets
+ * for session resumption.
+ */
+ if (sc->session_tickets == FALSE) {
+ SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
+ }
+#endif
+
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
if (sc->insecure_reneg == TRUE) {
SSL_CTX_set_options(ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 0cc6d3f..b601316 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -701,6 +701,7 @@ struct SSLSrvConfigRec {
#ifndef OPENSSL_NO_COMP
BOOL compression;
#endif
+ BOOL session_tickets;
};
/**
@@ -756,6 +757,7 @@ const char *ssl_cmd_SSLCARevocationFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag);
const char *ssl_cmd_SSLCompression(cmd_parms *, void *, int flag);
+const char *ssl_cmd_SSLSessionTickets(cmd_parms *, void *, int flag);
const char *ssl_cmd_SSLVerifyClient(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLVerifyDepth(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLSessionCache(cmd_parms *, void *, const char *);

41
SOURCES/httpd-2.4.6-r1650655.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index c37a09b..2121892 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1733,6 +1733,9 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
memset(wshared, 0, sizeof(proxy_worker_shared));
+ if (uri.port && uri.port == ap_proxy_port_of_scheme(uri.scheme)) {
+ uri.port = 0;
+ }
ptr = apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD);
if (PROXY_STRNCPY(wshared->name, ptr) != APR_SUCCESS) {
return apr_psprintf(p, "worker name (%s) too long", ptr);
@@ -2688,6 +2691,13 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
worker->s->hostname);
break;
}
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02823)
+ "%s: connection established with Unix domain socket "
+ "%s (%s)",
+ proxy_function,
+ conn->uds_path,
+ worker->s->hostname);
}
else
#endif
@@ -2780,6 +2790,12 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
backend_addr = backend_addr->next;
continue;
}
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02824)
+ "%s: connection established with %pI (%s)",
+ proxy_function,
+ backend_addr,
+ worker->s->hostname);
}
/* Set a timeout on the socket */

49
SOURCES/httpd-2.4.6-r1650677.patch

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
--- a/modules/proxy/mod_proxy_fcgi.c 2015/01/09 21:25:26 1650676
+++ b/modules/proxy/mod_proxy_fcgi.c 2015/01/09 21:33:12 1650677
@@ -367,7 +367,7 @@
request_rec *r, int request_id)
{
apr_bucket_brigade *ib, *ob;
- int seen_end_of_headers = 0, done = 0;
+ int seen_end_of_headers = 0, done = 0, ignore_body = 0;
apr_status_t rv = APR_SUCCESS;
int script_error_status = HTTP_OK;
conn_rec *c = r->connection;
@@ -577,9 +577,16 @@
APR_BRIGADE_INSERT_TAIL(ob, tmp_b);
r->status = status;
ap_pass_brigade(r->output_filters, ob);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01070)
- "Error parsing script headers");
- rv = APR_EINVAL;
+ if (status == HTTP_NOT_MODIFIED) {
+ /* The 304 response MUST NOT contain
+ * a message-body, ignore it. */
+ ignore_body = 1;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01070)
+ "Error parsing script headers");
+ rv = APR_EINVAL;
+ }
break;
}
@@ -598,7 +605,7 @@
r->status = HTTP_OK;
}
- if (script_error_status == HTTP_OK) {
+ if (script_error_status == HTTP_OK && !ignore_body) {
rv = ap_pass_brigade(r->output_filters, ob);
if (rv != APR_SUCCESS) {
break;
@@ -626,7 +633,7 @@
* but that could be a huge amount of data; so we pass
* along smaller chunks
*/
- if (script_error_status == HTTP_OK) {
+ if (script_error_status == HTTP_OK && !ignore_body) {
rv = ap_pass_brigade(r->output_filters, ob);
if (rv != APR_SUCCESS) {
break;

10
SOURCES/httpd-2.4.6-r1651083.patch

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
--- a/server/core.c 2015/01/12 13:37:20 1651082
+++ b/server/core.c 2015/01/12 13:38:02 1651083
@@ -1271,6 +1271,7 @@
static int reset_config_defines(void *dummy)
{
ap_server_config_defines = saved_server_config_defines;
+ saved_server_config_defines = NULL;
server_config_defined_vars = NULL;
return OK;
}

100
SOURCES/httpd-2.4.6-r1651653.patch

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
diff --git a/server/util.c b/server/util.c
index e0ba5c2..a6516d4 100644
--- a/server/util.c
+++ b/server/util.c
@@ -968,20 +968,20 @@ AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
/* Read one line from open ap_configfile_t, strip LF, increase line number */
/* If custom handler does not define a getstr() function, read char by char */
static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize,
- ap_configfile_t *cfp)
+ apr_size_t offset, ap_configfile_t *cfp)
{
apr_status_t rc;
/* If a "get string" function is defined, use it */
if (cfp->getstr != NULL) {
char *cp;
- char *cbuf = buf;
- apr_size_t cbufsize = bufsize;
+ char *cbuf = buf + offset;
+ apr_size_t cbufsize = bufsize - offset;
while (1) {
++cfp->line_number;
rc = cfp->getstr(cbuf, cbufsize, cfp->param);
if (rc == APR_EOF) {
- if (cbuf != buf) {
+ if (cbuf != buf + offset) {
*cbuf = '\0';
break;
}
@@ -999,11 +999,11 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize,
*/
cp = cbuf;
cp += strlen(cp);
- if (cp > cbuf && cp[-1] == LF) {
+ if (cp > buf && cp[-1] == LF) {
cp--;
- if (cp > cbuf && cp[-1] == CR)
+ if (cp > buf && cp[-1] == CR)
cp--;
- if (cp > cbuf && cp[-1] == '\\') {
+ if (cp > buf && cp[-1] == '\\') {
cp--;
/*
* line continuation requested -
@@ -1021,19 +1021,19 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize,
}
} else {
/* No "get string" function defined; read character by character */
- apr_size_t i = 0;
+ apr_size_t i = offset;
if (bufsize < 2) {
/* too small, assume caller is crazy */
return APR_EINVAL;
}
- buf[0] = '\0';
+ buf[offset] = '\0';
while (1) {
char c;
rc = cfp->getch(&c, cfp->param);
if (rc == APR_EOF) {
- if (i > 0)
+ if (i > offset)
break;
else
return APR_EOF;
@@ -1051,11 +1051,11 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize,
break;
}
}
- else if (i >= bufsize - 2) {
- return APR_ENOSPC;
- }
buf[i] = c;
++i;
+ if (i >= bufsize - 1) {
+ return APR_ENOSPC;
+ }
}
buf[i] = '\0';
}
@@ -1089,7 +1089,7 @@ static int cfg_trim_line(char *buf)
AP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, apr_size_t bufsize,
ap_configfile_t *cfp)
{
- apr_status_t rc = ap_cfg_getline_core(buf, bufsize, cfp);
+ apr_status_t rc = ap_cfg_getline_core(buf, bufsize, 0, cfp);
if (rc == APR_SUCCESS)
cfg_trim_line(buf);
return rc;
@@ -1116,7 +1116,7 @@ AP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
}
for (;;) {
- rc = ap_cfg_getline_core(vb->buf + vb->strlen, vb->avail - vb->strlen, cfp);
+ rc = ap_cfg_getline_core(vb->buf, vb->avail, vb->strlen, cfp);
if (rc == APR_ENOSPC || rc == APR_SUCCESS)
vb->strlen += strlen(vb->buf + vb->strlen);
if (rc != APR_ENOSPC)

22
SOURCES/httpd-2.4.6-r1651658.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
--- a/modules/proxy/mod_proxy_fcgi.c 2015/01/14 13:22:50 1651657
+++ b/modules/proxy/mod_proxy_fcgi.c 2015/01/14 13:24:10 1651658
@@ -204,9 +204,19 @@
apr_status_t rv;
apr_size_t len;
int i, numenv;
+ char *proxyfilename = r->filename;
+
+ /* Strip balancer prefix */
+ if (r->filename && !strncmp(r->filename, "proxy:balancer://", 17)) {
+ char *newfname = apr_pstrdup(r->pool, r->filename+17);
+ newfname = ap_strchr(newfname, '/');
+ r->filename = newfname;
+ }
ap_add_common_vars(r);
ap_add_cgi_vars(r);
+
+ r->filename = proxyfilename;
/* XXX are there any FastCGI specific env vars we need to send? */

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save