webbuilder_pel7x64builder0
6 years ago
144 changed files with 16545 additions and 0 deletions
@ -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 |
||||||
|
|
@ -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 |
@ -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 |
||||||
|
|
@ -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 |
@ -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 |
@ -0,0 +1,2 @@ |
|||||||
|
# This file configures systemd module: |
||||||
|
LoadModule systemd_module modules/mod_systemd.so |
@ -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> |
||||||
|
|
@ -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 |
@ -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 |
@ -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 |
||||||
|
|
@ -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; |
||||||
|
} |
||||||
|
|
@ -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) |
@ -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; |
||||||
|
} |
||||||
|
|
@ -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 |
@ -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 |
@ -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 |
@ -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> |
@ -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, |
||||||
|
+}; |
@ -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 *); |
@ -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"), |
@ -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 |
@ -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. |
@ -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); |
||||||
|
|
@ -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. |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
@ -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])) |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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); |
@ -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 */ |
@ -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); |
||||||
|
|
||||||
|
|
@ -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 */ |
@ -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") |
@ -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. |
@ -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 |
@ -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"); |
||||||
|
|
@ -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"); |
||||||
|
|
@ -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); |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -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; |
||||||
|
+} |
@ -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)) { |
@ -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) { |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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++; |
@ -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)); |
||||||
|
} |
@ -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); |
@ -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); |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -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 |
||||||
|
|
@ -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\&. |
@ -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 |
@ -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 |
||||||
|
} |
@ -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; |
@ -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) |
@ -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, |
@ -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) |
@ -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 */ |
@ -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 |
@ -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 *); |
@ -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, |
@ -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) = |
@ -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; |
@ -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, |
@ -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) { |
@ -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)); |
@ -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 |
@ -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; |
@ -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 |
@ -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. */ |
@ -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; |
||||||
|
} |
@ -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 */ |
||||||
|
|
@ -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; |
||||||
|
} |
@ -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 |
||||||
|
** _________________________________________________________________ |
||||||
|
*/ |
@ -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, |
@ -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 |
@ -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 */ |
||||||
|
}; |
@ -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")))) { |
@ -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; |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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"))) { |
@ -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; |
||||||
|
} |
||||||
|
|
@ -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); |
||||||
|
|
@ -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; |
@ -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; |
@ -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, |
@ -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 { |
@ -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 */ |
||||||
|
}; |
@ -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; |
@ -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", |
@ -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); |
||||||
|
} |
||||||
|
|
@ -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 ? |
@ -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; |
||||||
|
} |
@ -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 *); |
@ -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 */ |
@ -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; |
@ -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; |
||||||
|
} |
@ -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) |
@ -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…
Reference in new issue