You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2018/09/12 13:56:21 UTC

svn commit: r1840688 [12/37] - in /httpd/sandbox/httpd-2.4.x-trunk-delta: ./ build/ build/rpm/ build/win32/ docs/ docs/conf/ docs/conf/extra/ docs/log-message-tags/ docs/man/ docs/man/tr/ include/ modules/ modules/aaa/ modules/apreq/ modules/arch/unix/...

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/config.m4
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/config.m4?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/config.m4 (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/config.m4 Wed Sep 12 13:56:17 2018
@@ -1,4 +1,6 @@
 
 APACHE_MODPATH_INIT(experimental)
 
+APACHE_MODULE(noloris, Module to mitigate Slowloris attacks, , , no)
+
 APACHE_MODPATH_FINISH

Added: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/mod_noloris.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/mod_noloris.c?rev=1840688&view=auto
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/mod_noloris.c (added)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/experimental/mod_noloris.c Wed Sep 12 13:56:17 2018
@@ -0,0 +1,235 @@
+/* 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.
+ */
+
+
+/* The use of the scoreboard in this module is based on a similar
+ * but simpler module, mod_antiloris by Kees Monshouwer, from
+ * ftp://ftp.monshouwer.eu/pub/linux/mod_antiloris/
+ * Note the FIXME that affects both modules.
+ *
+ * The major difference is that mod_antiloris checks the scoreboard
+ * on every request.  This implies a per-request overhead that grows
+ * with the scoreboard, and gets very expensive on a big server.
+ * On the other hand, this module (mod_noloris) may be slower to
+ * react to a DoS attack, and in the case of a very small server
+ * it might be too late.
+ *
+ * Author's untested instinct: mod_antiloris will suit servers with
+ * Prefork MPM and low traffic.  A server with a threaded MPM
+ * (or possibly a big prefork server with lots of memory) should
+ * raise MaxClients and use mod_noloris.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_connection.h"
+#include "http_log.h"
+#include "mpm_common.h"
+#include "ap_mpm.h"
+#include "apr_hash.h"
+#include "scoreboard.h"
+
+module AP_MODULE_DECLARE_DATA noloris_module;
+
+#define ADDR_MAX_SIZE 48
+
+static unsigned int default_max_connections;
+static apr_hash_t *trusted;
+static apr_interval_time_t recheck_time;
+static apr_shm_t *shm;
+static apr_size_t shm_size;
+static int server_limit;
+static int thread_limit;
+
+static int noloris_conn(conn_rec *conn)
+{
+    char *shm_rec;
+    if (shm == NULL) {
+        return DECLINED;  /* we're disabled */
+    }
+
+    /* check the IP is not banned */
+    shm_rec = apr_shm_baseaddr_get(shm);
+    while (shm_rec[0] != '\0') {
+        if (!strcmp(shm_rec, conn->client_ip)) {
+            apr_socket_t *csd = ap_get_conn_socket(conn);
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, APLOGNO(02059)
+                          "Dropping connection from banned IP %s",
+                          conn->client_ip);
+            apr_socket_close(csd);
+
+            return DONE;
+        }
+        shm_rec += ADDR_MAX_SIZE;
+    }
+
+    /* store this client IP for the monitor to pick up */
+
+    ap_update_child_status_from_conn(conn->sbh, SERVER_READY, conn);
+
+    return DECLINED;
+}
+static int noloris_monitor(apr_pool_t *pool, server_rec *s)
+{
+    static apr_hash_t *connections = NULL;
+    static apr_time_t last_check = 0;
+    static int *totals;
+
+    int i, j;
+    int *n;
+    int index = 0;
+    apr_hash_index_t *hi;
+    char *ip;
+    apr_time_t time_now;
+    char *shm_rec;
+    worker_score *ws;
+
+    /* do nothing if disabled */
+    if (shm == NULL) {
+        return 0;
+    }
+
+    /* skip check if it's not due yet */
+    time_now = apr_time_now();
+    if (time_now - last_check < recheck_time) {
+        return 0;
+    }
+    last_check = time_now;
+
+    /* alloc lots of stuff at start, so we don't leak memory per-call */
+    if (connections == NULL) {
+        connections = apr_hash_make(pool);
+        totals = apr_palloc(pool, server_limit*thread_limit);
+        ip = apr_palloc(pool, ADDR_MAX_SIZE);
+    }
+
+    /* Get a per-client count of connections in READ state */
+    for (i = 0; i < server_limit; ++i) {
+        for (j = 0; j < thread_limit; ++j) {
+            ws = ap_get_scoreboard_worker_from_indexes(i, j);
+            if (ws->status == SERVER_BUSY_READ) {
+                n = apr_hash_get(connections, ws->client64, APR_HASH_KEY_STRING);
+                if (n == NULL) {
+                    n = totals + index++;
+                    *n = 0;
+                }
+                ++*n;
+                apr_hash_set(connections, ws->client64, APR_HASH_KEY_STRING, n);
+            }
+        }
+    }
+
+    /* reset shm before writing to it.
+     * We're only dealing with approx. counts, so we ignore the race condition
+     * with our prospective readers
+     */
+    shm_rec = apr_shm_baseaddr_get(shm);
+    memset(shm_rec, 0, shm_size);
+
+    /* Now check the hash for clients with too many connections in READ state */
+    for (hi = apr_hash_first(NULL, connections); hi; hi = apr_hash_next(hi)) {
+        apr_hash_this(hi, (const void**) &ip, NULL, (void**)&n);
+        if (*n >= default_max_connections) {
+            /* if this isn't a trusted proxy, we mark it as bad */
+            if (!apr_hash_get(trusted, ip, APR_HASH_KEY_STRING)) {
+                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02060)
+                       "noloris: banning %s with %d connections in READ state",
+                       ip, *n);
+                strcpy(shm_rec, ip);
+                shm_rec += ADDR_MAX_SIZE;
+            }
+        }
+    }
+    apr_hash_clear(connections);
+    return 0;
+}
+static int noloris_post(apr_pool_t *pconf, apr_pool_t *ptmp, apr_pool_t *plog,
+                        server_rec *s)
+{
+    apr_status_t rv;
+    int max_bans = thread_limit * server_limit / default_max_connections;
+    shm_size = ADDR_MAX_SIZE * max_bans;
+
+    rv = apr_shm_create(&shm, shm_size, NULL, pconf);
+    if (rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(02061)
+                     "Failed to create shm segment; mod_noloris disabled");
+        apr_hash_clear(trusted);
+        shm = NULL;
+    }
+    return 0;
+}
+static int noloris_pre(apr_pool_t *pconf, apr_pool_t *ptmp, apr_pool_t *plog)
+{
+    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+    ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+
+    /* set up default config stuff here */
+    trusted = apr_hash_make(pconf);
+    default_max_connections = 50;
+    recheck_time = apr_time_from_sec(10);
+    return 0;
+}
+static void noloris_hooks(apr_pool_t *p)
+{
+    ap_hook_process_connection(noloris_conn, NULL, NULL, APR_HOOK_FIRST);
+    ap_hook_pre_config(noloris_pre, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_post_config(noloris_post, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_monitor(noloris_monitor, NULL, NULL, APR_HOOK_MIDDLE);
+}
+static const char *noloris_trusted(cmd_parms *cmd, void *cfg, const char *val)
+{
+    const char* err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (!err) {
+        apr_hash_set(trusted, val, APR_HASH_KEY_STRING, &noloris_module);
+    }
+    return err;
+}
+static const char *noloris_recheck(cmd_parms *cmd, void *cfg, const char *val)
+{
+    const char* err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (!err) {
+        recheck_time = apr_time_from_sec(atoi(val));
+    }
+    return err;
+}
+static const char *noloris_max_conn(cmd_parms *cmd, void *cfg, const char *val)
+{
+    const char* err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (!err) {
+        default_max_connections = atoi(val);
+    }
+    return err;
+}
+static const command_rec noloris_cmds[] = {
+    AP_INIT_ITERATE("TrustedProxy", noloris_trusted, NULL, RSRC_CONF,
+                    "IP addresses from which to allow unlimited connections"),
+    AP_INIT_TAKE1("ClientRecheckTime", noloris_recheck, NULL, RSRC_CONF,
+                  "Time interval for rechecking client connection tables"),
+    AP_INIT_TAKE1("MaxClientConnections", noloris_max_conn, NULL, RSRC_CONF,
+            "Max connections in READ state to permit from an untrusted client"),
+    {NULL}
+};
+AP_DECLARE_MODULE(noloris) = {
+    STANDARD20_MODULE_STUFF,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    noloris_cmds,
+    noloris_hooks
+};

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUcharsetl
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUcharsetl?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUcharsetl (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUcharsetl Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUdeflate
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUdeflate?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUdeflate (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUdeflate Wed Sep 12 13:56:17 2018
@@ -29,7 +29,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(STDMOD)/ssl \
 			$(NWOS) \
 			$(EOLIST)

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUextfiltr
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUextfiltr?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUextfiltr (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUextfiltr Wed Sep 12 13:56:17 2018
@@ -18,7 +18,7 @@ endif
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmakefile
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmakefile?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmakefile (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmakefile Wed Sep 12 13:56:17 2018
@@ -154,6 +154,7 @@ XDCDATA		=
 TARGET_nlm = \
 	$(OBJDIR)/extfiltr.nlm \
 	$(OBJDIR)/charsetl.nlm \
+        $(OBJDIR)/mod_crypto.nlm \
 	$(OBJDIR)/mod_data.nlm \
 	$(OBJDIR)/mod_filter.nlm \
 	$(OBJDIR)/mod_request.nlm \

Added: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_crypto
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_crypto?rev=1840688&view=auto
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_crypto (added)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_crypto Wed Sep 12 13:56:17 2018
@@ -0,0 +1,248 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APRUTIL)/include \
+			$(SRC)/include \
+			$(NWOS) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm.  If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME	= mod_crypto
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache $(VERSION_STR) Data Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= Filter Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).nlm \
+	$(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(OBJDIR)/$(NLM_NAME).o \
+	$(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+	$(PRELUDE) \
+	$(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+	aprlib \
+	libc \
+	$(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@aprlib.imp \
+	@httpd.imp \
+	@libc.imp \
+	$(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	crypto_module \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place.  (See $(AP_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APBUILD)/NWGNUtail.inc
+
+

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_data
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_data?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_data (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_data Wed Sep 12 13:56:17 2018
@@ -18,7 +18,7 @@ endif
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_filter
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_filter?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_filter (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_filter Wed Sep 12 13:56:17 2018
@@ -18,7 +18,7 @@ endif
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_request
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_request?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_request (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmod_request Wed Sep 12 13:56:17 2018
@@ -18,7 +18,7 @@ endif
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodbuffer
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodbuffer?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodbuffer (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodbuffer Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodsed
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodsed?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodsed (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUmodsed Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUproxyhtml
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUproxyhtml?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUproxyhtml (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUproxyhtml Wed Sep 12 13:56:17 2018
@@ -19,8 +19,8 @@ XINCDIRS	+= \
 			$(LIBXML2SDK)/include \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
-			$(AP_WORK)/modules/http \
+			$(SRC)/include \
+			$(STDMOD)/http \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUratelimit
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUratelimit?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUratelimit (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUratelimit Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreflector
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreflector?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreflector (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreflector Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreqtimeout
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreqtimeout?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreqtimeout (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUreqtimeout Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUsubstitute
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUsubstitute?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUsubstitute (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUsubstitute Wed Sep 12 13:56:17 2018
@@ -26,7 +26,7 @@ include $(AP_WORK)/build/NWGNUhead.inc
 XINCDIRS	+= \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUxml2enc
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUxml2enc?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUxml2enc (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/NWGNUxml2enc Wed Sep 12 13:56:17 2018
@@ -27,7 +27,7 @@ XINCDIRS	+= \
 			$(LIBXML2SDK)/include \
 			$(APR)/include \
 			$(APRUTIL)/include \
-			$(AP_WORK)/include \
+			$(SRC)/include \
 			$(NWOS) \
 			$(EOLIST)
 

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/config.m4
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/config.m4?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/config.m4 (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/config.m4 Wed Sep 12 13:56:17 2018
@@ -192,6 +192,25 @@ if (o) return *o;],
   fi
 ])
 
+APACHE_MODULE(crypto, Symmetrical encryption / decryption, , , no, [
+  dnl Check for the required APR-util version.
+  AC_MSG_CHECKING([for APR-util >= 1.6])
+  if test "$apr_major_version" -lt 2; then
+    case "$APU_VERSION" in
+    dnl Sorry for the quadrigraphs; this expands to "1.[0-5].*)"
+    1.@<:@0-5@:>@.*)
+      AC_MSG_RESULT(no)
+      enable_crypto=no
+      ;;
+    *)
+      AC_MSG_RESULT(yes)
+      ;;
+    esac
+  else
+    AC_MSG_RESULT([yes (APR 2)])
+  fi
+])
+
 APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
 
 APACHE_MODPATH_FINISH

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_brotli.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_brotli.dsp?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_brotli.dsp (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_brotli.dsp Wed Sep 12 13:56:17 2018
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so
-# ADD LINK32 kernel32.lib brotlicommon.lib brotlienc.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so /opt:ref
+# ADD LINK32 kernel32.lib brotlicommon-static.lib brotlienc-static.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so /opt:ref
 # Begin Special Build Tool
 TargetPath=.\Release\mod_brotli.so
 SOURCE="$(InputPath)"
@@ -85,7 +85,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so
-# ADD LINK32 kernel32.lib brotlicommon.lib brotlienc.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so
+# ADD LINK32 kernel32.lib brotlicommon-static.lib brotlienc-static.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_brotli.so" /libpath:"../../srclib/brotli" /base:@..\..\os\win32\BaseAddr.ref,mod_brotli.so
 # Begin Special Build Tool
 TargetPath=.\Debug\mod_brotli.so
 SOURCE="$(InputPath)"

Modified: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_charset_lite.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_charset_lite.c?rev=1840688&r1=1840687&r2=1840688&view=diff
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_charset_lite.c (original)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_charset_lite.c Wed Sep 12 13:56:17 2018
@@ -790,7 +790,7 @@ static apr_status_t xlate_out_filter(ap_
     if (!ctx->noop && ctx->xlate == NULL) {
         const char *mime_type = f->r->content_type;
 
-        if (mime_type && (strncasecmp(mime_type, "text/", 5) == 0 ||
+        if (mime_type && (ap_cstr_casecmpn(mime_type, "text/", 5) == 0 ||
 #if APR_CHARSET_EBCDIC
         /* On an EBCDIC machine, be willing to translate mod_autoindex-
          * generated output.  Otherwise, it doesn't look too cool.
@@ -806,7 +806,7 @@ static apr_status_t xlate_out_filter(ap_
          */
             strcmp(mime_type, DIR_MAGIC_TYPE) == 0 ||
 #endif
-            strncasecmp(mime_type, "message/", 8) == 0 ||
+            ap_cstr_casecmpn(mime_type, "message/", 8) == 0 ||
             dc->force_xlate == FX_FORCE)) {
 
             rv = apr_xlate_open(&ctx->xlate,
@@ -1123,10 +1123,17 @@ static void charset_register_hooks(apr_p
 {
     ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_REALLY_LAST);
+#if APR_CHARSET_EBCDIC
+    ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL,
+                              AP_FTYPE_RESOURCE+1);
+    ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL,
+                             AP_FTYPE_RESOURCE+1);
+#else
     ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL,
                               AP_FTYPE_RESOURCE);
     ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL,
                              AP_FTYPE_RESOURCE);
+#endif
 }
 
 AP_DECLARE_MODULE(charset_lite) =

Added: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.c?rev=1840688&view=auto
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.c (added)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.c Wed Sep 12 13:56:17 2018
@@ -0,0 +1,1314 @@
+/* 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_crypto.c --- Encrypt / decrypt data in the input and output filter
+ *                  stacks.
+ */
+
+#include "apr_version.h"
+#if !APR_VERSION_AT_LEAST(2,0,0)
+#include "apu_version.h"
+#endif
+
+#if !APR_VERSION_AT_LEAST(2,0,0) && \
+    !(APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 6)
+#error This module requires at least v1.6.0 of apr-util.
+#else
+
+#include "mod_crypto.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_crypto.h"
+#include "apr_base64.h"
+#include "apr_escape.h"
+#include "util_filter.h"
+#include "http_log.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "ap_expr.h"
+
+APR_HOOK_STRUCT(APR_HOOK_LINK(crypto_key)
+                APR_HOOK_LINK(crypto_iv))
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ap, CRYPTO, apr_status_t, crypto_key,
+                                      (request_rec *r,
+                                      apr_crypto_block_key_type_t * cipher,
+                                      apr_crypto_block_key_mode_t * mode,
+                                      int pad,
+                                      const apr_crypto_key_rec_t ** rec),
+                                      (r, cipher, mode, pad, rec), DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ap, CRYPTO, apr_status_t, crypto_iv,
+                                      (request_rec *r,
+                                      apr_crypto_block_key_type_t * cipher,
+                                      const unsigned char **iv), (r, cipher,
+                                      iv), DECLINED)
+module AP_MODULE_DECLARE_DATA crypto_module;
+
+#define DEFAULT_BUFFER_SIZE 128*1024
+#define DEFAULT_CIPHER "aes256"
+#define DEFAULT_MODE "cbc"
+#define CRYPTO_KEY "crypto_context"
+
+typedef struct pass_conf
+{
+    const char *scheme;
+    const ap_expr_info_t *expr;
+    unsigned char *raw;
+    apr_size_t size;
+} pass_conf;
+
+/**
+ * Structure to carry the server wide session config.
+ */
+typedef struct
+{
+    const char *library;
+    const char *params;
+    apr_crypto_t **crypto;
+    int library_set;
+} crypto_conf;
+
+typedef struct crypto_dir_conf
+{
+    apr_off_t size;        /* size of the buffer */
+    int size_set;          /* has the size been set */
+    const char *cipher;
+    const char *mode;
+    int cipher_set;
+    pass_conf *key;
+    int key_set;
+    pass_conf *iv;
+    int iv_set;
+} crypto_dir_conf;
+
+typedef struct crypto_ctx
+{
+    apr_bucket_brigade *bb;
+    apr_bucket_brigade *tmp;
+    crypto_dir_conf *conf;
+    unsigned char *out;
+    apr_crypto_key_t *key;
+    apr_crypto_block_key_type_t *cipher;
+    apr_crypto_block_key_mode_t *mode;
+    apr_crypto_block_t *block;
+    const unsigned char *iv;
+    apr_off_t remaining;
+    apr_off_t written;
+    apr_size_t osize;
+    int seen_eos:1;
+    int encrypt:1;
+    int clength:1;
+} crypto_ctx;
+
+static const char *parse_pass_conf_binary(cmd_parms *cmd,
+                                          pass_conf * pass,
+                                          const char *arg)
+{
+    apr_status_t rv;
+    char ps = *arg;
+
+    if ('f' == ps && !strncmp(arg, "file:", 5)) {
+        const char *name;
+
+        arg += 5;
+        if (!*arg) {
+            return apr_pstrcat(cmd->pool, "No filename specified", NULL);
+        }
+
+        name = ap_server_root_relative(cmd->temp_pool, arg);
+        if (name) {
+            apr_file_t *file;
+
+            rv = apr_file_open(&file, name, APR_FOPEN_READ,
+                               APR_FPROT_OS_DEFAULT, cmd->temp_pool);
+            if (APR_SUCCESS == rv) {
+                apr_finfo_t finfo;
+
+                rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file);
+                if (rv == APR_SUCCESS) {
+                    apr_size_t size;
+
+                    pass->scheme = "file";
+                    pass->raw = apr_palloc(cmd->pool, finfo.size);
+                    pass->size = finfo.size;
+                    apr_crypto_clear(cmd->pool, pass->raw, pass->size);
+
+                    rv = apr_file_read_full(file, pass->raw, pass->size,
+                                            &size);
+                    if (APR_SUCCESS == rv && size != pass->size) {
+                        rv = APR_EGENERAL;
+                    }
+
+                }
+            }
+            if (APR_SUCCESS != rv) {
+                char buf[120];
+                return apr_pstrcat(cmd->pool, "Unable to load from file '",
+                                   arg, "': ", apr_strerror(rv, buf,
+                                                            sizeof(buf)),
+                                   NULL);
+            }
+        }
+        else {
+            return apr_pstrcat(cmd->pool, "Unable to locate file from name ",
+                               arg, NULL);
+        }
+    }
+
+    else if ('h' == ps && (!strncmp(arg, "hex:", 4))) {
+        const char *expr_err = NULL;
+        arg += 4;
+
+        if (!*arg) {
+            return apr_pstrcat(cmd->temp_pool,
+                               "Cannot parse expression, it is blank", NULL);
+        }
+
+        pass->scheme = "hex";
+        pass->expr = ap_expr_parse_cmd(cmd, arg, AP_EXPR_FLAG_STRING_RESULT,
+                                       &expr_err, NULL);
+
+        if (expr_err) {
+            return apr_pstrcat(cmd->temp_pool, "Cannot parse ", pass->scheme,
+                               " expression '", arg, "' in: ", expr_err,
+                               NULL);
+        }
+
+    }
+
+    else if ('b' == ps && !strncmp(arg, "base64:", 7)) {
+        const char *expr_err = NULL;
+        arg += 7;
+
+        if (!*arg) {
+            return apr_pstrcat(cmd->temp_pool,
+                               "Cannot parse expression, it is blank", NULL);
+        }
+
+        pass->scheme = "base64";
+        pass->expr = ap_expr_parse_cmd(cmd, arg, AP_EXPR_FLAG_STRING_RESULT,
+                                       &expr_err, NULL);
+
+        if (expr_err) {
+            return apr_pstrcat(cmd->temp_pool, "Cannot parse ", pass->scheme,
+                               " expression '", arg, "' in: ", expr_err,
+                               NULL);
+        }
+
+    }
+
+    else if ('d' == ps && !strncmp(arg, "decimal:", 8)) {
+        const char *expr_err = NULL;
+        arg += 8;
+
+        if (!*arg) {
+            return apr_pstrcat(cmd->temp_pool,
+                               "Cannot parse expression, it is blank", NULL);
+        }
+
+        pass->scheme = "decimal";
+        pass->expr = ap_expr_parse_cmd(cmd, arg, AP_EXPR_FLAG_STRING_RESULT,
+                                       &expr_err, NULL);
+
+        if (expr_err) {
+            return apr_pstrcat(cmd->temp_pool, "Cannot parse ", pass->scheme,
+                               " expression '", arg, "' in: ", expr_err,
+                               NULL);
+        }
+
+    }
+
+    else if ('n' == ps && !strcmp(arg, "none")) {
+        pass->scheme = arg;
+    }
+
+    else {
+        return apr_pstrcat(cmd->pool,
+                           "Scheme must be 'file:', 'hex:', 'base64:', 'decimal:' or 'none': ",
+                           arg, NULL);
+    }
+
+    return NULL;
+}
+
+static apr_status_t
+exec_pass_conf_binary(request_rec *r, pass_conf * pass,
+                      const char *description, apr_size_t size,
+                      const unsigned char **k)
+{
+
+    if (pass) {
+
+        if (pass->raw) {
+            *k = pass->raw;
+
+            if (size != pass->size) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
+                              APLOGNO(03409) "%s has wrong size (was %"
+                              APR_SIZE_T_FMT ", must be %" APR_SIZE_T_FMT ")",
+                              description, pass->size, size);
+                return APR_EGENERAL;
+            }
+
+            return APR_SUCCESS;
+        }
+
+        else if (pass->expr) {
+            char ps = *pass->scheme;
+            const char *err = NULL;
+
+            const char *arg = ap_expr_str_exec(r, pass->expr, &err);
+            if (err) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
+                              APLOGNO(03410) "%s could not be parsed: %s",
+                              description, err);
+                return APR_EGENERAL;
+            }
+
+            /* hex */
+            if ('h' == ps) {
+                apr_size_t len;
+                unsigned char *b;
+
+                apr_unescape_hex(NULL, arg, strlen(arg), 1, &len);
+                if (len < size) {
+                    b = apr_palloc(r->pool, size);
+                    memset(b, 0, size - len);
+                    apr_unescape_hex(b + size - len, arg, strlen(arg), 1,
+                                     &len);
+                }
+                else {
+                    b = apr_palloc(r->pool, len);
+                    apr_unescape_hex(b, arg, strlen(arg), 1, NULL);
+                    b += len - size;
+                }
+                *k = b;
+
+            }
+
+            /* base64 */
+            else if ('b' == ps) {
+                apr_size_t len;
+                unsigned char *b;
+
+                len = apr_base64_decode_len(arg);
+                if (len < size) {
+                    b = apr_palloc(r->pool, size);
+                    memset(b, 0, size - len);
+                    apr_base64_decode_binary(b + size - len, arg);
+                }
+                else {
+                    b = apr_palloc(r->pool, len);
+                    apr_base64_decode_binary(b, arg);
+                    b += len - size;
+                }
+                *k = b;
+
+            }
+
+            /* decimal */
+            else if ('d' == ps) {
+                apr_size_t len;
+                unsigned char *b;
+                char n[8];
+                apr_uint64_t t;
+                int i;
+
+                t = (apr_uint64_t) apr_atoi64(arg);
+
+                for (i = 7; i >= 0; i--) {
+                    n[i] = t & 0xFF;
+                    t = t >> 8;
+                }
+
+                len = sizeof(n);
+                if (len < size) {
+                    b = apr_palloc(r->pool, size);
+                    memset(b, 0, size - len);
+                    memcpy(b + size - len, n, len);
+                }
+                else {
+                    b = apr_palloc(r->pool, len);
+                    memcpy(b, n, len);
+                    b += len - size;
+                }
+                *k = b;
+
+            }
+
+        }
+
+    }
+
+    return DECLINED;
+}
+
+static apr_status_t
+init_cipher(request_rec *r,
+            apr_crypto_block_key_type_t ** cipher,
+            apr_crypto_block_key_mode_t ** mode)
+{
+    apr_status_t rv;
+    apr_hash_t *ciphers;
+    apr_hash_t *modes;
+
+    crypto_conf *conf = ap_get_module_config(r->server->module_config,
+                                             &crypto_module);
+    crypto_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+                                                  &crypto_module);
+
+    if (cipher) {
+
+        rv = apr_crypto_get_block_key_types(&ciphers, *conf->crypto);
+        if (APR_SUCCESS != rv) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03411) "no ciphers returned by APR");
+            return rv;
+        }
+
+        *cipher = apr_hash_get(ciphers, dconf->cipher, APR_HASH_KEY_STRING);
+        if (!*cipher) {
+            apr_hash_index_t *hi;
+            const void *key;
+            apr_ssize_t klen;
+            int sum = 0;
+            int offset = 0;
+            char *options = NULL;
+
+            for (hi = apr_hash_first(r->pool, ciphers); hi;
+                 hi = apr_hash_next(hi)) {
+                apr_hash_this(hi, NULL, &klen, NULL);
+                sum += klen + 2;
+            }
+            for (hi = apr_hash_first(r->pool, ciphers); hi;
+                 hi = apr_hash_next(hi)) {
+                apr_hash_this(hi, &key, &klen, NULL);
+                if (!options) {
+                    options = apr_palloc(r->pool, sum + 1);
+                }
+                else {
+                    options[offset++] = ',';
+                    options[offset++] = ' ';
+                }
+                strncpy(options + offset, key, klen);
+                offset += klen;
+            }
+            options[offset] = 0;
+
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03428) "cipher '%s' not recognised by crypto driver. "
+                          "Options: %s", dconf->cipher, options);
+
+            return rv;
+        }
+
+    }
+
+    if (mode) {
+
+        rv = apr_crypto_get_block_key_modes(&modes, *conf->crypto);
+        if (APR_SUCCESS != rv) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03412) "no cipher modes returned by APR");
+            return rv;
+        }
+
+        *mode = apr_hash_get(modes, dconf->mode, APR_HASH_KEY_STRING);
+        if (!*mode) {
+            apr_hash_index_t *hi;
+            const void *key;
+            apr_ssize_t klen;
+            int sum = 0;
+            int offset = 0;
+            char *options = NULL;
+
+            for (hi = apr_hash_first(r->pool, modes); hi;
+                 hi = apr_hash_next(hi)) {
+                apr_hash_this(hi, NULL, &klen, NULL);
+                sum += klen + 2;
+            }
+            for (hi = apr_hash_first(r->pool, modes); hi;
+                 hi = apr_hash_next(hi)) {
+                apr_hash_this(hi, &key, &klen, NULL);
+                if (!options) {
+                    options = apr_palloc(r->pool, sum + 1);
+                }
+                else {
+                    options[offset++] = ',';
+                    options[offset++] = ' ';
+                }
+                strncpy(options + offset, key, klen);
+                offset += klen;
+            }
+            options[offset] = 0;
+
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03429) "cipher mode '%s' not recognised by crypto driver. "
+                          "Options: %s", dconf->mode, options);
+
+            return rv;
+        }
+
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t init_crypt(ap_filter_t * f)
+{
+    apr_status_t rv;
+    crypto_ctx *ctx = f->ctx;
+    const apr_crypto_key_rec_t *rec;
+
+    crypto_conf *conf = ap_get_module_config(f->r->server->module_config,
+                                             &crypto_module);
+    crypto_dir_conf *dconf =
+        ap_get_module_config(f->r->per_dir_config, &crypto_module);
+
+    /* sanity check - has crypto been switched on? */
+    if (!conf->crypto || !*conf->crypto) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, f->r,
+                      APLOGNO(03430) "crypto driver has not been enabled for this server");
+        return APR_EGENERAL;
+    }
+
+    /* initial setup of the context */
+    ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+    ctx->conf = dconf;
+    ctx->remaining = ctx->conf->size;
+    ctx->written = 0;
+    ctx->osize = ctx->conf->size;
+
+    /* fetch the cipher for this location */
+    rv = init_cipher(f->r, &ctx->cipher, &ctx->mode);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    /* sanity check - buffer size multiple of block size? */
+    if (ctx->conf->size % ctx->cipher->blocksize) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, f->r,
+                      APLOGNO(03413) "Buffer size %" APR_OFF_T_FMT
+                      " is not a multiple of the block size %d of cipher '%s'",
+                      ctx->conf->size, ctx->cipher->blocksize, dconf->cipher);
+        return APR_EGENERAL;
+    }
+
+    /* fetch the key we'll be using for decryption */
+    rv = ap_run_crypto_key(f->r, ctx->cipher, ctx->mode, 1, &rec);
+    if (DECLINED == rv) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
+                      APLOGNO(03414) "no key specified for this URL");
+        return APR_ENOKEY;
+    }
+    if (APR_SUCCESS != rv || !rec) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03415) "key could not be retrieved");
+        return APR_ENOKEY;
+    }
+    if (rec->ktype != APR_CRYPTO_KTYPE_SECRET) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03416) "key is not a symmetrical key");
+        return APR_ENOKEY;
+    }
+
+    /* attempt to import the key */
+    rv = apr_crypto_key(&ctx->key, rec, *conf->crypto, f->r->pool);
+    if (APR_STATUS_IS_ENOKEY(rv)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03417) "key could not be loaded");
+    }
+    if (APR_STATUS_IS_EPADDING(rv)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03418) "padding is not supported for cipher");
+    }
+    if (APR_STATUS_IS_EKEYTYPE(rv)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03419) "the key type is not known");
+    }
+    if (APR_SUCCESS != rv) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03420) "encryption could not be configured.");
+        return rv;
+    }
+
+    /* fetch the optional iv */
+    rv = ap_run_crypto_iv(f->r, ctx->cipher, &ctx->iv);
+    if (DECLINED != rv && APR_SUCCESS != rv) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                      APLOGNO(03431) "initialisation vector could not be retrieved");
+        return rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+static int init_encrypt(ap_filter_t * f)
+{
+    apr_status_t rv;
+    crypto_ctx *ctx;
+
+    ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
+    ctx->encrypt = 1;
+
+    rv = init_crypt(f);
+    if (APR_SUCCESS != rv) {
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    return OK;
+}
+
+static int init_decrypt(ap_filter_t * f)
+{
+    apr_status_t rv;
+    crypto_ctx *ctx;
+
+    ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
+    ctx->encrypt = 0;
+
+    rv = init_crypt(f);
+    if (APR_SUCCESS != rv) {
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    return OK;
+}
+
+/**
+ * Run the crypto algorithm, write to ctx->out
+ */
+static apr_status_t
+do_crypto(ap_filter_t * f, unsigned char *in, apr_off_t size, int finish)
+{
+    apr_status_t rv;
+    crypto_ctx *ctx = f->ctx;
+    apr_off_t extra = 0;
+    apr_size_t blockSize = 0;
+    int need_iv = (ctx->iv == NULL);
+    unsigned char *out;
+    apr_size_t written;
+
+    /* encrypt the given buffer */
+    if (ctx->encrypt) {
+
+        if (!ctx->block) {
+            rv = apr_crypto_block_encrypt_init(&ctx->block, &ctx->iv,
+                                               ctx->key, &blockSize,
+                                               f->r->pool);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03421) "could not initialise encryption");
+                return rv;
+            }
+        }
+
+        if (!ctx->out) {
+
+            if (need_iv && ctx->iv) {
+                ctx->osize += blockSize;
+            }
+
+            out = ctx->out = apr_palloc(f->r->pool,
+                                        ctx->osize + ctx->cipher->blocksize);
+            apr_crypto_clear(f->r->pool, ctx->out,
+                             ctx->osize + ctx->cipher->blocksize);
+
+            /* no precomputed iv? write the generated iv as the first block of the stream */
+            if (need_iv && ctx->iv) {
+                memcpy(out, ctx->iv, blockSize);
+                ctx->remaining += blockSize;
+                out += blockSize;
+                extra = blockSize;
+            }
+
+        }
+        else {
+            out = ctx->out + (ctx->osize - ctx->remaining);
+        }
+
+        if (!finish) {
+            rv = apr_crypto_block_encrypt(&out, &written, in, size,
+                                          ctx->block);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03422) "crypto: attempt to encrypt failed");
+                return rv;
+            }
+        }
+
+        else {
+            rv = apr_crypto_block_encrypt_finish(out, &written, ctx->block);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03432) "crypto: attempt to finish encrypt failed");
+                return rv;
+            }
+        }
+    }
+
+    /* decrypt the given buffer */
+    else {
+
+        if (!ctx->out) {
+            out = ctx->out = apr_palloc(f->r->pool,
+                                        ctx->osize + ctx->cipher->blocksize);
+            apr_crypto_clear(f->r->pool, ctx->out,
+                             ctx->osize + ctx->cipher->blocksize);
+        }
+        else {
+            out = ctx->out + (ctx->osize - ctx->remaining);
+        }
+
+        /* no precomputed iv? assume the first block in the stream is the iv */
+        if (need_iv) {
+            apr_off_t isize =
+                ctx->cipher->blocksize - (ctx->osize - ctx->remaining);
+            if (size < isize) {
+                memcpy(out, in, size);
+                ctx->remaining -= size;
+                return APR_SUCCESS;
+            }
+            else {
+                memcpy(out, in, isize);
+                ctx->remaining -= isize;
+                out += isize;
+                ctx->iv = ctx->out;
+            }
+        }
+
+        if (!ctx->block) {
+            rv = apr_crypto_block_decrypt_init(&ctx->block, &blockSize,
+                                               ctx->iv, ctx->key, f->r->pool);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03423) "could not initialise decryption");
+                return rv;
+            }
+        }
+
+        if (!finish) {
+            rv = apr_crypto_block_decrypt(&out, &written, in, size,
+                                          ctx->block);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03433) "crypto: attempt to decrypt failed (key/iv incorrect?)");
+                return rv;
+            }
+        }
+        else {
+            rv = apr_crypto_block_decrypt_finish(out, &written, ctx->block);
+            if (APR_SUCCESS != rv) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+                              APLOGNO(03434) "crypto: attempt to finish decrypt failed (key/iv incorrect?)");
+                return rv;
+            }
+        }
+    }
+
+    ctx->remaining -= written;
+    ctx->written += written;
+    ctx->written += extra;
+
+    return rv;
+}
+
+/**
+ * Encrypt/decrypt buckets being written to the output filter stack.
+ */
+static apr_status_t
+crypto_out_filter(ap_filter_t * f, apr_bucket_brigade * bb)
+{
+    apr_bucket *e, *after;
+    crypto_ctx *ctx = f->ctx;
+    apr_status_t rv = APR_SUCCESS;
+
+    /* Do nothing if asked to filter nothing. */
+    if (APR_BRIGADE_EMPTY(bb)) {
+        return ap_pass_brigade(f->next, bb);
+    }
+
+    /* clear the content length */
+    if (!ctx->clength) {
+        ctx->clength = 1;
+        apr_table_unset(f->r->headers_out, "Content-Length");
+    }
+
+    /* make sure we fit in the buffer snugly */
+    if (APR_BRIGADE_EMPTY(ctx->bb)) {
+        apr_brigade_partition(bb, ctx->remaining, &after);
+    }
+
+    while (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(bb)) {
+        const char *data;
+        apr_size_t size;
+
+        e = APR_BRIGADE_FIRST(bb);
+
+        /* EOS means we are done. */
+        if (APR_BUCKET_IS_EOS(e)) {
+
+            /* handle any leftovers */
+            do_crypto(f, NULL, 0, 1);
+            apr_brigade_write(ctx->bb, NULL, NULL, (const char *) ctx->out,
+                              ctx->conf->size - ctx->remaining);
+            ctx->remaining = ctx->osize;
+            ctx->written = 0;
+            apr_brigade_partition(bb, ctx->remaining, &after);
+
+            /* pass the EOS across */
+            APR_BUCKET_REMOVE(e);
+            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+
+            /* pass what we have down the chain */
+            rv = ap_pass_brigade(f->next, ctx->bb);
+
+            ap_remove_output_filter(f);
+            continue;
+        }
+
+        /* handle flush */
+        if (APR_BUCKET_IS_FLUSH(e)) {
+
+            /* we cannot change the laws of physics: crypto can only happen
+             * on a block boundary. As a result, just pass the flush bucket
+             * through as is, we'll send the rest of the block when it
+             * arrives in full.
+             */
+
+            /* pass the flush bucket across */
+            APR_BUCKET_REMOVE(e);
+            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+
+            /* pass what we have down the chain */
+            rv = ap_pass_brigade(f->next, ctx->bb);
+            continue;
+        }
+
+        /* metadata buckets are preserved as is */
+        if (APR_BUCKET_IS_METADATA(e)) {
+            /*
+             * Remove meta data bucket from old brigade and insert into the
+             * new.
+             */
+            APR_BUCKET_REMOVE(e);
+            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+            continue;
+        }
+
+        if (APR_SUCCESS
+            == (rv = apr_bucket_read(e, &data, &size, APR_BLOCK_READ))) {
+
+            do_crypto(f, (unsigned char *) data, size, 0);
+            apr_bucket_delete(e);
+
+            if (!ctx->remaining) {
+                apr_brigade_write(ctx->bb, NULL, NULL,
+                                  (const char *) ctx->out, ctx->written);
+                ctx->remaining = ctx->osize;
+                ctx->written = 0;
+                apr_brigade_partition(bb, ctx->remaining, &after);
+                rv = ap_pass_brigade(f->next, ctx->bb);
+            }
+
+        }
+
+    }
+
+    return rv;
+
+}
+
+/**
+ * Decrypt/encrypt buckets being read from the input filter stack.
+ */
+static apr_status_t
+crypto_in_filter(ap_filter_t * f, apr_bucket_brigade * bb,
+                 ap_input_mode_t mode, apr_read_type_e block,
+                 apr_off_t readbytes)
+{
+    apr_bucket *e, *after;
+    apr_status_t rv = APR_SUCCESS;
+    crypto_ctx *ctx = f->ctx;
+
+    if (!ctx->tmp) {
+        ctx->tmp = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+    }
+
+    /* just get out of the way of things we don't want. */
+    if (mode != AP_MODE_READBYTES) {
+        return ap_get_brigade(f->next, bb, mode, block, readbytes);
+    }
+
+    /* if our buffer is empty, read off the network until the buffer is full */
+    if (APR_BRIGADE_EMPTY(ctx->bb)) {
+        ctx->remaining = ctx->osize;
+        ctx->written = 0;
+
+        while (!ctx->seen_eos && ctx->remaining > 0) {
+            const char *data;
+            apr_size_t size = 0;
+
+            if (APR_BRIGADE_EMPTY(ctx->tmp)) {
+                rv = ap_get_brigade(f->next, ctx->tmp, mode, block,
+                                    ctx->remaining);
+            }
+
+            /* if an error was received, bail out now. If the error is
+             * EAGAIN and we have not yet seen an EOS, we will definitely
+             * be called again, at which point we will send our buffered
+             * data. Instead of sending EAGAIN, some filters return an
+             * empty brigade instead when data is not yet available. In
+             * this case, we drop through and pass buffered data, if any.
+             */
+            if (APR_STATUS_IS_EAGAIN(rv)
+                || (rv == APR_SUCCESS
+                    && block == APR_NONBLOCK_READ
+                    && APR_BRIGADE_EMPTY(ctx->tmp))) {
+                if (APR_BRIGADE_EMPTY(ctx->bb)) {
+                    return rv;
+                }
+                break;
+            }
+            if (APR_SUCCESS != rv) {
+                return rv;
+            }
+
+            while (!APR_BRIGADE_EMPTY(ctx->tmp)) {
+                e = APR_BRIGADE_FIRST(ctx->tmp);
+
+                /* if we see an EOS, we are done */
+                if (APR_BUCKET_IS_EOS(e)) {
+
+                    /* handle any leftovers */
+                    do_crypto(f, NULL, 0, 1);
+                    apr_brigade_write(ctx->bb, NULL, NULL,
+                                      (const char *) ctx->out, ctx->written);
+
+                    APR_BUCKET_REMOVE(e);
+                    APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+                    ctx->seen_eos = 1;
+                    break;
+                }
+
+                /* flush buckets clear the buffer */
+                if (APR_BUCKET_IS_FLUSH(e)) {
+                    APR_BUCKET_REMOVE(e);
+                    APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+                    break;
+                }
+
+                /* pass metadata buckets through */
+                if (APR_BUCKET_IS_METADATA(e)) {
+                    APR_BUCKET_REMOVE(e);
+                    APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+                    continue;
+                }
+
+                /* read the bucket in, pack it into the buffer */
+                rv = apr_bucket_read(e, &data, &size, block);
+                if (APR_STATUS_IS_EAGAIN(rv)) {
+                    if (APR_BRIGADE_EMPTY(ctx->bb)) {
+                        return rv;
+                    }
+                    break;
+                }
+                if (APR_SUCCESS != rv) {
+                    return rv;
+                }
+
+                do_crypto(f, (unsigned char *) data, size, 0);
+                if (!ctx->remaining || APR_STATUS_IS_EAGAIN(rv)) {
+                    apr_brigade_write(ctx->bb, NULL, NULL,
+                                      (const char *) ctx->out, ctx->written);
+                }
+
+                apr_bucket_delete(e);
+
+            }
+        }
+    }
+
+    /* give the caller the data they asked for from the buffer */
+    apr_brigade_partition(ctx->bb, readbytes, &after);
+    e = APR_BRIGADE_FIRST(ctx->bb);
+    while (e != after) {
+        if (APR_BUCKET_IS_EOS(e)) {
+            /* last bucket read, step out of the way */
+            ap_remove_input_filter(f);
+        }
+        APR_BUCKET_REMOVE(e);
+        APR_BRIGADE_INSERT_TAIL(bb, e);
+        e = APR_BRIGADE_FIRST(ctx->bb);
+    }
+
+    /* clear the content length */
+    if (!ctx->clength) {
+        ctx->clength = 1;
+        apr_table_unset(f->r->headers_in, "Content-Length");
+    }
+
+    return APR_SUCCESS;
+}
+
+static int crypto_handler(request_rec *r)
+{
+    crypto_conf *conf;
+    crypto_dir_conf *dconf;
+    apr_status_t rv;
+
+    if (*r->handler != 'c' || strcmp(r->handler, "crypto-key")) {
+        return DECLINED;
+    }
+
+    conf = ap_get_module_config(r->server->module_config, &crypto_module);
+    dconf = ap_get_module_config(r->per_dir_config, &crypto_module);
+
+    /* sanity check - has crypto been switched on? */
+    if (!conf->crypto || !*conf->crypto) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
+                      APLOGNO(03435) "crypto driver has not been enabled for this server");
+        return APR_EGENERAL;
+    }
+
+    if (dconf->key_set) {
+        const apr_crypto_key_rec_t *rec;
+        apr_crypto_block_key_type_t *cipher;
+        apr_crypto_block_key_mode_t *mode;
+
+        /* fetch the cipher for this location */
+        rv = init_cipher(r, &cipher, &mode);
+        if (APR_SUCCESS != rv) {
+            return HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        /* fetch the key we'll be using for encryption / decryption */
+        rv = ap_run_crypto_key(r, cipher, mode, 1, &rec);
+        if (DECLINED == rv) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          APLOGNO(03424) "no key specified for this URL");
+            return HTTP_INTERNAL_SERVER_ERROR;
+        }
+        if (APR_SUCCESS != rv || !rec) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03425) "key could not be retrieved");
+            return HTTP_INTERNAL_SERVER_ERROR;
+        }
+        if (rec->ktype != APR_CRYPTO_KTYPE_SECRET) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                          APLOGNO(03426) "key is not a symmetrical key");
+            return HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ap_set_content_type(r, "application/octet-stream");
+        ap_set_content_length(r, rec->k.secret.secretLen);
+        ap_rwrite(rec->k.secret.secret, rec->k.secret.secretLen, r);
+
+        return OK;
+
+    }
+    else {
+
+        return HTTP_NOT_FOUND;
+
+    }
+
+}
+
+static void *create_crypto_config(apr_pool_t * p, server_rec *s)
+{
+    crypto_conf *new = (crypto_conf *) apr_pcalloc(p, sizeof(crypto_conf));
+
+    /* if no library has been configured, set the recommended library
+     * as a sensible default.
+     */
+#ifdef APU_CRYPTO_RECOMMENDED_DRIVER
+    new->library = APU_CRYPTO_RECOMMENDED_DRIVER;
+#endif
+    new->crypto = apr_pcalloc(p, sizeof(apr_crypto_t *));
+
+    return (void *) new;
+}
+
+static void *merge_crypto_config(apr_pool_t * p, void *basev, void *addv)
+{
+    crypto_conf *new = (crypto_conf *) apr_pcalloc(p, sizeof(crypto_conf));
+    crypto_conf *add = (crypto_conf *) addv;
+    crypto_conf *base = (crypto_conf *) basev;
+
+    new->library = (add->library_set == 0) ? base->library : add->library;
+    new->params = (add->library_set == 0) ? base->params : add->params;
+    new->library_set = add->library_set || base->library_set;
+
+    new->crypto = base->crypto;
+
+    return (void *) new;
+}
+
+static void *create_crypto_dir_config(apr_pool_t * p, char *dummy)
+{
+    crypto_dir_conf *new =
+        (crypto_dir_conf *) apr_pcalloc(p, sizeof(crypto_dir_conf));
+
+    new->size = DEFAULT_BUFFER_SIZE;    /* default size */
+    new->cipher = DEFAULT_CIPHER;
+    new->mode = DEFAULT_MODE;
+
+    return (void *) new;
+}
+
+static void *merge_crypto_dir_config(apr_pool_t * p, void *basev, void *addv)
+{
+    crypto_dir_conf *new =
+        (crypto_dir_conf *) apr_pcalloc(p, sizeof(crypto_dir_conf));
+    crypto_dir_conf *add = (crypto_dir_conf *) addv;
+    crypto_dir_conf *base = (crypto_dir_conf *) basev;
+
+    new->size = (add->size_set == 0) ? base->size : add->size;
+    new->size_set = add->size_set || base->size_set;
+
+    new->cipher = (add->cipher_set == 0) ? base->cipher : add->cipher;
+    new->mode = (add->cipher_set == 0) ? base->mode : add->mode;
+    new->cipher_set = add->cipher_set || base->cipher_set;
+
+    new->key = (add->key_set == 0) ? base->key : add->key;
+    new->key_set = add->key_set || base->key_set;
+
+    new->iv = (add->iv_set == 0) ? base->iv : add->iv;
+    new->iv_set = add->iv_set || base->iv_set;
+
+    return new;
+}
+
+static const char *set_crypto_size(cmd_parms *cmd, void *dconf,
+                                   const char *arg)
+{
+    crypto_dir_conf *conf = dconf;
+
+    if (APR_SUCCESS != apr_strtoff(&(conf->size), arg, NULL, 10)
+        || conf->size <= 0) {
+        return "CryptoSize must be a size in bytes, and greater than zero";
+    }
+    conf->size_set = 1;
+
+    return NULL;
+}
+
+static const char *set_crypto_driver(cmd_parms *cmd, void *config,
+                                     const char *arg)
+{
+    crypto_conf *conf =
+        (crypto_conf *) ap_get_module_config(cmd->server->module_config,
+                                             &crypto_module);
+
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+    if (err != NULL) {
+        return err;
+    }
+
+    conf->library = ap_getword_conf(cmd->pool, &arg);
+    conf->params = arg;
+    conf->crypto = apr_pcalloc(cmd->pool, sizeof(apr_crypto_t *));
+    conf->library_set = 1;
+
+    return NULL;
+}
+
+static const char *set_crypto_cipher(cmd_parms *cmd, void *config,
+                                     const char *cipher, const char *mode)
+{
+    crypto_dir_conf *dconf = (crypto_dir_conf *) config;
+
+    dconf->cipher = cipher;
+    dconf->mode = mode ? mode : DEFAULT_MODE;
+    dconf->cipher_set = 1;
+
+    return NULL;
+}
+
+static const char *set_crypto_key(cmd_parms *cmd, void *config,
+                                  const char *arg)
+{
+    crypto_dir_conf *dconf = (crypto_dir_conf *) config;
+
+    pass_conf *key = dconf->key = apr_pcalloc(cmd->pool, sizeof(pass_conf));
+    dconf->key_set = 1;
+
+    return parse_pass_conf_binary(cmd, key, arg);
+}
+
+static const char *set_crypto_iv(cmd_parms *cmd, void *config,
+                                 const char *arg)
+{
+    crypto_dir_conf *dconf = (crypto_dir_conf *) config;
+
+    pass_conf *iv = dconf->iv = apr_pcalloc(cmd->pool, sizeof(pass_conf));
+    dconf->iv_set = 1;
+
+    return parse_pass_conf_binary(cmd, iv, arg);
+}
+
+static const command_rec crypto_cmds[] = {
+    AP_INIT_TAKE1("CryptoSize", set_crypto_size, NULL, ACCESS_CONF,
+                  "Maximum size of the buffer used by the crypto filters"),
+    AP_INIT_RAW_ARGS("CryptoDriver", set_crypto_driver, NULL, RSRC_CONF,
+                     "The underlying crypto library driver to use"),
+    AP_INIT_TAKE12("CryptoCipher", set_crypto_cipher, NULL,
+                   RSRC_CONF | OR_AUTHCFG,
+                   "The underlying crypto cipher and mode to use. If unspecified, the mode defaults to 'cbc'"),
+    AP_INIT_TAKE1("CryptoKey", set_crypto_key, NULL, RSRC_CONF | OR_AUTHCFG,
+                  "The crypto key scheme and value to use. Scheme is one of 'none', 'file:', 'hex:', 'base64:' or 'decimal:'"),
+    AP_INIT_TAKE1("CryptoIV", set_crypto_iv, NULL, RSRC_CONF | OR_AUTHCFG,
+                  "The crypto IV scheme and value to use. Scheme is one of 'none', 'file:', 'hex:', 'base64:' or 'decimal:'"),
+    {NULL}
+};
+
+/**
+ * Initialise the SSL in the post_config hook.
+ */
+static int
+crypto_init(apr_pool_t * p, apr_pool_t * plog,
+            apr_pool_t * ptemp, server_rec *s)
+{
+    const apr_crypto_driver_t *driver = NULL;
+
+    while (s) {
+
+        crypto_conf *conf = ap_get_module_config(s->module_config,
+                                                 &crypto_module);
+
+        if (conf->library_set && !*conf->crypto) {
+
+            const apu_err_t *err = NULL;
+            apr_status_t rv;
+
+            rv = apr_crypto_init(p);
+            if (APR_SUCCESS != rv && APR_EREINIT != rv) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             APLOGNO(03427) "APR crypto could not be initialised");
+                return rv;
+            }
+
+            rv = apr_crypto_get_driver(&driver, conf->library, conf->params,
+                                       &err, p);
+            if (APR_EREINIT == rv) {
+                ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s,
+                             APLOGNO(03436) "warning: crypto for '%s' was already initialised, "
+                             "using existing configuration", conf->library);
+                rv = APR_SUCCESS;
+            }
+            if (APR_SUCCESS != rv && err) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             APLOGNO(03437) "The crypto library '%s' could not be loaded: %s (%s: %d)",
+                             conf->library, err->msg, err->reason, err->rc);
+                return rv;
+            }
+            if (APR_ENOTIMPL == rv) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             APLOGNO(03438) "The crypto library '%s' could not be found",
+                             conf->library);
+                return rv;
+            }
+            if (APR_SUCCESS != rv || !driver) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             APLOGNO(03439) "The crypto library '%s' could not be loaded",
+                             conf->library);
+                return rv;
+            }
+
+            rv = apr_crypto_make(conf->crypto, driver, conf->params, p);
+            if (APR_SUCCESS != rv) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             APLOGNO(03440) "The crypto library '%s' could not be initialised",
+                             conf->library);
+                return rv;
+            }
+
+            ap_log_error(APLOG_MARK, APLOG_INFO, rv, s,
+                         APLOGNO(03441) "The crypto library '%s' was loaded successfully",
+                         conf->library);
+
+        }
+        s = s->next;
+    }
+
+    return OK;
+}
+
+static apr_status_t
+crypto_key(request_rec *r,
+           apr_crypto_block_key_type_t * cipher,
+           apr_crypto_block_key_mode_t * mode, int pad,
+           const apr_crypto_key_rec_t ** recptr)
+{
+    apr_crypto_key_rec_t *rec;
+
+    crypto_dir_conf *conf =
+        ap_get_module_config(r->per_dir_config, &crypto_module);
+
+    pass_conf *key = conf->key;
+
+    *recptr = rec = apr_palloc(r->pool, sizeof(apr_crypto_key_rec_t));
+    rec->ktype = APR_CRYPTO_KTYPE_SECRET;
+    rec->type = cipher->type;
+    rec->mode = mode->mode;
+    rec->pad = pad;
+    rec->k.secret.secretLen = cipher->keysize;
+
+    return exec_pass_conf_binary(r, key, "key", cipher->keysize,
+                                 &(rec->k.secret.secret));
+}
+
+static apr_status_t
+crypto_iv(request_rec *r,
+          apr_crypto_block_key_type_t * cipher, const unsigned char **v)
+{
+    crypto_dir_conf *conf =
+        ap_get_module_config(r->per_dir_config, &crypto_module);
+
+    pass_conf *iv = conf->iv;
+
+    return exec_pass_conf_binary(r, iv, "iv", cipher->ivsize, v);
+}
+
+static void register_hooks(apr_pool_t * p)
+{
+    ap_hook_crypto_key(crypto_key, NULL, NULL, APR_HOOK_REALLY_LAST);
+    ap_hook_crypto_iv(crypto_iv, NULL, NULL, APR_HOOK_REALLY_LAST);
+    ap_hook_post_config(crypto_init, NULL, NULL, APR_HOOK_LAST);
+    ap_hook_handler(crypto_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_register_output_filter("ENCRYPT", crypto_out_filter, init_encrypt,
+                              AP_FTYPE_RESOURCE);
+    ap_register_input_filter("ENCRYPT", crypto_in_filter, init_encrypt,
+                             AP_FTYPE_RESOURCE);
+    ap_register_output_filter("DECRYPT", crypto_out_filter, init_decrypt,
+                              AP_FTYPE_RESOURCE);
+    ap_register_input_filter("DECRYPT", crypto_in_filter, init_decrypt,
+                             AP_FTYPE_RESOURCE);
+}
+
+AP_DECLARE_MODULE(crypto) = {
+    STANDARD20_MODULE_STUFF,
+    create_crypto_dir_config, /* create per-directory config structure */
+    merge_crypto_dir_config,  /* merge per-directory config structures */
+    create_crypto_config,     /* create per-server config structure */
+    merge_crypto_config,      /* merge per-server config structures */
+    crypto_cmds,              /* command apr_table_t */
+    register_hooks            /* register hooks */
+};
+
+#endif

Added: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.dsp?rev=1840688&view=auto
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.dsp (added)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.dsp Wed Sep 12 13:56:17 2018
@@ -0,0 +1,111 @@
+# Microsoft Developer Studio Project File - Name="mod_crypto" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_crypto - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "mod_crypto.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "mod_crypto.mak" CFG="mod_crypto - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "mod_crypto - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_crypto - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "mod_crypto - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "HAVE_ZUTIL_H" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_crypto_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/mod_crypto.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_crypto.so" /d LONG_NAME="crypto_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_crypto.so" /base:@..\..\os\win32\BaseAddr.ref,mod_crypto.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_crypto.so" /base:@..\..\os\win32\BaseAddr.ref,mod_crypto.so /opt:ref
+# Begin Special Build Tool
+TargetPath=.\Release\mod_crypto.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "mod_crypto - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "HAVE_ZUTIL_H" /Fd"Debug\mod_crypto_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/mod_crypto.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_crypto.so" /d LONG_NAME="crypto_module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_crypto.so" /base:@..\..\os\win32\BaseAddr.ref,mod_crypto.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_crypto.so" /base:@..\..\os\win32\BaseAddr.ref,mod_crypto.so
+# Begin Special Build Tool
+TargetPath=.\Debug\mod_crypto.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "mod_crypto - Win32 Release"
+# Name "mod_crypto - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_crypto.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\httpd.rc
+# End Source File
+# End Target
+# End Project

Added: httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.h
URL: http://svn.apache.org/viewvc/httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.h?rev=1840688&view=auto
==============================================================================
--- httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.h (added)
+++ httpd/sandbox/httpd-2.4.x-trunk-delta/modules/filters/mod_crypto.h Wed Sep 12 13:56:17 2018
@@ -0,0 +1,95 @@
+/* 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_CRYPTO_H_
+#define _MOD_CRYPTO_H_
+
+/* Create a set of CRYPTO_DECLARE(type), CRYPTO_DECLARE_NONSTD(type) and
+ * CRYPTO_DECLARE_DATA with appropriate export and import tags for the platform
+ */
+#if !defined(WIN32)
+#define CRYPTO_DECLARE(type)        type
+#define CRYPTO_DECLARE_NONSTD(type) type
+#define CRYPTO_DECLARE_DATA
+#elif defined(CRYPTO_DECLARE_STATIC)
+#define CRYPTO_DECLARE(type)        type __stdcall
+#define CRYPTO_DECLARE_NONSTD(type) type
+#define CRYPTO_DECLARE_DATA
+#elif defined(CRYPTO_DECLARE_EXPORT)
+#define CRYPTO_DECLARE(type)        __declspec(dllexport) type __stdcall
+#define CRYPTO_DECLARE_NONSTD(type) __declspec(dllexport) type
+#define CRYPTO_DECLARE_DATA         __declspec(dllexport)
+#else
+#define CRYPTO_DECLARE(type)        __declspec(dllimport) type __stdcall
+#define CRYPTO_DECLARE_NONSTD(type) __declspec(dllimport) type
+#define CRYPTO_DECLARE_DATA         __declspec(dllimport)
+#endif
+
+/**
+ * @file  mod_crypto.h
+ * @brief Crypto Module for Apache
+ *
+ * @defgroup MOD_CRYPTO mod_crypto
+ * @ingroup  APACHE_MODS
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_hooks.h"
+#include "apr_optional.h"
+#include "apr_tables.h"
+#include "apr_uuid.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+#include "apr_crypto.h"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "ap_config.h"
+
+/**
+ * Hook to provide a key.
+ *
+ * @param r The request
+ * @param cipher The cipher to use with this key
+ * @param rec Pointer to the key record from which to derive the key
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, CRYPTO, apr_status_t, crypto_key,
+                          (request_rec *r,
+                           apr_crypto_block_key_type_t * cipher,
+                           apr_crypto_block_key_mode_t * mode, int pad,
+                           const apr_crypto_key_rec_t ** rec));
+
+/**
+ * Hook to provide an initialization vector (IV).
+ *
+ * @param r The request
+ * @param size The block size of the expected IV.
+ * @param iv A pointer to where the iv will be returned
+ */
+APR_DECLARE_EXTERNAL_HOOK(ap, CRYPTO, apr_status_t, crypto_iv,
+                          (request_rec *r,
+                           apr_crypto_block_key_type_t * cipher,
+                           const unsigned char **iv));
+
+/**
+ * The name of the module.
+ */
+extern module AP_MODULE_DECLARE_DATA crypto_module;
+
+/** @} */
+
+#endif