diff --git a/README.debrand b/README.debrand
deleted file mode 100644
index 01c46d2..0000000
--- a/README.debrand
+++ /dev/null
@@ -1,2 +0,0 @@
-Warning: This package was configured for automatic debranding, but the changes
-failed to apply.
diff --git a/SOURCES/httpd-2.4.37-CVE-2018-17199.patch b/SOURCES/httpd-2.4.37-CVE-2018-17199.patch
new file mode 100644
index 0000000..e98a26e
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-CVE-2018-17199.patch
@@ -0,0 +1,39 @@
+diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
+index 10e6396..7ee477c 100644
+--- a/modules/session/mod_session.c
++++ b/modules/session/mod_session.c
+@@ -126,20 +126,23 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
+
+ /* found a session that hasn't expired? */
+ now = apr_time_now();
++
+ if (zz) {
+- if (zz->expiry && zz->expiry < now) {
++ /* load the session attibutes */
++ rv = ap_run_session_decode(r, zz);
++
++ /* having a session we cannot decode is just as good as having
++ none at all */
++ if (OK != rv) {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
++ "error while decoding the session, "
++ "session not loaded: %s", r->uri);
+ zz = NULL;
+ }
+- else {
+- /* having a session we cannot decode is just as good as having
+- none at all */
+- rv = ap_run_session_decode(r, zz);
+- if (OK != rv) {
+- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
+- "error while decoding the session, "
+- "session not loaded: %s", r->uri);
+- zz = NULL;
+- }
++
++ /* invalidate session if session is expired */
++ if (zz && zz->expiry && zz->expiry < now) {
++ zz = NULL;
+ }
+ }
+
diff --git a/SOURCES/httpd-2.4.37-CVE-2020-11984.patch b/SOURCES/httpd-2.4.37-CVE-2020-11984.patch
new file mode 100644
index 0000000..4bb9ea2
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-CVE-2020-11984.patch
@@ -0,0 +1,36 @@
+--- a/modules/proxy/mod_proxy_uwsgi.c 2020/07/24 09:31:46 1880250
++++ b/modules/proxy/mod_proxy_uwsgi.c 2020/07/24 09:35:25 1880251
+@@ -136,7 +136,7 @@
+ int j;
+
+ apr_size_t headerlen = 4;
+- apr_uint16_t pktsize, keylen, vallen;
++ apr_size_t pktsize, keylen, vallen;
+ const char *script_name;
+ const char *path_info;
+ const char *auth;
+@@ -178,6 +178,15 @@
+ headerlen += 2 + strlen(env[j].key) + 2 + strlen(env[j].val);
+ }
+
++ pktsize = headerlen - 4;
++ if (pktsize > APR_UINT16_MAX) {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10259)
++ "can't send headers to %s:%u: packet size too "
++ "large (%" APR_SIZE_T_FMT ")",
++ conn->hostname, conn->port, pktsize);
++ return HTTP_INTERNAL_SERVER_ERROR;
++ }
++
+ ptr = buf = apr_palloc(r->pool, headerlen);
+
+ ptr += 4;
+@@ -196,8 +205,6 @@
+ ptr += vallen;
+ }
+
+- pktsize = headerlen - 4;
+-
+ buf[0] = 0;
+ buf[1] = (apr_byte_t) (pktsize & 0xff);
+ buf[2] = (apr_byte_t) ((pktsize >> 8) & 0xff);
diff --git a/SOURCES/httpd-2.4.37-htcacheclean-dont-break.patch b/SOURCES/httpd-2.4.37-htcacheclean-dont-break.patch
new file mode 100644
index 0000000..17cc64e
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-htcacheclean-dont-break.patch
@@ -0,0 +1,13 @@
+diff --git a/support/htcacheclean.c b/support/htcacheclean.c
+index 8692377..fde34c9 100644
+--- a/support/htcacheclean.c
++++ b/support/htcacheclean.c
+@@ -557,8 +557,6 @@ static int list_urls(char *path, apr_pool_t *pool, apr_off_t round)
+ }
+ }
+ }
+-
+- break;
+ }
+ }
+ }
diff --git a/SOURCES/httpd-2.4.37-pr37355.patch b/SOURCES/httpd-2.4.37-pr37355.patch
new file mode 100644
index 0000000..0d161a5
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-pr37355.patch
@@ -0,0 +1,143 @@
+diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
+index d13c249..f383996 100644
+--- a/modules/proxy/mod_proxy.c
++++ b/modules/proxy/mod_proxy.c
+@@ -1200,11 +1200,20 @@ static int proxy_handler(request_rec *r)
+ /* handle the scheme */
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01142)
+ "Trying to run scheme_handler against proxy");
++
++ if (ents[i].creds) {
++ apr_table_set(r->notes, "proxy-basic-creds", ents[i].creds);
++ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
++ "Using proxy auth creds %s", ents[i].creds);
++ }
++
+ access_status = proxy_run_scheme_handler(r, worker,
+ conf, url,
+ ents[i].hostname,
+ ents[i].port);
+
++ if (ents[i].creds) apr_table_unset(r->notes, "proxy-basic-creds");
++
+ /* Did the scheme handler process the request? */
+ if (access_status != DECLINED) {
+ const char *cl_a;
+@@ -1621,8 +1630,8 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
+ return new;
+ }
+
+-static const char *
+- add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, int regex)
++static const char *add_proxy(cmd_parms *cmd, void *dummy, const char *f1,
++ const char *r1, const char *creds, int regex)
+ {
+ server_rec *s = cmd->server;
+ proxy_server_conf *conf =
+@@ -1680,19 +1689,24 @@ static const char *
+ new->port = port;
+ new->regexp = reg;
+ new->use_regex = regex;
++ if (creds) {
++ new->creds = apr_pstrcat(cmd->pool, "Basic ",
++ ap_pbase64encode(cmd->pool, (char *)creds),
++ NULL);
++ }
+ return NULL;
+ }
+
+-static const char *
+- add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1)
++static const char *add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1,
++ const char *r1, const char *creds)
+ {
+- return add_proxy(cmd, dummy, f1, r1, 0);
++ return add_proxy(cmd, dummy, f1, r1, creds, 0);
+ }
+
+-static const char *
+- add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1)
++static const char *add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1,
++ const char *r1, const char *creds)
+ {
+- return add_proxy(cmd, dummy, f1, r1, 1);
++ return add_proxy(cmd, dummy, f1, r1, creds, 1);
+ }
+
+ PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url)
+@@ -2638,9 +2652,9 @@ static const command_rec proxy_cmds[] =
+ "location, in regular expression syntax"),
+ AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF,
+ "on if the true proxy requests should be accepted"),
+- AP_INIT_TAKE2("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,
++ AP_INIT_TAKE23("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,
+ "a scheme, partial URL or '*' and a proxy server"),
+- AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
++ AP_INIT_TAKE23("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
+ "a regex pattern and a proxy server"),
+ AP_INIT_FLAG("ProxyPassInterpolateEnv", ap_set_flag_slot_char,
+ (void*)APR_OFFSETOF(proxy_dir_conf, interpolate_env),
+diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
+index 288c5d4..57cc92f 100644
+--- a/modules/proxy/mod_proxy.h
++++ b/modules/proxy/mod_proxy.h
+@@ -116,6 +116,7 @@ struct proxy_remote {
+ const char *protocol; /* the scheme used to talk to this proxy */
+ const char *hostname; /* the hostname of this proxy */
+ ap_regex_t *regexp; /* compiled regex (if any) for the remote */
++ const char *creds; /* auth credentials (if any) for the proxy */
+ int use_regex; /* simple boolean. True if we have a regex pattern */
+ apr_port_t port; /* the port for this proxy */
+ };
+diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
+index 0759dac..2bfc8f0 100644
+--- a/modules/proxy/proxy_util.c
++++ b/modules/proxy/proxy_util.c
+@@ -2446,11 +2446,14 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
+ * So let's make it configurable by env.
+ * The logic here is the same used in mod_proxy_http.
+ */
+- proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
++ proxy_auth = apr_table_get(r->notes, "proxy-basic-creds");
++ if (proxy_auth == NULL)
++ proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
++
+ if (proxy_auth != NULL &&
+ proxy_auth[0] != '\0' &&
+- r->user == NULL && /* we haven't yet authenticated */
+- apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
++ (r->user == NULL /* we haven't yet authenticated */
++ || apr_table_get(r->subprocess_env, "Proxy-Chain-Auth"))) {
+ forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth);
+ }
+ }
+@@ -2672,7 +2675,8 @@ static apr_status_t send_http_connect(proxy_conn_rec *backend,
+ nbytes = apr_snprintf(buffer, sizeof(buffer),
+ "CONNECT %s:%d HTTP/1.0" CRLF,
+ forward->target_host, forward->target_port);
+- /* Add proxy authorization from the initial request if necessary */
++ /* Add proxy authorization from the configuration, or initial
++ * request if necessary */
+ if (forward->proxy_auth != NULL) {
+ nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes,
+ "Proxy-Authorization: %s" CRLF,
+@@ -3567,6 +3571,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
+ apr_bucket *e;
+ int do_100_continue;
+ conn_rec *origin = p_conn->connection;
++ const char *creds;
+ proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
+
+ /*
+@@ -3743,6 +3748,11 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
+ return HTTP_BAD_REQUEST;
+ }
+
++ creds = apr_table_get(r->notes, "proxy-basic-creds");
++ if (creds) {
++ apr_table_mergen(r->headers_in, "Proxy-Authorization", creds);
++ }
++
+ /* send request headers */
+ headers_in_array = apr_table_elts(r->headers_in);
+ headers_in = (const apr_table_entry_t *) headers_in_array->elts;
diff --git a/SOURCES/httpd-2.4.37-proxy-ws-idle-timeout.patch b/SOURCES/httpd-2.4.37-proxy-ws-idle-timeout.patch
new file mode 100644
index 0000000..25864bf
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-proxy-ws-idle-timeout.patch
@@ -0,0 +1,132 @@
+diff --git a/docs/manual/mod/mod_proxy_wstunnel.html.en b/docs/manual/mod/mod_proxy_wstunnel.html.en
+index 21ffbe2..16e1628 100644
+--- a/docs/manual/mod/mod_proxy_wstunnel.html.en
++++ b/docs/manual/mod/mod_proxy_wstunnel.html.en
+@@ -60,14 +60,33 @@ NONE means you bypass the check for the header but still upgrade to WebSocket.
+ ANY means that Upgrade
will read in the request headers and use
+ in the response Upgrade
+
+-
+
Available Languages: en |
+diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
+index 4aadbab..ca3ed3a 100644
+--- a/modules/proxy/mod_proxy_wstunnel.c
++++ b/modules/proxy/mod_proxy_wstunnel.c
+@@ -18,6 +18,10 @@
+
+ module AP_MODULE_DECLARE_DATA proxy_wstunnel_module;
+
++typedef struct {
++ apr_time_t idle_timeout;
++} proxyws_dir_conf;
++
+ /*
+ * Canonicalise http-like URLs.
+ * scheme is the scheme for the URL
+@@ -108,6 +112,8 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+ conn_rec *c = r->connection;
+ apr_socket_t *sock = conn->sock;
+ conn_rec *backconn = conn->connection;
++ proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
++ &proxy_wstunnel_module);
+ char *buf;
+ apr_bucket_brigade *header_brigade;
+ apr_bucket *e;
+@@ -185,10 +191,13 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+ c->keepalive = AP_CONN_CLOSE;
+
+ do { /* Loop until done (one side closes the connection, or an error) */
+- rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled);
++ rv = apr_pollset_poll(pollset, dconf->idle_timeout, &pollcnt, &signalled);
+ if (rv != APR_SUCCESS) {
+ if (APR_STATUS_IS_EINTR(rv)) {
+ continue;
++ } else if(APR_STATUS_IS_TIMEUP(rv)){
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "RH: the connection has timed out");
++ return HTTP_REQUEST_TIME_OUT;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02444) "error apr_poll()");
+ return HTTP_INTERNAL_SERVER_ERROR;
+@@ -366,6 +375,38 @@ cleanup:
+ return status;
+ }
+
++static const char * proxyws_set_idle(cmd_parms *cmd, void *conf, const char *val)
++{
++ proxyws_dir_conf *dconf = conf;
++ if (ap_timeout_parameter_parse(val, &(dconf->idle_timeout), "s") != APR_SUCCESS)
++ return "ProxyWebsocketIdleTimeout timeout has wrong format";
++
++ if (dconf->idle_timeout < 0)
++ return "ProxyWebsocketIdleTimeout timeout has to be a non-negative number";
++
++ if (!dconf->idle_timeout) dconf->idle_timeout = -1; /* loop indefinitely */
++
++ return NULL;
++}
++
++static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy)
++{
++ proxyws_dir_conf *new =
++ (proxyws_dir_conf *) apr_pcalloc(p, sizeof(proxyws_dir_conf));
++
++ new->idle_timeout = -1; /* no timeout */
++
++ return (void *) new;
++}
++
++static const command_rec ws_proxy_cmds[] =
++{
++ AP_INIT_TAKE1("ProxyWebsocketIdleTimeout", proxyws_set_idle, NULL, RSRC_CONF|ACCESS_CONF,
++ "timeout for activity in either direction, unlimited by default."),
++
++ {NULL}
++};
++
+ static void ap_proxy_http_register_hook(apr_pool_t *p)
+ {
+ proxy_hook_scheme_handler(proxy_wstunnel_handler, NULL, NULL, APR_HOOK_FIRST);
+@@ -374,10 +415,10 @@ static void ap_proxy_http_register_hook(apr_pool_t *p)
+
+ AP_DECLARE_MODULE(proxy_wstunnel) = {
+ STANDARD20_MODULE_STUFF,
+- NULL, /* create per-directory config structure */
++ create_proxyws_dir_config, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+- NULL, /* command apr_table_t */
++ ws_proxy_cmds, /* command apr_table_t */
+ ap_proxy_http_register_hook /* register hooks */
+ };
diff --git a/SOURCES/httpd-2.4.37-r1851471.patch b/SOURCES/httpd-2.4.37-r1851471.patch
index f56c907..03e3301 100644
--- a/SOURCES/httpd-2.4.37-r1851471.patch
+++ b/SOURCES/httpd-2.4.37-r1851471.patch
@@ -1,20 +1,19 @@
-# ./pullrev.sh 1851471
-http://svn.apache.org/viewvc?view=revision&revision=1851471
-
---- httpd-2.4.37/modules/ssl/ssl_engine_io.c
-+++ httpd-2.4.37/modules/ssl/ssl_engine_io.c
-@@ -200,6 +200,8 @@
+diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
+index 0958135..018b667 100644
+--- a/modules/ssl/ssl_engine_io.c
++++ b/modules/ssl/ssl_engine_io.c
+@@ -200,6 +200,8 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
apr_bucket *e;
int need_flush;
+ BIO_clear_retry_flags(bio);
+
+ #ifndef SSL_OP_NO_RENEGOTIATION
/* Abort early if the client has initiated a renegotiation. */
if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
- outctx->rc = APR_ECONNABORTED;
-@@ -206,12 +208,6 @@
- return -1;
+@@ -208,12 +210,6 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
}
+ #endif
- /* when handshaking we'll have a small number of bytes.
- * max size SSL will pass us here is about 16k.
@@ -25,18 +24,18 @@ http://svn.apache.org/viewvc?view=revision&revision=1851471
/* Use a transient bucket for the output data - any downstream
* filter must setaside if necessary. */
e = apr_bucket_transient_create(in, inl, outctx->bb->bucket_alloc);
-@@ -458,6 +454,8 @@
+@@ -460,6 +456,8 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
if (!in)
return 0;
+ BIO_clear_retry_flags(bio);
+
+ #ifndef SSL_OP_NO_RENEGOTIATION
/* Abort early if the client has initiated a renegotiation. */
if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
- inctx->rc = APR_ECONNABORTED;
-@@ -464,8 +462,6 @@
- return -1;
+@@ -468,8 +466,6 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
}
+ #endif
- BIO_clear_retry_flags(bio);
-
diff --git a/SOURCES/httpd-2.4.37-r1861793+.patch b/SOURCES/httpd-2.4.37-r1861793+.patch
index a74ece4..4ac9c2d 100644
--- a/SOURCES/httpd-2.4.37-r1861793+.patch
+++ b/SOURCES/httpd-2.4.37-r1861793+.patch
@@ -57,7 +57,7 @@ index 660a27c..136f62a 100644
- " -B Force bcrypt encryption of the password (very secure)." NL
+ " -2 Force SHA-256 crypt() hash of the password (secure)." NL
+ " -5 Force SHA-512 crypt() hash of the password (secure)." NL
-+ " -B Force bcrypt aencryption of the password (very secure)." NL
++ " -B Force bcrypt encryption of the password (very secure)." NL
" -C Set the computing time used for the bcrypt algorithm" NL
" (higher is more secure but slower, default: %d, valid: 4 to 31)." NL
+ " -r Set the number of rounds used for the SHA-256, SHA-512 algorithms" NL
diff --git a/SOURCES/httpd-2.4.37-r1864000.patch b/SOURCES/httpd-2.4.37-r1864000.patch
new file mode 100644
index 0000000..8adecfa
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1864000.patch
@@ -0,0 +1,40 @@
+--- a/modules/proxy/mod_proxy_hcheck.c 2019/07/30 13:01:08 1863999
++++ b/modules/proxy/mod_proxy_hcheck.c 2019/07/30 13:01:21 1864000
+@@ -110,6 +110,10 @@
+ if (!worker && !v) {
+ return "Bad call to set_worker_hc_param()";
+ }
++ if (!ctx) {
++ ctx = hc_create_config(p, s);
++ ap_set_module_config(s->module_config, &proxy_hcheck_module, ctx);
++ }
+ temp = (hc_template_t *)v;
+ if (!strcasecmp(key, "hctemplate")) {
+ hc_template_t *template;
+@@ -1059,6 +1063,8 @@
+ int i;
+ sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
+ &proxy_hcheck_module);
++ if (!ctx)
++ return;
+ if (apr_is_empty_table(ctx->conditions))
+ return;
+
+@@ -1088,6 +1094,8 @@
+ int i;
+ sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
+ &proxy_hcheck_module);
++ if (!ctx)
++ return;
+ if (apr_is_empty_table(ctx->conditions))
+ return;
+
+@@ -1111,6 +1119,8 @@
+ int i;
+ sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
+ &proxy_hcheck_module);
++ if (!ctx)
++ return 0;
+ if (apr_is_empty_table(ctx->conditions))
+ return 0;
+
diff --git a/SOURCES/httpd-2.4.37-r1872790.patch b/SOURCES/httpd-2.4.37-r1872790.patch
new file mode 100644
index 0000000..2cab606
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1872790.patch
@@ -0,0 +1,636 @@
+diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
+index 57cc92f..fbbd508 100644
+--- a/modules/proxy/mod_proxy.h
++++ b/modules/proxy/mod_proxy.h
+@@ -288,12 +288,15 @@ typedef struct {
+
+ /* Connection pool */
+ struct proxy_conn_pool {
+- apr_pool_t *pool; /* The pool used in constructor and destructor calls */
+- apr_sockaddr_t *addr; /* Preparsed remote address info */
+- apr_reslist_t *res; /* Connection resource list */
+- proxy_conn_rec *conn; /* Single connection for prefork mpm */
++ apr_pool_t *pool; /* The pool used in constructor and destructor calls */
++ apr_sockaddr_t *addr; /* Preparsed remote address info */
++ apr_reslist_t *res; /* Connection resource list */
++ proxy_conn_rec *conn; /* Single connection for prefork mpm */
++ apr_pool_t *dns_pool; /* The pool used for worker scoped DNS resolutions */
+ };
+
++#define AP_VOLATILIZE_T(T, x) (*(T volatile *)&(x))
++
+ /* worker status bits */
+ /*
+ * NOTE: Keep up-to-date w/ proxy_wstat_tbl[]
+@@ -475,7 +478,9 @@ struct proxy_worker {
+ proxy_conn_pool *cp; /* Connection pool to use */
+ proxy_worker_shared *s; /* Shared data */
+ proxy_balancer *balancer; /* which balancer am I in? */
++#if APR_HAS_THREADS
+ apr_thread_mutex_t *tmutex; /* Thread lock for updating address cache */
++#endif
+ void *context; /* general purpose storage */
+ ap_conf_vector_t *section_config; /* -section wherein defined */
+ };
+@@ -534,7 +539,9 @@ struct proxy_balancer {
+ apr_time_t wupdated; /* timestamp of last change to workers list */
+ proxy_balancer_method *lbmethod;
+ apr_global_mutex_t *gmutex; /* global lock for updating list of workers */
++#if APR_HAS_THREADS
+ apr_thread_mutex_t *tmutex; /* Thread lock for updating shm */
++#endif
+ proxy_server_conf *sconf;
+ void *context; /* general purpose storage */
+ proxy_balancer_shared *s; /* Shared data */
+diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
+index c59f5e9..3a28038 100644
+--- a/modules/proxy/mod_proxy_balancer.c
++++ b/modules/proxy/mod_proxy_balancer.c
+@@ -346,23 +346,27 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer,
+ proxy_worker *candidate = NULL;
+ apr_status_t rv;
+
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01163)
+ "%s: Lock failed for find_best_worker()",
+ balancer->s->name);
+ return NULL;
+ }
++#endif
+
+ candidate = (*balancer->lbmethod->finder)(balancer, r);
+
+ if (candidate)
+ candidate->s->elected++;
+
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01164)
+ "%s: Unlock failed for find_best_worker()",
+ balancer->s->name);
+ }
++#endif
+
+ if (candidate == NULL) {
+ /* All the workers are in error state or disabled.
+@@ -492,11 +496,13 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
+ /* Step 2: Lock the LoadBalancer
+ * XXX: perhaps we need the process lock here
+ */
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01166)
+ "%s: Lock failed for pre_request", (*balancer)->s->name);
+ return DECLINED;
+ }
++#endif
+
+ /* Step 3: force recovery */
+ force_recovery(*balancer, r->server);
+@@ -557,20 +563,24 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01167)
+ "%s: All workers are in error state for route (%s)",
+ (*balancer)->s->name, route);
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01168)
+ "%s: Unlock failed for pre_request",
+ (*balancer)->s->name);
+ }
++#endif
+ return HTTP_SERVICE_UNAVAILABLE;
+ }
+ }
+
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01169)
+ "%s: Unlock failed for pre_request",
+ (*balancer)->s->name);
+ }
++#endif
+ if (!*worker) {
+ runtime = find_best_worker(*balancer, r);
+ if (!runtime) {
+@@ -644,12 +654,14 @@ static int proxy_balancer_post_request(proxy_worker *worker,
+
+ apr_status_t rv;
+
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01173)
+ "%s: Lock failed for post_request",
+ balancer->s->name);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
++#endif
+
+ if (!apr_is_empty_array(balancer->errstatuses)
+ && !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
+@@ -681,11 +693,12 @@ static int proxy_balancer_post_request(proxy_worker *worker,
+ worker->s->error_time = apr_time_now();
+
+ }
+-
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01175)
+ "%s: Unlock failed for post_request", balancer->s->name);
+ }
++#endif
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01176)
+ "proxy_balancer_post_request for (%s)", balancer->s->name);
+
+@@ -945,7 +958,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
+ PROXY_STRNCPY(balancer->s->sname, sname); /* We know this will succeed */
+
+ balancer->max_workers = balancer->workers->nelts + balancer->growth;
+-
+ /* Create global mutex */
+ rv = ap_global_mutex_create(&(balancer->gmutex), NULL, balancer_mutex_type,
+ balancer->s->sname, s, pconf, 0);
+@@ -955,7 +967,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
+ balancer->s->sname);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+-
+ apr_pool_cleanup_register(pconf, (void *)s, lock_remove,
+ apr_pool_cleanup_null);
+
+@@ -1135,17 +1146,21 @@ static int balancer_handler(request_rec *r)
+
+ balancer = (proxy_balancer *)conf->balancers->elts;
+ for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01189)
+ "%s: Lock failed for balancer_handler",
+ balancer->s->name);
+ }
++#endif
+ ap_proxy_sync_balancer(balancer, r->server, conf);
++#if APR_HAS_THREADS
+ if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01190)
+ "%s: Unlock failed for balancer_handler",
+ balancer->s->name);
+ }
++#endif
+ }
+
+ if (r->args && (r->method_number == M_GET)) {
+@@ -1359,11 +1374,13 @@ static int balancer_handler(request_rec *r)
+ proxy_worker *nworker;
+ nworker = ap_proxy_get_worker(r->pool, bsel, conf, val);
+ if (!nworker && storage->num_free_slots(bsel->wslot)) {
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_LOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01194)
+ "%s: Lock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
+ ret = ap_proxy_define_worker(conf->pool, &nworker, bsel, conf, val, 0);
+ if (!ret) {
+ unsigned int index;
+@@ -1372,53 +1389,76 @@ static int balancer_handler(request_rec *r)
+ if ((rv = storage->grab(bsel->wslot, &index)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01195)
+ "worker slotmem_grab failed");
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01196)
+ "%s: Unlock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
+ return HTTP_BAD_REQUEST;
+ }
+ if ((rv = storage->dptr(bsel->wslot, index, (void *)&shm)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01197)
+ "worker slotmem_dptr failed");
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01198)
+ "%s: Unlock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
+ return HTTP_BAD_REQUEST;
+ }
+ if ((rv = ap_proxy_share_worker(nworker, shm, index)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01199)
+ "Cannot share worker");
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01200)
+ "%s: Unlock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
+ return HTTP_BAD_REQUEST;
+ }
+ if ((rv = ap_proxy_initialize_worker(nworker, r->server, conf->pool)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_EMERG, rv, r, APLOGNO(01201)
+ "Cannot init worker");
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01202)
+ "%s: Unlock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
+ return HTTP_BAD_REQUEST;
+ }
+ /* sync all timestamps */
+ bsel->wupdated = bsel->s->wupdated = nworker->s->updated = apr_time_now();
+ /* by default, all new workers are disabled */
+ ap_proxy_set_wstatus(PROXY_WORKER_DISABLED_FLAG, 1, nworker);
++ } else {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10163)
++ "%s: failed to add worker %s",
++ bsel->s->name, val);
++#if APR_HAS_THREADS
++ PROXY_GLOBAL_UNLOCK(bsel);
++#endif
++ return HTTP_BAD_REQUEST;
+ }
++#if APR_HAS_THREADS
+ if ((rv = PROXY_GLOBAL_UNLOCK(bsel)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01203)
+ "%s: Unlock failed for adding worker",
+ bsel->s->name);
+ }
++#endif
++ } else {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10164)
++ "%s: failed to add worker %s",
++ bsel->s->name, val);
++ return HTTP_BAD_REQUEST;
+ }
+
+ }
+diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
+index 5d9175e..5c4d641 100644
+--- a/modules/proxy/mod_proxy_ftp.c
++++ b/modules/proxy/mod_proxy_ftp.c
+@@ -979,8 +979,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
+ apr_status_t rv;
+ conn_rec *origin, *data = NULL;
+ apr_status_t err = APR_SUCCESS;
++#if APR_HAS_THREADS
+ apr_status_t uerr = APR_SUCCESS;
+- apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
++#endif
++ apr_bucket_brigade *bb;
+ char *buf, *connectname;
+ apr_port_t connectport;
+ char *ftpmessage = NULL;
+@@ -1120,13 +1122,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
+
+ if (worker->s->is_address_reusable) {
+ if (!worker->cp->addr) {
++#if APR_HAS_THREADS
+ if ((err = PROXY_THREAD_LOCK(worker->balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(01037) "lock");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
++#endif
+ }
+- connect_addr = worker->cp->addr;
+- address_pool = worker->cp->pool;
++ connect_addr = AP_VOLATILIZE_T(apr_sockaddr_t *, worker->cp->addr);
++ address_pool = worker->cp->dns_pool;
+ }
+ else
+ address_pool = r->pool;
+@@ -1139,9 +1143,11 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
+ address_pool);
+ if (worker->s->is_address_reusable && !worker->cp->addr) {
+ worker->cp->addr = connect_addr;
++#if APR_HAS_THREADS
+ if ((uerr = PROXY_THREAD_UNLOCK(worker->balancer)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(01038) "unlock");
+ }
++#endif
+ }
+ /*
+ * get all the possible IP addresses for the destname and loop through
+@@ -1212,6 +1218,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
+ * correct directory...
+ */
+
++ bb = apr_brigade_create(p, c->bucket_alloc);
+
+ /* possible results: */
+ /* 120 Service ready in nnn minutes. */
+diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
+index 2bfc8f0..7714b6c 100644
+--- a/modules/proxy/proxy_util.c
++++ b/modules/proxy/proxy_util.c
+@@ -1167,8 +1167,10 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
+ lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0");
+
+ (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
++#if APR_HAS_THREADS
+ (*balancer)->gmutex = NULL;
+ (*balancer)->tmutex = NULL;
++#endif
+ (*balancer)->lbmethod = lbmethod;
+
+ if (do_malloc)
+@@ -1257,7 +1259,9 @@ PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
+
+ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, server_rec *s, apr_pool_t *p)
+ {
++#if APR_HAS_THREADS
+ apr_status_t rv = APR_SUCCESS;
++#endif
+ ap_slotmem_provider_t *storage = balancer->storage;
+ apr_size_t size;
+ unsigned int num;
+@@ -1297,6 +1301,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balance
+ if (balancer->lbmethod && balancer->lbmethod->reset)
+ balancer->lbmethod->reset(balancer, s);
+
++#if APR_HAS_THREADS
+ if (balancer->tmutex == NULL) {
+ rv = apr_thread_mutex_create(&(balancer->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
+ if (rv != APR_SUCCESS) {
+@@ -1305,6 +1310,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balance
+ return rv;
+ }
+ }
++#endif
+ return APR_SUCCESS;
+ }
+
+@@ -1446,16 +1452,14 @@ static void socket_cleanup(proxy_conn_rec *conn)
+
+ static apr_status_t conn_pool_cleanup(void *theworker)
+ {
+- proxy_worker *worker = (proxy_worker *)theworker;
+- if (worker->cp->res) {
+- worker->cp->pool = NULL;
+- }
++ ((proxy_worker *)theworker)->cp = NULL;
+ return APR_SUCCESS;
+ }
+
+ static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
+ {
+ apr_pool_t *pool;
++ apr_pool_t *dns_pool;
+ proxy_conn_pool *cp;
+
+ /*
+@@ -1466,12 +1470,21 @@ static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
+ */
+ apr_pool_create(&pool, p);
+ apr_pool_tag(pool, "proxy_worker_cp");
++ /*
++ * Create a subpool of the connection pool for worker
++ * scoped DNS resolutions. This is needed to avoid race
++ * conditions in using the connection pool by multiple
++ * threads during ramp up.
++ */
++ apr_pool_create(&dns_pool, pool);
++ apr_pool_tag(dns_pool, "proxy_worker_dns");
+ /*
+ * Alloc from the same pool as worker.
+ * proxy_conn_pool is permanently attached to the worker.
+ */
+ cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));
+ cp->pool = pool;
++ cp->dns_pool = dns_pool;
+ worker->cp = cp;
+ }
+
+@@ -1487,14 +1500,6 @@ static apr_status_t connection_cleanup(void *theconn)
+ proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
+ proxy_worker *worker = conn->worker;
+
+- /*
+- * If the connection pool is NULL the worker
+- * cleanup has been run. Just return.
+- */
+- if (!worker->cp->pool) {
+- return APR_SUCCESS;
+- }
+-
+ if (conn->r) {
+ apr_pool_destroy(conn->r->pool);
+ conn->r = NULL;
+@@ -1616,7 +1621,7 @@ static apr_status_t connection_destructor(void *resource, void *params,
+ proxy_worker *worker = params;
+
+ /* Destroy the pool only if not called from reslist_destroy */
+- if (worker->cp->pool) {
++ if (worker->cp) {
+ proxy_conn_rec *conn = resource;
+ apr_pool_destroy(conn->pool);
+ }
+@@ -1972,67 +1977,73 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
+ ap_proxy_worker_name(p, worker));
+ }
+ else {
+- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
+- "initializing worker %s local",
+- ap_proxy_worker_name(p, worker));
+ apr_global_mutex_lock(proxy_mutex);
+- /* Now init local worker data */
+- if (worker->tmutex == NULL) {
+- rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
+- if (rv != APR_SUCCESS) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00928)
+- "can not create worker thread mutex");
++ /* Check again after we got the lock if we are still uninitialized */
++ if (!(AP_VOLATILIZE_T(unsigned int, worker->local_status) & PROXY_WORKER_INITIALIZED)) {
++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
++ "initializing worker %s local",
++ ap_proxy_worker_name(p, worker));
++ /* Now init local worker data */
++#if APR_HAS_THREADS
++ if (worker->tmutex == NULL) {
++ rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
++ if (rv != APR_SUCCESS) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00928)
++ "can not create worker thread mutex");
++ apr_global_mutex_unlock(proxy_mutex);
++ return rv;
++ }
++ }
++#endif
++ if (worker->cp == NULL)
++ init_conn_pool(p, worker);
++ if (worker->cp == NULL) {
++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
++ "can not create connection pool");
+ apr_global_mutex_unlock(proxy_mutex);
+- return rv;
++ return APR_EGENERAL;
+ }
+- }
+- if (worker->cp == NULL)
+- init_conn_pool(p, worker);
+- if (worker->cp == NULL) {
+- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
+- "can not create connection pool");
+- apr_global_mutex_unlock(proxy_mutex);
+- return APR_EGENERAL;
+- }
+
+- if (worker->s->hmax) {
+- rv = apr_reslist_create(&(worker->cp->res),
+- worker->s->min, worker->s->smax,
+- worker->s->hmax, worker->s->ttl,
+- connection_constructor, connection_destructor,
+- worker, worker->cp->pool);
++ if (worker->s->hmax) {
++ rv = apr_reslist_create(&(worker->cp->res),
++ worker->s->min, worker->s->smax,
++ worker->s->hmax, worker->s->ttl,
++ connection_constructor, connection_destructor,
++ worker, worker->cp->pool);
+
+- apr_pool_cleanup_register(worker->cp->pool, (void *)worker,
+- conn_pool_cleanup,
+- apr_pool_cleanup_null);
++ apr_pool_pre_cleanup_register(worker->cp->pool, worker,
++ conn_pool_cleanup);
+
+- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00930)
+- "initialized pool in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d",
+- getpid(), worker->s->hostname_ex, worker->s->min,
+- worker->s->hmax, worker->s->smax);
++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00930)
++ "initialized pool in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d",
++ getpid(), worker->s->hostname_ex, worker->s->min,
++ worker->s->hmax, worker->s->smax);
+
+- /* Set the acquire timeout */
+- if (rv == APR_SUCCESS && worker->s->acquire_set) {
+- apr_reslist_timeout_set(worker->cp->res, worker->s->acquire);
+- }
++ /* Set the acquire timeout */
++ if (rv == APR_SUCCESS && worker->s->acquire_set) {
++ apr_reslist_timeout_set(worker->cp->res, worker->s->acquire);
++ }
+
+- }
+- else {
+- void *conn;
++ }
++ else {
++ void *conn;
+
+- rv = connection_constructor(&conn, worker, worker->cp->pool);
+- worker->cp->conn = conn;
++ rv = connection_constructor(&conn, worker, worker->cp->pool);
++ worker->cp->conn = conn;
+
+- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00931)
+- "initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
+- getpid(), worker->s->hostname_ex);
++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(00931)
++ "initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
++ getpid(), worker->s->hostname_ex);
++ }
++ if (rv == APR_SUCCESS) {
++ worker->local_status |= (PROXY_WORKER_INITIALIZED);
++ }
+ }
+ apr_global_mutex_unlock(proxy_mutex);
+
+ }
+ if (rv == APR_SUCCESS) {
+ worker->s->status |= (PROXY_WORKER_INITIALIZED);
+- worker->local_status |= (PROXY_WORKER_INITIALIZED);
+ }
+ return rv;
+ }
+@@ -2292,13 +2303,13 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
+ else {
+ /* create the new connection if the previous was destroyed */
+ if (!worker->cp->conn) {
+- connection_constructor((void **)conn, worker, worker->cp->pool);
++ rv = connection_constructor((void **)conn, worker, worker->cp->pool);
+ }
+ else {
+ *conn = worker->cp->conn;
+ worker->cp->conn = NULL;
++ rv = APR_SUCCESS;
+ }
+- rv = APR_SUCCESS;
+ }
+
+ if (rv != APR_SUCCESS) {
+@@ -2344,7 +2355,9 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
+ {
+ int server_port;
+ apr_status_t err = APR_SUCCESS;
++#if APR_HAS_THREADS
+ apr_status_t uerr = APR_SUCCESS;
++#endif
+ const char *uds_path;
+
+ /*
+@@ -2481,25 +2494,39 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
+ * we can reuse the address.
+ */
+ if (!worker->cp->addr) {
++#if APR_HAS_THREADS
+ if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
++#endif
+
+ /*
+- * Worker can have the single constant backend address.
+- * The single DNS lookup is used once per worker.
+- * If dynamic change is needed then set the addr to NULL
+- * inside dynamic config to force the lookup.
++ * Recheck addr after we got the lock. This may have changed
++ * while waiting for the lock.
+ */
+- err = apr_sockaddr_info_get(&(worker->cp->addr),
+- conn->hostname, APR_UNSPEC,
+- conn->port, 0,
+- worker->cp->pool);
++ if (!AP_VOLATILIZE_T(apr_sockaddr_t *, worker->cp->addr)) {
++
++ apr_sockaddr_t *addr;
++
++ /*
++ * Worker can have the single constant backend address.
++ * The single DNS lookup is used once per worker.
++ * If dynamic change is needed then set the addr to NULL
++ * inside dynamic config to force the lookup.
++ */
++ err = apr_sockaddr_info_get(&addr,
++ conn->hostname, APR_UNSPEC,
++ conn->port, 0,
++ worker->cp->dns_pool);
++ worker->cp->addr = addr;
++ }
+ conn->addr = worker->cp->addr;
++#if APR_HAS_THREADS
+ if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
+ }
++#endif
+ }
+ else {
+ conn->addr = worker->cp->addr;
+@@ -3422,7 +3449,9 @@ PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, server_rec
+ (*runtime)->cp = NULL;
+ (*runtime)->balancer = b;
+ (*runtime)->s = shm;
++#if APR_HAS_THREADS
+ (*runtime)->tmutex = NULL;
++#endif
+ rv = ap_proxy_initialize_worker(*runtime, s, conf->pool);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00966) "Cannot init worker");
diff --git a/SOURCES/httpd-2.4.37-r1877397.patch b/SOURCES/httpd-2.4.37-r1877397.patch
new file mode 100644
index 0000000..93aeb2e
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1877397.patch
@@ -0,0 +1,249 @@
+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
+index b286053..8b6c34f 100644
+--- a/modules/ssl/ssl_engine_init.c
++++ b/modules/ssl/ssl_engine_init.c
+@@ -824,6 +824,13 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+ SSL_CTX_set_keylog_callback(ctx, modssl_callback_keylog);
+ }
+ #endif
++
++#ifdef SSL_OP_NO_RENEGOTIATION
++ /* For server-side SSL_CTX, disable renegotiation by default.. */
++ if (!mctx->pkp) {
++ SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION);
++ }
++#endif
+
+ return APR_SUCCESS;
+ }
+@@ -845,6 +852,14 @@ static void ssl_init_ctx_session_cache(server_rec *s,
+ }
+ }
+
++#ifdef SSL_OP_NO_RENEGOTIATION
++/* OpenSSL-level renegotiation protection. */
++#define MODSSL_BLOCKS_RENEG (0)
++#else
++/* mod_ssl-level renegotiation protection. */
++#define MODSSL_BLOCKS_RENEG (1)
++#endif
++
+ static void ssl_init_ctx_callbacks(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+@@ -854,7 +869,13 @@ static void ssl_init_ctx_callbacks(server_rec *s,
+
+ SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
+
+- SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
++ /* The info callback is used for debug-level tracing. For OpenSSL
++ * versions where SSL_OP_NO_RENEGOTIATION is not available, the
++ * callback is also used to prevent use of client-initiated
++ * renegotiation. Enable it in either case. */
++ if (APLOGdebug(s) || MODSSL_BLOCKS_RENEG) {
++ SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
++ }
+
+ #ifdef HAVE_TLS_ALPN
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_callback_alpn_select, NULL);
+diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
+index 836bfdb..0958135 100644
+--- a/modules/ssl/ssl_engine_io.c
++++ b/modules/ssl/ssl_engine_io.c
+@@ -200,11 +200,13 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
+ apr_bucket *e;
+ int need_flush;
+
++#ifndef SSL_OP_NO_RENEGOTIATION
+ /* Abort early if the client has initiated a renegotiation. */
+ if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
+ outctx->rc = APR_ECONNABORTED;
+ return -1;
+ }
++#endif
+
+ /* when handshaking we'll have a small number of bytes.
+ * max size SSL will pass us here is about 16k.
+@@ -458,11 +460,13 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
+ if (!in)
+ return 0;
+
++#ifndef SSL_OP_NO_RENEGOTIATION
+ /* Abort early if the client has initiated a renegotiation. */
+ if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
+ inctx->rc = APR_ECONNABORTED;
+ return -1;
+ }
++#endif
+
+ BIO_clear_retry_flags(bio);
+
+diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
+index e217b9d..21f701f 100644
+--- a/modules/ssl/ssl_engine_kernel.c
++++ b/modules/ssl/ssl_engine_kernel.c
+@@ -992,7 +992,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
+
+ /* Toggle the renegotiation state to allow the new
+ * handshake to proceed. */
+- sslconn->reneg_state = RENEG_ALLOW;
++ modssl_set_reneg_state(sslconn, RENEG_ALLOW);
+
+ SSL_renegotiate(ssl);
+ SSL_do_handshake(ssl);
+@@ -1019,7 +1019,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
+ */
+ SSL_peek(ssl, peekbuf, 0);
+
+- sslconn->reneg_state = RENEG_REJECT;
++ modssl_set_reneg_state(sslconn, RENEG_REJECT);
+
+ if (!SSL_is_init_finished(ssl)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02261)
+@@ -1078,7 +1078,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
+ int vmode_inplace, vmode_needed;
+ int change_vmode = FALSE;
+- int old_state, n, rc;
++ int n, rc;
+
+ vmode_inplace = SSL_get_verify_mode(ssl);
+ vmode_needed = SSL_VERIFY_NONE;
+@@ -1180,8 +1180,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ return HTTP_FORBIDDEN;
+ }
+
+- old_state = sslconn->reneg_state;
+- sslconn->reneg_state = RENEG_ALLOW;
+ modssl_set_app_data2(ssl, r);
+
+ SSL_do_handshake(ssl);
+@@ -1191,7 +1189,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ */
+ SSL_peek(ssl, peekbuf, 0);
+
+- sslconn->reneg_state = old_state;
+ modssl_set_app_data2(ssl, NULL);
+
+ /*
+@@ -2271,8 +2268,8 @@ static void log_tracing_state(const SSL *ssl, conn_rec *c,
+ /*
+ * This callback function is executed while OpenSSL processes the SSL
+ * handshake and does SSL record layer stuff. It's used to trap
+- * client-initiated renegotiations, and for dumping everything to the
+- * log.
++ * client-initiated renegotiations (where SSL_OP_NO_RENEGOTIATION is
++ * not available), and for dumping everything to the log.
+ */
+ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ {
+@@ -2284,14 +2281,12 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ return;
+ }
+
+- /* With TLS 1.3 this callback may be called multiple times on the first
+- * negotiation, so the below logic to detect renegotiations can't work.
+- * Fortunately renegotiations are forbidden starting with TLS 1.3, and
+- * this is enforced by OpenSSL so there's nothing to be done here.
+- */
+-#if SSL_HAVE_PROTOCOL_TLSV1_3
+- if (SSL_version(ssl) < TLS1_3_VERSION)
+-#endif
++#ifndef SSL_OP_NO_RENEGOTIATION
++ /* With OpenSSL < 1.1.1 (implying TLS v1.2 or earlier), this
++ * callback is used to block client-initiated renegotiation. With
++ * TLSv1.3 it is unnecessary since renegotiation is forbidden at
++ * protocol level. Otherwise (TLSv1.2 with OpenSSL >=1.1.1),
++ * SSL_OP_NO_RENEGOTIATION is used to block renegotiation. */
+ {
+ SSLConnRec *sslconn;
+
+@@ -2316,6 +2311,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ sslconn->reneg_state = RENEG_REJECT;
+ }
+ }
++#endif
+
+ s = mySrvFromConn(c);
+ if (s && APLOGdebug(s)) {
+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
+index 2514407..f4e5ac9 100644
+--- a/modules/ssl/ssl_private.h
++++ b/modules/ssl/ssl_private.h
+@@ -508,6 +508,16 @@ typedef struct {
+ apr_time_t source_mtime;
+ } ssl_asn1_t;
+
++typedef enum {
++ RENEG_INIT = 0, /* Before initial handshake */
++ RENEG_REJECT, /* After initial handshake; any client-initiated
++ * renegotiation should be rejected */
++ RENEG_ALLOW, /* A server-initiated renegotiation is taking
++ * place (as dictated by configuration) */
++ RENEG_ABORT /* Renegotiation initiated by client, abort the
++ * connection */
++} modssl_reneg_state;
++
+ /**
+ * Define the mod_ssl per-module configuration structure
+ * (i.e. the global configuration for each httpd process)
+@@ -540,18 +550,13 @@ typedef struct {
+ NON_SSL_SET_ERROR_MSG /* Need to set the error message */
+ } non_ssl_request;
+
+- /* Track the handshake/renegotiation state for the connection so
+- * that all client-initiated renegotiations can be rejected, as a
+- * partial fix for CVE-2009-3555. */
+- enum {
+- RENEG_INIT = 0, /* Before initial handshake */
+- RENEG_REJECT, /* After initial handshake; any client-initiated
+- * renegotiation should be rejected */
+- RENEG_ALLOW, /* A server-initiated renegotiation is taking
+- * place (as dictated by configuration) */
+- RENEG_ABORT /* Renegotiation initiated by client, abort the
+- * connection */
+- } reneg_state;
++#ifndef SSL_OP_NO_RENEGOTIATION
++ /* For OpenSSL < 1.1.1, track the handshake/renegotiation state
++ * for the connection to block client-initiated renegotiations.
++ * For OpenSSL >=1.1.1, the SSL_OP_NO_RENEGOTIATION flag is used in
++ * the SSL * options state with equivalent effect. */
++ modssl_reneg_state reneg_state;
++#endif
+
+ server_rec *server;
+ SSLDirConfigRec *dc;
+@@ -1130,6 +1135,9 @@ int ssl_is_challenge(conn_rec *c, const char *servername,
+ * the configured ENGINE. */
+ int modssl_is_engine_id(const char *name);
+
++/* Set the renegotation state for connection. */
++void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state);
++
+ #endif /* SSL_PRIVATE_H */
+ /** @} */
+
+diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
+index 4fa089b..3413d83 100644
+--- a/modules/ssl/ssl_util_ssl.c
++++ b/modules/ssl/ssl_util_ssl.c
+@@ -504,3 +504,19 @@ char *modssl_SSL_SESSION_id2sz(IDCONST unsigned char *id, int idlen,
+
+ return str;
+ }
++
++void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state)
++{
++#ifdef SSL_OP_NO_RENEGOTIATION
++ switch (state) {
++ case RENEG_ALLOW:
++ SSL_clear_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
++ break;
++ default:
++ SSL_set_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
++ break;
++ }
++#else
++ sslconn->reneg_state = state;
++#endif
++}
diff --git a/SOURCES/httpd-2.4.37-r1878280.patch b/SOURCES/httpd-2.4.37-r1878280.patch
new file mode 100644
index 0000000..8393411
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1878280.patch
@@ -0,0 +1,47 @@
+From ced24e032ebe185a2d885fa309d6de47668ba31e Mon Sep 17 00:00:00 2001
+From: Yann Ylavic
+Date: Fri, 26 Jun 2020 10:21:19 +0000
+Subject: [PATCH] Merge r1878280 from trunk:
+
+mod_proxy_http: don't strip EOS when spooling request body to file.
+
+To prevent stream_reqbody() from sending the FILE and FLUSH bucket in separate
+brigades, and thus apr_file_setaside() to trigger if network congestion occurs
+with the backend, restore the EOS in spool_reqbody_cl() which was stripped
+when spooling the request body to a file.
+
+Until APR r1878279 is released (and installed by users), apr_file_setaside()
+on a temporary file (mktemp) will simply drop the file cleanup, leaking the
+fd and inode..
+
+This fixes BZ 64452.
+
+
+Submitted by: ylavic
+Reviewed by: ylavic, jorton, rpluem
+
+
+git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1879226 13f79535-47bb-0310-9956-ffa450edef68
+---
+ modules/proxy/mod_proxy_http.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
+index e94bf26d412..7a0f063f705 100644
+--- a/modules/proxy/mod_proxy_http.c
++++ b/modules/proxy/mod_proxy_http.c
+@@ -548,6 +548,14 @@ static int spool_reqbody_cl(proxy_http_req_t *req, apr_off_t *bytes_spooled)
+ e = apr_bucket_immortal_create(CRLF_ASCII, 2, bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(input_brigade, e);
+ }
++ if (tmpfile) {
++ /* We dropped metadata buckets when spooling to tmpfile,
++ * terminate with EOS for stream_reqbody() to flush the
++ * whole in one go.
++ */
++ e = apr_bucket_eos_create(bucket_alloc);
++ APR_BRIGADE_INSERT_TAIL(input_brigade, e);
++ }
+ return OK;
+ }
+
diff --git a/SOURCES/httpd-2.4.37-r1878890.patch b/SOURCES/httpd-2.4.37-r1878890.patch
new file mode 100644
index 0000000..0dcc4b0
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1878890.patch
@@ -0,0 +1,116 @@
+diff --git a/include/util_ldap.h b/include/util_ldap.h
+index f7cd736..f401e79 100644
+--- a/include/util_ldap.h
++++ b/include/util_ldap.h
+@@ -32,7 +32,6 @@
+ #if APR_MAJOR_VERSION < 2
+ /* The LDAP API is currently only present in APR 1.x */
+ #include "apr_ldap.h"
+-#include "apr_ldap_rebind.h"
+ #else
+ #define APR_HAS_LDAP 0
+ #endif
+diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c
+index 08f986c..eecb3f7 100644
+--- a/modules/ldap/util_ldap.c
++++ b/modules/ldap/util_ldap.c
+@@ -140,6 +140,38 @@ static int util_ldap_handler(request_rec *r)
+ return OK;
+ }
+
++/* For OpenLDAP with the 3-arg version of ldap_set_rebind_proc(), use
++ * a simpler rebind callback than the implementation in APR-util.
++ * Testing for API version >= 3001 appears safe although OpenLDAP
++ * 2.1.x (API version = 2004) also has the 3-arg API. */
++#if APR_HAS_OPENLDAP_LDAPSDK && defined(LDAP_API_VERSION) && LDAP_API_VERSION >= 3001
++
++#define uldap_rebind_init(p) APR_SUCCESS /* noop */
++
++static int uldap_rebind_proc(LDAP *ld, const char *url, ber_tag_t request,
++ ber_int_t msgid, void *params)
++{
++ util_ldap_connection_t *ldc = params;
++
++ return ldap_bind_s(ld, ldc->binddn, ldc->bindpw, LDAP_AUTH_SIMPLE);
++}
++
++static apr_status_t uldap_rebind_add(util_ldap_connection_t *ldc)
++{
++ ldap_set_rebind_proc(ldc->ldap, uldap_rebind_proc, ldc);
++ return APR_SUCCESS;
++}
++
++#else /* !APR_HAS_OPENLDAP_LDAPSDK */
++
++#define USE_APR_LDAP_REBIND
++#include
++
++#define uldap_rebind_init(p) apr_ldap_rebind_init(p)
++#define uldap_rebind_add(ldc) apr_ldap_rebind_add((ldc)->rebind_pool, \
++ (ldc)->ldap, (ldc)->binddn, \
++ (ldc)->bindpw)
++#endif
+
+
+ /* ------------------------------------------------------------------ */
+@@ -181,6 +213,13 @@ static apr_status_t uldap_connection_unbind(void *param)
+ util_ldap_connection_t *ldc = param;
+
+ if (ldc) {
++#ifdef USE_APR_LDAP_REBIND
++ /* forget the rebind info for this conn */
++ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
++ apr_pool_clear(ldc->rebind_pool);
++ }
++#endif
++
+ if (ldc->ldap) {
+ if (ldc->r) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, ldc->r, "LDC %pp unbind", ldc);
+@@ -189,12 +228,6 @@ static apr_status_t uldap_connection_unbind(void *param)
+ ldc->ldap = NULL;
+ }
+ ldc->bound = 0;
+-
+- /* forget the rebind info for this conn */
+- if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+- apr_ldap_rebind_remove(ldc->ldap);
+- apr_pool_clear(ldc->rebind_pool);
+- }
+ }
+
+ return APR_SUCCESS;
+@@ -330,7 +363,7 @@ static int uldap_connection_init(request_rec *r,
+
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ /* Now that we have an ldap struct, add it to the referral list for rebinds. */
+- rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);
++ rc = uldap_rebind_add(ldc);
+ if (rc != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, APLOGNO(01277)
+ "LDAP: Unable to add rebind cross reference entry. Out of memory?");
+@@ -855,6 +888,7 @@ static util_ldap_connection_t *
+ /* whether or not to keep this connection in the pool when it's returned */
+ l->keep = (st->connection_pool_ttl == 0) ? 0 : 1;
+
++#ifdef USE_APR_LDAP_REBIND
+ if (l->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ if (apr_pool_create(&(l->rebind_pool), l->pool) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01286)
+@@ -865,6 +899,7 @@ static util_ldap_connection_t *
+ return NULL;
+ }
+ }
++#endif
+
+ if (p) {
+ p->next = l;
+@@ -3051,7 +3086,7 @@ static int util_ldap_post_config(apr_pool_t *p, apr_pool_t *plog,
+ }
+
+ /* Initialize the rebind callback's cross reference list. */
+- apr_ldap_rebind_init (p);
++ (void) uldap_rebind_init(p);
+
+ #ifdef AP_LDAP_OPT_DEBUG
+ if (st->debug_level > 0) {
diff --git a/SOURCES/httpd-2.4.37-r1879224.patch b/SOURCES/httpd-2.4.37-r1879224.patch
new file mode 100644
index 0000000..2566d8f
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1879224.patch
@@ -0,0 +1,13 @@
+diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
+index c217a0d..d07d0ba 100644
+--- a/modules/ssl/ssl_engine_kernel.c
++++ b/modules/ssl/ssl_engine_kernel.c
+@@ -1947,7 +1947,7 @@ static void modssl_proxy_info_log(conn_rec *c,
+ *cert = info->x509; \
+ CRYPTO_add(&(*cert)->references, +1, CRYPTO_LOCK_X509); \
+ *pkey = info->x_pkey->dec_pkey; \
+- CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_X509_PKEY)
++ CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_EVP_PKEY)
+ #else
+ #define modssl_set_cert_info(info, cert, pkey) \
+ *cert = info->x509; \
diff --git a/SOURCES/httpd-2.4.37-r1881459.patch b/SOURCES/httpd-2.4.37-r1881459.patch
new file mode 100644
index 0000000..0f73c06
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-r1881459.patch
@@ -0,0 +1,16 @@
+--- a/modules/generators/cgi_common.h 2020/09/04 13:16:53 1881458
++++ b/modules/generators/cgi_common.h 2020/09/04 13:56:25 1881459
+@@ -259,6 +259,13 @@
+ if ((ret = ap_scan_script_header_err_brigade_ex(r, bb, sbuf,
+ APLOG_MODULE_INDEX)))
+ {
++ /* In the case of a timeout reading script output, clear
++ * the brigade to avoid a second attempt to read the
++ * output. */
++ if (ret == HTTP_GATEWAY_TIME_OUT) {
++ apr_brigade_cleanup(bb);
++ }
++
+ ret = log_script(r, conf, ret, logdata, sbuf, bb, script_err);
+
+ /*
diff --git a/SOURCES/httpd-2.4.37-ssl-proxy-chains.patch b/SOURCES/httpd-2.4.37-ssl-proxy-chains.patch
new file mode 100644
index 0000000..e7ec218
--- /dev/null
+++ b/SOURCES/httpd-2.4.37-ssl-proxy-chains.patch
@@ -0,0 +1,101 @@
+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
+index 8b6c34f..3587fb5 100644
+--- a/modules/ssl/ssl_engine_init.c
++++ b/modules/ssl/ssl_engine_init.c
+@@ -1609,6 +1609,10 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s,
+ STACK_OF(X509) *chain;
+ X509_STORE_CTX *sctx;
+ X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx);
++ int addl_chain = 0; /* non-zero if additional chain certs were
++ * added to store */
++
++ ap_assert(store != NULL); /* safe to assume always non-NULL? */
+
+ #if OPENSSL_VERSION_NUMBER >= 0x1010100fL
+ /* For OpenSSL >=1.1.1, turn on client cert support which is
+@@ -1653,20 +1657,28 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s,
+ }
+ }
+
+- if ((ncerts = sk_X509_INFO_num(sk)) <= 0) {
+- sk_X509_INFO_free(sk);
+- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206)
+- "no client certs found for SSL proxy");
+- return APR_SUCCESS;
+- }
+-
+ /* Check that all client certs have got certificates and private
+- * keys. */
+- for (n = 0; n < ncerts; n++) {
++ * keys. Note the number of certs in the stack may decrease
++ * during the loop. */
++ for (n = 0; n < sk_X509_INFO_num(sk); n++) {
+ X509_INFO *inf = sk_X509_INFO_value(sk, n);
++ int has_privkey = inf->x_pkey && inf->x_pkey->dec_pkey;
++
++ /* For a lone certificate in the file, trust it as a
++ * CA/intermediate certificate. */
++ if (inf->x509 && !has_privkey && !inf->enc_data) {
++ ssl_log_xerror(SSLLOG_MARK, APLOG_DEBUG, 0, ptemp, s, inf->x509,
++ APLOGNO(10261) "Trusting non-leaf certificate");
++ X509_STORE_add_cert(store, inf->x509); /* increments inf->x509 */
++ /* Delete from the stack and iterate again. */
++ X509_INFO_free(inf);
++ sk_X509_INFO_delete(sk, n);
++ n--;
++ addl_chain = 1;
++ continue;
++ }
+
+- if (!inf->x509 || !inf->x_pkey || !inf->x_pkey->dec_pkey ||
+- inf->enc_data) {
++ if (!has_privkey || inf->enc_data) {
+ sk_X509_INFO_free(sk);
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252)
+ "incomplete client cert configured for SSL proxy "
+@@ -1683,13 +1695,21 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s,
+ }
+ }
+
++ if ((ncerts = sk_X509_INFO_num(sk)) <= 0) {
++ sk_X509_INFO_free(sk);
++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206)
++ "no client certs found for SSL proxy");
++ return APR_SUCCESS;
++ }
++
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02207)
+ "loaded %d client certs for SSL proxy",
+ ncerts);
+ pkp->certs = sk;
+
+-
+- if (!pkp->ca_cert_file || !store) {
++ /* If any chain certs are configured, build the ->ca_certs chains
++ * corresponding to the loaded keypairs. */
++ if (!pkp->ca_cert_file && !addl_chain) {
+ return APR_SUCCESS;
+ }
+
+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
+index 2a08d1c..8055200 100644
+--- a/modules/ssl/ssl_private.h
++++ b/modules/ssl/ssl_private.h
+@@ -655,10 +655,13 @@ typedef struct {
+ const char *cert_file;
+ const char *cert_path;
+ const char *ca_cert_file;
+- STACK_OF(X509_INFO) *certs; /* Contains End Entity certs */
+- STACK_OF(X509) **ca_certs; /* Contains ONLY chain certs for
+- * each item in certs.
+- * (ptr to array of ptrs) */
++ /* certs is a stack of configured cert, key pairs. */
++ STACK_OF(X509_INFO) *certs;
++ /* ca_certs contains ONLY chain certs for each item in certs.
++ * ca_certs[n] is a pointer to the (STACK_OF(X509) *) stack which
++ * holds the cert chain for the 'n'th cert in the certs stack, or
++ * NULL if no chain is configured. */
++ STACK_OF(X509) **ca_certs;
+ } modssl_pk_proxy_t;
+
+ /** stuff related to authentication that can also be per-dir */
diff --git a/SOURCES/index.html b/SOURCES/index.html
deleted file mode 100644
index 06ad3fc..0000000
--- a/SOURCES/index.html
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
- Test Page for the Apache HTTP Server on Red Hat Enterprise Linux
-
-
-
-
-
- Red Hat Enterprise Linux Test Page
-
-
-
-
This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the Apache HTTP server installed at this site is working properly.
-
-
-
-
-
-
If you are a member of the general public:
-
-
The fact that you are seeing this page indicates that the website you just visited is either experiencing problems, or is undergoing routine maintenance.
-
-
If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name "webmaster" and directed to the website's domain should reach the appropriate person.
-
-
For example, if you experienced problems while visiting www.example.com, you should send e-mail to "webmaster@example.com".
-
-
For information on Red Hat Enterprise Linux, please visit the Red Hat, Inc. website. The documentation for Red Hat Enterprise Linux is available on the Red Hat, Inc. website.
-
-
-
-
-
If you are the website administrator:
-
-
You may now add content to the directory /var/www/html/. Note that until you do so, people visiting your website will see this page, and not your content. To prevent this page from ever being used, follow the instructions in the file /etc/httpd/conf.d/welcome.conf.
-
-
You are free to use the image below on web sites powered by the Apache HTTP Server:
-
-
-
-
-
-
-
-
diff --git a/SOURCES/welcome.conf b/SOURCES/welcome.conf
index 5d1e452..5158e8b 100644
--- a/SOURCES/welcome.conf
+++ b/SOURCES/welcome.conf
@@ -16,3 +16,4 @@
Alias /.noindex.html /usr/share/httpd/noindex/index.html
+Alias /poweredby.png /usr/share/httpd/icons/apache_pb2.png
\ No newline at end of file
diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec
index 361b2ad..584035e 100644
--- a/SPECS/httpd.spec
+++ b/SPECS/httpd.spec
@@ -13,10 +13,9 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.37
-Release: 30%{?dist}
+Release: 39%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
-Source1: index.html
Source2: httpd.logrotate
Source3: instance.conf
Source4: httpd-ssl-pass-dialog
@@ -96,6 +95,13 @@ Patch35: httpd-2.4.37-sslkeylogfile-support.patch
Patch36: httpd-2.4.37-session-expiry-updt-int.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1209162
Patch37: httpd-2.4.37-logjournal.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1869576
+Patch38: httpd-2.4.37-pr37355.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1896176
+Patch39: httpd-2.4.37-proxy-ws-idle-timeout.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1883648
+Patch40: httpd-2.4.37-ssl-proxy-chains.patch
+
# Bug fixes
# https://bugzilla.redhat.com/show_bug.cgi?id=1397243
Patch61: httpd-2.4.35-r1738878.patch
@@ -128,7 +134,22 @@ Patch75: httpd-2.4.37-r1870095+.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1771847
Patch76: httpd-2.4.37-proxy-continue.patch
Patch77: httpd-2.4.37-balancer-failover.patch
-
+# https://bugzilla.redhat.com/show_bug.cgi?id=1875844
+Patch78: httpd-2.4.37-r1881459.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1891829
+Patch79: httpd-2.4.37-r1864000.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1868608
+Patch80: httpd-2.4.37-r1872790.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1861380
+Patch81: httpd-2.4.37-r1879224.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1680118
+Patch82: httpd-2.4.37-r1877397.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1847585
+Patch83: httpd-2.4.37-r1878890.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1918741
+Patch84: httpd-2.4.37-r1878280.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1891594
+Patch85: httpd-2.4.37-htcacheclean-dont-break.patch
# Security fixes
Patch200: httpd-2.4.37-r1851471.patch
@@ -154,6 +175,10 @@ Patch207: httpd-2.4.37-CVE-2019-10092.patch
Patch208: httpd-2.4.37-CVE-2019-10097.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1820772
Patch209: httpd-2.4.37-CVE-2020-1934.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1668493
+Patch210: httpd-2.4.37-CVE-2018-17199.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1866563
+Patch211: httpd-2.4.37-CVE-2020-11984.patch
License: ASL 2.0
Group: System Environment/Daemons
@@ -162,7 +187,8 @@ BuildRequires: autoconf, perl-interpreter, perl-generators, pkgconfig, findutils
BuildRequires: zlib-devel, libselinux-devel, lua-devel, brotli-devel
BuildRequires: apr-devel >= 1.5.0, apr-util-devel >= 1.5.0, pcre-devel >= 5.0
BuildRequires: systemd-devel
-Requires: /etc/mime.types, system-logos-httpd
+# web server testpage added to redhat-logos in 82.0 (rhbz1896319)
+Requires: /etc/mime.types, system-logos-httpd >= 82.0
Obsoletes: httpd-suexec
Provides: webserver
Provides: mod_dav = %{version}-%{release}, httpd-suexec = %{version}-%{release}
@@ -299,6 +325,9 @@ interface for storing and accessing per-user session data.
%patch35 -p1 -b .sslkeylogfile-support
%patch36 -p1 -b .session-expiry
%patch37 -p1 -b .logjournal
+%patch38 -p1 -b .pr37355
+%patch39 -p1 -b .proxy-ws-idle-timeout
+%patch40 -p1 -b .ssl-proxy-chains
%patch61 -p1 -b .r1738878
%patch62 -p1 -b .r1633085
@@ -315,7 +344,14 @@ interface for storing and accessing per-user session data.
%patch75 -p1 -b .r1870095+
%patch76 -p1 -b .proxy-continue
%patch77 -p1 -b .balancer-failover
-
+%patch78 -p1 -b .r1881459
+%patch79 -p1 -b .r1864000
+%patch80 -p1 -b .r1872790
+%patch81 -p1 -b .r1879224
+%patch82 -p1 -b .r1877397
+%patch83 -p1 -b .r1878890
+%patch84 -p1 -b .r1878280
+%patch85 -p1 -b .htcacheclean-dont-break
%patch200 -p1 -b .r1851471
%patch201 -p1 -b .CVE-2019-0211
@@ -327,6 +363,8 @@ interface for storing and accessing per-user session data.
%patch207 -p1 -b .CVE-2019-10092
%patch208 -p1 -b .CVE-2019-10097
%patch209 -p1 -b .CVE-2020-1934
+%patch210 -p1 -b .CVE-2018-17199
+%patch211 -p1 -b .CVE-2020-11984
# Patch in the vendor string
sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h
@@ -530,8 +568,8 @@ EOF
# Handle contentdir
mkdir $RPM_BUILD_ROOT%{contentdir}/noindex
-install -m 644 -p $RPM_SOURCE_DIR/index.html \
- $RPM_BUILD_ROOT%{contentdir}/noindex/index.html
+ln -s ../../testpage/index.html \
+ $RPM_BUILD_ROOT%{contentdir}/noindex/index.html
rm -rf %{contentdir}/htdocs
# remove manual sources
@@ -829,8 +867,43 @@ rm -rf $RPM_BUILD_ROOT
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
-* Tue Jul 28 2020 CentOS Sources - 2.4.37-30.el8.centos
-- Apply debranding changes
+* Tue Jan 26 2021 Artem Egorenkov - 2.4.37-39
+- prevent htcacheclean from while break when first file processed
+
+* Tue Jan 26 2021 Lubos Uhliarik - 2.4.37-38
+- Resolves: #1918741 - Thousands of /tmp/modproxy.tmp.* files created by apache
+
+* Wed Dec 09 2020 Lubos Uhliarik - 2.4.37-37
+- Resolves: #1883648 - [RFE] Update httpd directive SSLProxyMachineCertificateFile
+ to be able to handle certs without matching private key
+
+* Mon Nov 30 2020 Lubos Uhliarik - 2.4.37-36
+- Resolves: #1896176 - [RFE] ProxyWebsocketIdleTimeout from httpd
+ mod_proxy_wstunnel
+- Resolves: #1847585 - mod_ldap: High CPU usage at apr_ldap_rebind_remove()
+
+* Wed Nov 11 2020 Lubos Uhliarik - 2.4.37-35
+- Resolves: #1651376 - centralizing default index.html for httpd
+
+* Fri Nov 06 2020 Lubos Uhliarik - 2.4.37-33
+- Resolves: #1868608 - Intermittent Segfault in Apache httpd due to pool
+ concurrency issues
+- Resolves: #1861380 - httpd/mod_proxy_http/mod_ssl aborted when sending
+ a client cert to backend server
+- Resolves: #1680118 - unorderly connection close when client attempts
+ renegotiation
+
+* Thu Oct 29 2020 Lubos Uhliarik - 2.4.37-31
+- Resolves: #1677590 - CVE-2018-17199 httpd:2.4/httpd: mod_session_cookie does
+ not respect expiry time
+- Resolves: #1869075 - CVE-2020-11984 httpd:2.4/httpd: mod_proxy_uswgi buffer
+ overflow
+- Resolves: #1872828 - httpd: typo in htpasswd, contained in httpd-tools package
+- Resolves: #1869576 - httpd : mod_proxy should allow to specify
+ Proxy-Authorization in ProxyRemote directive
+- Resolves: #1875844 - mod_cgid takes CGIDScriptTimeout x 2 seconds for timeout
+- Resolves: #1891829 - mod_proxy_hcheck Doesn't perform checks when in
+ a balancer
* Mon Jun 15 2020 Joe Orton - 2.4.37-30
- Resolves: #1209162 - support logging to journald from CustomLog