update to 2.4.43
This commit is contained in:
parent
2ffb308702
commit
a1284fac8a
@ -55,6 +55,7 @@ LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
|
||||
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
|
||||
LoadModule socache_dbm_module modules/mod_socache_dbm.so
|
||||
LoadModule socache_memcache_module modules/mod_socache_memcache.so
|
||||
LoadModule socache_memcache_module modules/mod_socache_redis.so
|
||||
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
|
||||
LoadModule status_module modules/mod_status.so
|
||||
LoadModule substitute_module modules/mod_substitute.so
|
||||
|
||||
@ -1,460 +0,0 @@
|
||||
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
|
||||
index 814d2a96..a1b31d2b 100644
|
||||
--- a/modules/http2/h2_session.c
|
||||
+++ b/modules/http2/h2_session.c
|
||||
@@ -235,6 +235,7 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags,
|
||||
stream = h2_session_stream_get(session, stream_id);
|
||||
if (stream) {
|
||||
status = h2_stream_recv_DATA(stream, flags, data, len);
|
||||
+ dispatch_event(session, H2_SESSION_EV_STREAM_CHANGE, 0, "stream data rcvd");
|
||||
}
|
||||
else {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03064)
|
||||
@@ -317,9 +318,9 @@ static int on_header_cb(nghttp2_session *ngh2, const nghttp2_frame *frame,
|
||||
}
|
||||
|
||||
/**
|
||||
- * nghttp2 session has received a complete frame. Most, it uses
|
||||
- * for processing of internal state. HEADER and DATA frames however
|
||||
- * we need to handle ourself.
|
||||
+ * nghttp2 session has received a complete frame. Most are used by nghttp2
|
||||
+ * for processing of internal state. Some, like HEADER and DATA frames,
|
||||
+ * we need to act on.
|
||||
*/
|
||||
static int on_frame_recv_cb(nghttp2_session *ng2s,
|
||||
const nghttp2_frame *frame,
|
||||
@@ -378,6 +379,9 @@ static int on_frame_recv_cb(nghttp2_session *ng2s,
|
||||
"h2_stream(%ld-%d): WINDOW_UPDATE incr=%d",
|
||||
session->id, (int)frame->hd.stream_id,
|
||||
frame->window_update.window_size_increment);
|
||||
+ if (nghttp2_session_want_write(session->ngh2)) {
|
||||
+ dispatch_event(session, H2_SESSION_EV_FRAME_RCVD, 0, "window update");
|
||||
+ }
|
||||
break;
|
||||
case NGHTTP2_RST_STREAM:
|
||||
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03067)
|
||||
@@ -404,6 +408,12 @@ static int on_frame_recv_cb(nghttp2_session *ng2s,
|
||||
frame->goaway.error_code, NULL);
|
||||
}
|
||||
break;
|
||||
+ case NGHTTP2_SETTINGS:
|
||||
+ if (APLOGctrace2(session->c)) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
|
||||
+ H2_SSSN_MSG(session, "SETTINGS, len=%ld"), (long)frame->hd.length);
|
||||
+ }
|
||||
+ break;
|
||||
default:
|
||||
if (APLOGctrace2(session->c)) {
|
||||
char buffer[256];
|
||||
@@ -415,7 +425,40 @@ static int on_frame_recv_cb(nghttp2_session *ng2s,
|
||||
}
|
||||
break;
|
||||
}
|
||||
- return (APR_SUCCESS == rv)? 0 : NGHTTP2_ERR_PROTO;
|
||||
+
|
||||
+ if (session->state == H2_SESSION_ST_IDLE) {
|
||||
+ /* We received a frame, but session is in state IDLE. That means the frame
|
||||
+ * did not really progress any of the (possibly) open streams. It was a meta
|
||||
+ * frame, e.g. SETTINGS/WINDOW_UPDATE/unknown/etc.
|
||||
+ * Remember: IDLE means we cannot send because either there are no streams open or
|
||||
+ * all open streams are blocked on exhausted WINDOWs for outgoing data.
|
||||
+ * The more frames we receive that do not change this, the less interested we
|
||||
+ * become in serving this connection. This is expressed in increasing "idle_delays".
|
||||
+ * Eventually, the connection will timeout and we'll close it. */
|
||||
+ session->idle_frames = H2MIN(session->idle_frames + 1, session->frames_received);
|
||||
+ ap_log_cerror( APLOG_MARK, APLOG_TRACE2, 0, session->c,
|
||||
+ H2_SSSN_MSG(session, "session has %ld idle frames"),
|
||||
+ (long)session->idle_frames);
|
||||
+ if (session->idle_frames > 10) {
|
||||
+ apr_size_t busy_frames = H2MAX(session->frames_received - session->idle_frames, 1);
|
||||
+ int idle_ratio = (int)(session->idle_frames / busy_frames);
|
||||
+ if (idle_ratio > 100) {
|
||||
+ session->idle_delay = apr_time_from_msec(H2MIN(1000, idle_ratio));
|
||||
+ }
|
||||
+ else if (idle_ratio > 10) {
|
||||
+ session->idle_delay = apr_time_from_msec(10);
|
||||
+ }
|
||||
+ else if (idle_ratio > 1) {
|
||||
+ session->idle_delay = apr_time_from_msec(1);
|
||||
+ }
|
||||
+ else {
|
||||
+ session->idle_delay = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (APR_SUCCESS != rv) return NGHTTP2_ERR_PROTO;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int h2_session_continue_data(h2_session *session) {
|
||||
@@ -1603,23 +1646,57 @@ static void update_child_status(h2_session *session, int status, const char *msg
|
||||
|
||||
static void transit(h2_session *session, const char *action, h2_session_state nstate)
|
||||
{
|
||||
+ apr_time_t timeout;
|
||||
+ int ostate, loglvl;
|
||||
+ const char *s;
|
||||
+
|
||||
if (session->state != nstate) {
|
||||
- int loglvl = APLOG_DEBUG;
|
||||
- if ((session->state == H2_SESSION_ST_BUSY && nstate == H2_SESSION_ST_WAIT)
|
||||
- || (session->state == H2_SESSION_ST_WAIT && nstate == H2_SESSION_ST_BUSY)){
|
||||
+ ostate = session->state;
|
||||
+ session->state = nstate;
|
||||
+
|
||||
+ loglvl = APLOG_DEBUG;
|
||||
+ if ((ostate == H2_SESSION_ST_BUSY && nstate == H2_SESSION_ST_WAIT)
|
||||
+ || (ostate == H2_SESSION_ST_WAIT && nstate == H2_SESSION_ST_BUSY)){
|
||||
loglvl = APLOG_TRACE1;
|
||||
}
|
||||
ap_log_cerror(APLOG_MARK, loglvl, 0, session->c,
|
||||
H2_SSSN_LOG(APLOGNO(03078), session,
|
||||
"transit [%s] -- %s --> [%s]"),
|
||||
- h2_session_state_str(session->state), action,
|
||||
+ h2_session_state_str(ostate), action,
|
||||
h2_session_state_str(nstate));
|
||||
- session->state = nstate;
|
||||
+
|
||||
switch (session->state) {
|
||||
case H2_SESSION_ST_IDLE:
|
||||
- update_child_status(session, (session->open_streams == 0?
|
||||
- SERVER_BUSY_KEEPALIVE
|
||||
- : SERVER_BUSY_READ), "idle");
|
||||
+ if (!session->remote.emitted_count) {
|
||||
+ /* on fresh connections, with async mpm, do not return
|
||||
+ * to mpm for a second. This gives the first request a better
|
||||
+ * chance to arrive (und connection leaving IDLE state).
|
||||
+ * If we return to mpm right away, this connection has the
|
||||
+ * same chance of being cleaned up by the mpm as connections
|
||||
+ * that already served requests - not fair. */
|
||||
+ session->idle_sync_until = apr_time_now() + apr_time_from_sec(1);
|
||||
+ s = "timeout";
|
||||
+ timeout = H2MAX(session->s->timeout, session->s->keep_alive_timeout);
|
||||
+ update_child_status(session, SERVER_BUSY_READ, "idle");
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
+ H2_SSSN_LOG("", session, "enter idle, timeout = %d sec"),
|
||||
+ (int)apr_time_sec(H2MAX(session->s->timeout, session->s->keep_alive_timeout)));
|
||||
+ }
|
||||
+ else if (session->open_streams) {
|
||||
+ s = "timeout";
|
||||
+ timeout = session->s->keep_alive_timeout;
|
||||
+ update_child_status(session, SERVER_BUSY_KEEPALIVE, "idle");
|
||||
+ }
|
||||
+ else {
|
||||
+ /* normal keepalive setup */
|
||||
+ s = "keepalive";
|
||||
+ timeout = session->s->keep_alive_timeout;
|
||||
+ update_child_status(session, SERVER_BUSY_KEEPALIVE, "idle");
|
||||
+ }
|
||||
+ session->idle_until = apr_time_now() + timeout;
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
+ H2_SSSN_LOG("", session, "enter idle, %s = %d sec"),
|
||||
+ s, (int)apr_time_sec(timeout));
|
||||
break;
|
||||
case H2_SESSION_ST_DONE:
|
||||
update_child_status(session, SERVER_CLOSING, "done");
|
||||
@@ -1726,8 +1803,6 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg)
|
||||
* This means we only wait for WINDOW_UPDATE from the
|
||||
* client and can block on READ. */
|
||||
transit(session, "no io (flow wait)", H2_SESSION_ST_IDLE);
|
||||
- session->idle_until = apr_time_now() + session->s->timeout;
|
||||
- session->keep_sync_until = session->idle_until;
|
||||
/* Make sure we have flushed all previously written output
|
||||
* so that the client will react. */
|
||||
if (h2_conn_io_flush(&session->io) != APR_SUCCESS) {
|
||||
@@ -1738,12 +1813,7 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg)
|
||||
}
|
||||
else if (session->local.accepting) {
|
||||
/* When we have no streams, but accept new, switch to idle */
|
||||
- apr_time_t now = apr_time_now();
|
||||
transit(session, "no io (keepalive)", H2_SESSION_ST_IDLE);
|
||||
- session->idle_until = (session->remote.emitted_count?
|
||||
- session->s->keep_alive_timeout :
|
||||
- session->s->timeout) + now;
|
||||
- session->keep_sync_until = now + apr_time_from_sec(1);
|
||||
}
|
||||
else {
|
||||
/* We are no longer accepting new streams and there are
|
||||
@@ -1758,12 +1828,25 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg)
|
||||
}
|
||||
}
|
||||
|
||||
-static void h2_session_ev_data_read(h2_session *session, int arg, const char *msg)
|
||||
+static void h2_session_ev_frame_rcvd(h2_session *session, int arg, const char *msg)
|
||||
+{
|
||||
+ switch (session->state) {
|
||||
+ case H2_SESSION_ST_IDLE:
|
||||
+ case H2_SESSION_ST_WAIT:
|
||||
+ transit(session, "frame received", H2_SESSION_ST_BUSY);
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* nop */
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void h2_session_ev_stream_change(h2_session *session, int arg, const char *msg)
|
||||
{
|
||||
switch (session->state) {
|
||||
case H2_SESSION_ST_IDLE:
|
||||
case H2_SESSION_ST_WAIT:
|
||||
- transit(session, "data read", H2_SESSION_ST_BUSY);
|
||||
+ transit(session, "stream change", H2_SESSION_ST_BUSY);
|
||||
break;
|
||||
default:
|
||||
/* nop */
|
||||
@@ -1803,16 +1886,6 @@ static void h2_session_ev_pre_close(h2_session *session, int arg, const char *ms
|
||||
static void ev_stream_open(h2_session *session, h2_stream *stream)
|
||||
{
|
||||
h2_iq_append(session->in_process, stream->id);
|
||||
- switch (session->state) {
|
||||
- case H2_SESSION_ST_IDLE:
|
||||
- if (session->open_streams == 1) {
|
||||
- /* enter timeout, since we have a stream again */
|
||||
- session->idle_until = (session->s->timeout + apr_time_now());
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
}
|
||||
|
||||
static void ev_stream_closed(h2_session *session, h2_stream *stream)
|
||||
@@ -1825,11 +1898,6 @@ static void ev_stream_closed(h2_session *session, h2_stream *stream)
|
||||
}
|
||||
switch (session->state) {
|
||||
case H2_SESSION_ST_IDLE:
|
||||
- if (session->open_streams == 0) {
|
||||
- /* enter keepalive timeout, since we no longer have streams */
|
||||
- session->idle_until = (session->s->keep_alive_timeout
|
||||
- + apr_time_now());
|
||||
- }
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1887,6 +1955,7 @@ static void on_stream_state_enter(void *ctx, h2_stream *stream)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
+ dispatch_event(session, H2_SESSION_EV_STREAM_CHANGE, 0, "stream state change");
|
||||
}
|
||||
|
||||
static void on_stream_event(void *ctx, h2_stream *stream,
|
||||
@@ -1945,8 +2014,8 @@ static void dispatch_event(h2_session *session, h2_session_event_t ev,
|
||||
case H2_SESSION_EV_NO_IO:
|
||||
h2_session_ev_no_io(session, arg, msg);
|
||||
break;
|
||||
- case H2_SESSION_EV_DATA_READ:
|
||||
- h2_session_ev_data_read(session, arg, msg);
|
||||
+ case H2_SESSION_EV_FRAME_RCVD:
|
||||
+ h2_session_ev_frame_rcvd(session, arg, msg);
|
||||
break;
|
||||
case H2_SESSION_EV_NGH2_DONE:
|
||||
h2_session_ev_ngh2_done(session, arg, msg);
|
||||
@@ -1957,6 +2026,9 @@ static void dispatch_event(h2_session *session, h2_session_event_t ev,
|
||||
case H2_SESSION_EV_PRE_CLOSE:
|
||||
h2_session_ev_pre_close(session, arg, msg);
|
||||
break;
|
||||
+ case H2_SESSION_EV_STREAM_CHANGE:
|
||||
+ h2_session_ev_stream_change(session, arg, msg);
|
||||
+ break;
|
||||
default:
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
H2_SSSN_MSG(session, "unknown event %d"), ev);
|
||||
@@ -1990,13 +2062,15 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
apr_status_t status = APR_SUCCESS;
|
||||
conn_rec *c = session->c;
|
||||
int rv, mpm_state, trace = APLOGctrace3(c);
|
||||
-
|
||||
+ apr_time_t now;
|
||||
+
|
||||
if (trace) {
|
||||
ap_log_cerror( APLOG_MARK, APLOG_TRACE3, status, c,
|
||||
H2_SSSN_MSG(session, "process start, async=%d"), async);
|
||||
}
|
||||
|
||||
while (session->state != H2_SESSION_ST_DONE) {
|
||||
+ now = apr_time_now();
|
||||
session->have_read = session->have_written = 0;
|
||||
|
||||
if (session->local.accepting
|
||||
@@ -2034,39 +2108,42 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
break;
|
||||
|
||||
case H2_SESSION_ST_IDLE:
|
||||
- /* We trust our connection into the default timeout/keepalive
|
||||
- * handling of the core filters/mpm iff:
|
||||
- * - keep_sync_until is not set
|
||||
- * - we have an async mpm
|
||||
- * - we have no open streams to process
|
||||
- * - we are not sitting on a Upgrade: request
|
||||
- * - we already have seen at least one request
|
||||
- */
|
||||
- if (!session->keep_sync_until && async && !session->open_streams
|
||||
- && !session->r && session->remote.emitted_count) {
|
||||
+ if (session->idle_until && (apr_time_now() + session->idle_delay) > session->idle_until) {
|
||||
+ ap_log_cerror( APLOG_MARK, APLOG_TRACE1, status, c,
|
||||
+ H2_SSSN_MSG(session, "idle, timeout reached, closing"));
|
||||
+ if (session->idle_delay) {
|
||||
+ apr_table_setn(session->c->notes, "short-lingering-close", "1");
|
||||
+ }
|
||||
+ dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, "timeout");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (session->idle_delay) {
|
||||
+ /* we are less interested in spending time on this connection */
|
||||
+ ap_log_cerror( APLOG_MARK, APLOG_TRACE2, status, c,
|
||||
+ H2_SSSN_MSG(session, "session is idle (%ld ms), idle wait %ld sec left"),
|
||||
+ (long)apr_time_as_msec(session->idle_delay),
|
||||
+ (long)apr_time_sec(session->idle_until - now));
|
||||
+ apr_sleep(session->idle_delay);
|
||||
+ session->idle_delay = 0;
|
||||
+ }
|
||||
+
|
||||
+ h2_conn_io_flush(&session->io);
|
||||
+ if (async && !session->r && (now > session->idle_sync_until)) {
|
||||
if (trace) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, c,
|
||||
H2_SSSN_MSG(session,
|
||||
"nonblock read, %d streams open"),
|
||||
session->open_streams);
|
||||
}
|
||||
- h2_conn_io_flush(&session->io);
|
||||
status = h2_session_read(session, 0);
|
||||
|
||||
if (status == APR_SUCCESS) {
|
||||
session->have_read = 1;
|
||||
- dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL);
|
||||
}
|
||||
- else if (APR_STATUS_IS_EAGAIN(status)
|
||||
- || APR_STATUS_IS_TIMEUP(status)) {
|
||||
- if (apr_time_now() > session->idle_until) {
|
||||
- dispatch_event(session,
|
||||
- H2_SESSION_EV_CONN_TIMEOUT, 0, NULL);
|
||||
- }
|
||||
- else {
|
||||
- status = APR_EAGAIN;
|
||||
- goto out;
|
||||
- }
|
||||
+ else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) {
|
||||
+ status = APR_EAGAIN;
|
||||
+ goto out;
|
||||
}
|
||||
else {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c,
|
||||
@@ -2078,7 +2155,6 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
}
|
||||
else {
|
||||
/* make certain, we send everything before we idle */
|
||||
- h2_conn_io_flush(&session->io);
|
||||
if (trace) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, c,
|
||||
H2_SSSN_MSG(session,
|
||||
@@ -2090,7 +2166,6 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
*/
|
||||
status = h2_mplx_idle(session->mplx);
|
||||
if (status == APR_EAGAIN) {
|
||||
- dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL);
|
||||
break;
|
||||
}
|
||||
else if (status != APR_SUCCESS) {
|
||||
@@ -2101,33 +2176,11 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
status = h2_session_read(session, 1);
|
||||
if (status == APR_SUCCESS) {
|
||||
session->have_read = 1;
|
||||
- dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL);
|
||||
}
|
||||
else if (status == APR_EAGAIN) {
|
||||
/* nothing to read */
|
||||
}
|
||||
else if (APR_STATUS_IS_TIMEUP(status)) {
|
||||
- apr_time_t now = apr_time_now();
|
||||
- if (now > session->keep_sync_until) {
|
||||
- /* if we are on an async mpm, now is the time that
|
||||
- * we may dare to pass control to it. */
|
||||
- session->keep_sync_until = 0;
|
||||
- }
|
||||
- if (now > session->idle_until) {
|
||||
- if (trace) {
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, c,
|
||||
- H2_SSSN_MSG(session,
|
||||
- "keepalive timeout"));
|
||||
- }
|
||||
- dispatch_event(session,
|
||||
- H2_SESSION_EV_CONN_TIMEOUT, 0, "timeout");
|
||||
- }
|
||||
- else if (trace) {
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, c,
|
||||
- H2_SSSN_MSG(session,
|
||||
- "keepalive, %f sec left"),
|
||||
- (session->idle_until - now) / 1000000.0f);
|
||||
- }
|
||||
/* continue reading handling */
|
||||
}
|
||||
else if (APR_STATUS_IS_ECONNABORTED(status)
|
||||
@@ -2145,6 +2198,18 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, "error");
|
||||
}
|
||||
}
|
||||
+ if (nghttp2_session_want_write(session->ngh2)) {
|
||||
+ ap_update_child_status(session->c->sbh, SERVER_BUSY_WRITE, NULL);
|
||||
+ status = h2_session_send(session);
|
||||
+ if (status == APR_SUCCESS) {
|
||||
+ status = h2_conn_io_flush(&session->io);
|
||||
+ }
|
||||
+ if (status != APR_SUCCESS) {
|
||||
+ dispatch_event(session, H2_SESSION_EV_CONN_ERROR,
|
||||
+ H2_ERR_INTERNAL_ERROR, "writing");
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
break;
|
||||
|
||||
case H2_SESSION_ST_BUSY:
|
||||
@@ -2154,7 +2219,6 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
status = h2_session_read(session, 0);
|
||||
if (status == APR_SUCCESS) {
|
||||
session->have_read = 1;
|
||||
- dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL);
|
||||
}
|
||||
else if (status == APR_EAGAIN) {
|
||||
/* nothing to read */
|
||||
@@ -2218,7 +2282,7 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
session->iowait);
|
||||
if (status == APR_SUCCESS) {
|
||||
session->wait_us = 0;
|
||||
- dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL);
|
||||
+ dispatch_event(session, H2_SESSION_EV_STREAM_CHANGE, 0, NULL);
|
||||
}
|
||||
else if (APR_STATUS_IS_TIMEUP(status)) {
|
||||
/* go back to checking all inputs again */
|
||||
diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h
|
||||
index 486938b0..df2a8624 100644
|
||||
--- a/modules/http2/h2_session.h
|
||||
+++ b/modules/http2/h2_session.h
|
||||
@@ -66,10 +66,11 @@ typedef enum {
|
||||
H2_SESSION_EV_PROTO_ERROR, /* protocol error */
|
||||
H2_SESSION_EV_CONN_TIMEOUT, /* connection timeout */
|
||||
H2_SESSION_EV_NO_IO, /* nothing has been read or written */
|
||||
- H2_SESSION_EV_DATA_READ, /* connection data has been read */
|
||||
+ H2_SESSION_EV_FRAME_RCVD, /* a frame has been received */
|
||||
H2_SESSION_EV_NGH2_DONE, /* nghttp2 wants neither read nor write anything */
|
||||
H2_SESSION_EV_MPM_STOPPING, /* the process is stopping */
|
||||
H2_SESSION_EV_PRE_CLOSE, /* connection will close after this */
|
||||
+ H2_SESSION_EV_STREAM_CHANGE, /* a stream (state/input/output) changed */
|
||||
} h2_session_event_t;
|
||||
|
||||
typedef struct h2_session {
|
||||
@@ -118,7 +119,9 @@ typedef struct h2_session {
|
||||
apr_size_t max_stream_mem; /* max buffer memory for a single stream */
|
||||
|
||||
apr_time_t idle_until; /* Time we shut down due to sheer boredom */
|
||||
- apr_time_t keep_sync_until; /* Time we sync wait until passing to async mpm */
|
||||
+ apr_time_t idle_sync_until; /* Time we sync wait until keepalive handling kicks in */
|
||||
+ apr_size_t idle_frames; /* number of rcvd frames that kept session in idle state */
|
||||
+ apr_interval_time_t idle_delay; /* Time we delay processing rcvd frames in idle state */
|
||||
|
||||
apr_bucket_brigade *bbtmp; /* brigade for keeping temporary data */
|
||||
struct apr_thread_cond_t *iowait; /* our cond when trywaiting for data */
|
||||
@ -1,20 +0,0 @@
|
||||
diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c
|
||||
index 2e95659..f7f81be 100644
|
||||
--- a/modules/http2/h2_conn.c
|
||||
+++ b/modules/http2/h2_conn.c
|
||||
@@ -354,6 +354,15 @@ apr_status_t h2_slave_run_pre_connection(conn_rec *slave, apr_socket_t *csd)
|
||||
* (Not necessarily in pre_connection, but later. Set it here, so it
|
||||
* is in place.) */
|
||||
slave->keepalives = 1;
|
||||
+ /* We signal that this connection will be closed after the request.
|
||||
+ * Which is true in that sense that we throw away all traffic data
|
||||
+ * on this slave connection after each requests. Although we might
|
||||
+ * reuse internal structures like memory pools.
|
||||
+ * The wanted effect of this is that httpd does not try to clean up
|
||||
+ * any dangling data on this connection when a request is done. Which
|
||||
+ * is unneccessary on a h2 stream.
|
||||
+ */
|
||||
+ slave->keepalive = AP_CONN_CLOSE;
|
||||
return ap_run_pre_connection(slave, csd);
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
@ -1,85 +0,0 @@
|
||||
From 34f58ae20d9a85f2a1508a9a732874239491d456 Mon Sep 17 00:00:00 2001
|
||||
From: Hank Ibell <hwibell@apache.org>
|
||||
Date: Tue, 15 Jan 2019 19:54:41 +0000
|
||||
Subject: [PATCH] mod_session: Always decode session attributes early.
|
||||
|
||||
Backport r1850947 from trunk
|
||||
Submitted by: hwibell
|
||||
Reviewed by: hwibell, covener, wrowe
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1851409 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 2 ++
|
||||
STATUS | 5 -----
|
||||
modules/session/mod_session.c | 25 ++++++++++++++-----------
|
||||
3 files changed, 16 insertions(+), 16 deletions(-)
|
||||
|
||||
#diff --git a/CHANGES b/CHANGES
|
||||
#index c4d9f6c2ea8..4b0a07fdcf5 100644
|
||||
#--- a/CHANGES
|
||||
#+++ b/CHANGES
|
||||
#@@ -9,6 +9,8 @@ Changes with Apache 2.4.38
|
||||
# and we should just set the value for the environment variable
|
||||
# like in the pattern case. [Ruediger Pluem]
|
||||
#
|
||||
#+ *) mod_session: Always decode session attributes early. [Hank Ibell]
|
||||
#+
|
||||
# *) core: Incorrect values for environment variables are substituted when
|
||||
# multiple environment variables are specified in a directive. [Hank Ibell]
|
||||
#
|
||||
#diff --git a/STATUS b/STATUS
|
||||
#index 00070f9f247..45a92ba4d81 100644
|
||||
#--- a/STATUS
|
||||
#+++ b/STATUS
|
||||
#@@ -125,11 +125,6 @@ RELEASE SHOWSTOPPERS:
|
||||
# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
|
||||
# [ start all new proposals below, under PATCHES PROPOSED. ]
|
||||
#
|
||||
#- *) mod_session: Always decode session attributes early.
|
||||
#- trunk patch: http://svn.apache.org/r1850947
|
||||
#- 2.4.x patch: svn merge -c 1850947 ^/httpd/httpd/trunk .
|
||||
#- +1: hwibell, covener, wrowe
|
||||
#-
|
||||
# *) mod_ssl (ssl_engine_io.c: bio_filter_out_write, bio_filter_in_read)
|
||||
# Clear retry flags before aborting on client-initiated reneg. [Joe Orton]
|
||||
# PR: 63052
|
||||
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
|
||||
index d517020d995..64e6e4a8132 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
From 0ab8232f93d1861a6d63ffcfc127c9fe7f701d78 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Tue, 5 Feb 2019 11:52:28 +0000
|
||||
Subject: [PATCH] Merge of r1852986 from trunk:
|
||||
|
||||
mod_http2: disentangelment of stream and request method.
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1852989 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http2/h2_request.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c
|
||||
index 8899c4f..5ee88e9 100644
|
||||
--- a/modules/http2/h2_request.c
|
||||
+++ b/modules/http2/h2_request.c
|
||||
@@ -266,7 +266,7 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
|
||||
|
||||
/* Time to populate r with the data we have. */
|
||||
r->request_time = req->request_time;
|
||||
- r->method = req->method;
|
||||
+ r->method = apr_pstrdup(r->pool, req->method);
|
||||
/* Provide quick information about the request method as soon as known */
|
||||
r->method_number = ap_method_number_of(r->method);
|
||||
if (r->method_number == M_GET && r->method[0] == 'H') {
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
From 610b78f35a5dd12f953aac23d867c890c92c46d1 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Wed, 13 Mar 2019 12:30:20 +0000
|
||||
Subject: [PATCH] Merge r1852038, r1852101 from trunk:
|
||||
|
||||
mod_http2: enable re-use of slave connections again.
|
||||
|
||||
mod_http2: fixed slave connection keepalives counter.
|
||||
|
||||
Submitted by: icing
|
||||
Reviewed by: icing, ylavic, jim
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855406 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http2/h2_conn.c | 14 +++++++++-----
|
||||
modules/http2/h2_mplx.c | 8 +++++++-
|
||||
modules/http2/h2_task.c | 3 +--
|
||||
3 files changed, 17 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c
|
||||
index f7f81be..dc2081e 100644
|
||||
--- a/modules/http2/h2_conn.c
|
||||
+++ b/modules/http2/h2_conn.c
|
||||
@@ -305,6 +305,10 @@ conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
|
||||
c->notes = apr_table_make(pool, 5);
|
||||
c->input_filters = NULL;
|
||||
c->output_filters = NULL;
|
||||
+ c->keepalives = 0;
|
||||
+#if AP_MODULE_MAGIC_AT_LEAST(20180903, 1)
|
||||
+ c->filter_conn_ctx = NULL;
|
||||
+#endif
|
||||
c->bucket_alloc = apr_bucket_alloc_create(pool);
|
||||
c->data_in_input_filters = 0;
|
||||
c->data_in_output_filters = 0;
|
||||
@@ -332,16 +336,15 @@ conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
|
||||
ap_set_module_config(c->conn_config, mpm, cfg);
|
||||
}
|
||||
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
|
||||
- "h2_stream(%ld-%d): created slave", master->id, slave_id);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c,
|
||||
+ "h2_slave(%s): created", c->log_id);
|
||||
return c;
|
||||
}
|
||||
|
||||
void h2_slave_destroy(conn_rec *slave)
|
||||
{
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, slave,
|
||||
- "h2_stream(%s): destroy slave",
|
||||
- apr_table_get(slave->notes, H2_TASK_ID_NOTE));
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, slave,
|
||||
+ "h2_slave(%s): destroy", slave->log_id);
|
||||
slave->sbh = NULL;
|
||||
apr_pool_destroy(slave->pool);
|
||||
}
|
||||
@@ -365,6 +368,7 @@ apr_status_t h2_slave_run_pre_connection(conn_rec *slave, apr_socket_t *csd)
|
||||
slave->keepalive = AP_CONN_CLOSE;
|
||||
return ap_run_pre_connection(slave, csd);
|
||||
}
|
||||
+ ap_assert(slave->output_filters);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c
|
||||
index 05667ab..29f040c 100644
|
||||
--- a/modules/http2/h2_mplx.c
|
||||
+++ b/modules/http2/h2_mplx.c
|
||||
@@ -327,7 +327,8 @@ static int stream_destroy_iter(void *ctx, void *val)
|
||||
&& !task->rst_error);
|
||||
}
|
||||
|
||||
- if (reuse_slave && slave->keepalive == AP_CONN_KEEPALIVE) {
|
||||
+ task->c = NULL;
|
||||
+ if (reuse_slave) {
|
||||
h2_beam_log(task->output.beam, m->c, APLOG_DEBUG,
|
||||
APLOGNO(03385) "h2_task_destroy, reuse slave");
|
||||
h2_task_destroy(task);
|
||||
@@ -437,6 +438,8 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
|
||||
apr_status_t status;
|
||||
int i, wait_secs = 60;
|
||||
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
|
||||
+ "h2_mplx(%ld): start release", m->id);
|
||||
/* How to shut down a h2 connection:
|
||||
* 0. abort and tell the workers that no more tasks will come from us */
|
||||
m->aborted = 1;
|
||||
@@ -973,6 +976,9 @@ static apr_status_t unschedule_slow_tasks(h2_mplx *m)
|
||||
*/
|
||||
n = (m->tasks_active - m->limit_active - (int)h2_ihash_count(m->sredo));
|
||||
while (n > 0 && (stream = get_latest_repeatable_unsubmitted_stream(m))) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
|
||||
+ "h2_mplx(%s): unschedule, resetting task for redo later",
|
||||
+ stream->task->id);
|
||||
h2_task_rst(stream->task, H2_ERR_CANCEL);
|
||||
h2_ihash_add(m->sredo, stream);
|
||||
--n;
|
||||
diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c
|
||||
index 86fb026..f4c875c 100644
|
||||
--- a/modules/http2/h2_task.c
|
||||
+++ b/modules/http2/h2_task.c
|
||||
@@ -504,7 +504,7 @@ static int h2_task_pre_conn(conn_rec* c, void *arg)
|
||||
(void)arg;
|
||||
if (h2_ctx_is_task(ctx)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
|
||||
- "h2_h2, pre_connection, found stream task");
|
||||
+ "h2_slave(%s), pre_connection, adding filters", c->log_id);
|
||||
ap_add_input_filter("H2_SLAVE_IN", NULL, NULL, c);
|
||||
ap_add_output_filter("H2_PARSE_H1", NULL, NULL, c);
|
||||
ap_add_output_filter("H2_SLAVE_OUT", NULL, NULL, c);
|
||||
@@ -545,7 +545,6 @@ h2_task *h2_task_create(conn_rec *slave, int stream_id,
|
||||
void h2_task_destroy(h2_task *task)
|
||||
{
|
||||
if (task->output.beam) {
|
||||
- h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "task_destroy");
|
||||
h2_beam_destroy(task->output.beam);
|
||||
task->output.beam = NULL;
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,220 +0,0 @@
|
||||
MPMs unix: bind the bucket number of each child to its slot number
|
||||
|
||||
We need not remember each child's bucket number in SHM for restarts, for the
|
||||
lifetime of the httpd main process the bucket number can be bound to the slot
|
||||
number such that: bucket = slot % num_buckets.
|
||||
|
||||
This both simplifies the logic and helps children maintenance per bucket in
|
||||
threaded MPMs, where previously perform_idle_server_maintenance() could create
|
||||
or kill children processes for the buckets it was not in charge of.
|
||||
|
||||
diff --git a/include/scoreboard.h b/include/scoreboard.h
|
||||
index 57cf3df..b714a8c 100644
|
||||
--- a/include/scoreboard.h
|
||||
+++ b/include/scoreboard.h
|
||||
@@ -143,7 +143,9 @@ struct process_score {
|
||||
apr_uint32_t lingering_close; /* async connections in lingering close */
|
||||
apr_uint32_t keep_alive; /* async connections in keep alive */
|
||||
apr_uint32_t suspended; /* connections suspended by some module */
|
||||
- int bucket; /* Listener bucket used by this child */
|
||||
+ int bucket; /* Listener bucket used by this child; this field is DEPRECATED
|
||||
+ * and no longer updated by the MPMs (i.e. always zero).
|
||||
+ */
|
||||
};
|
||||
|
||||
/* Scoreboard is now in 'local' memory, since it isn't updated once created,
|
||||
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
|
||||
index ffe8a23..048ae61 100644
|
||||
--- a/server/mpm/event/event.c
|
||||
+++ b/server/mpm/event/event.c
|
||||
@@ -2695,7 +2695,6 @@ static int make_child(server_rec * s, int slot, int bucket)
|
||||
|
||||
ap_scoreboard_image->parent[slot].quiescing = 0;
|
||||
ap_scoreboard_image->parent[slot].not_accepting = 0;
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
event_note_child_started(slot, pid);
|
||||
active_daemons++;
|
||||
retained->total_daemons++;
|
||||
@@ -2734,6 +2733,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
* that threads_per_child is always > 0 */
|
||||
int status = SERVER_DEAD;
|
||||
int child_threads_active = 0;
|
||||
+ int bucket = i % num_buckets;
|
||||
|
||||
if (i >= retained->max_daemons_limit &&
|
||||
free_length == retained->idle_spawn_rate[child_bucket]) {
|
||||
@@ -2757,7 +2757,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
*/
|
||||
if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
|
||||
&& ps->generation == retained->mpm->my_generation
|
||||
- && ps->bucket == child_bucket)
|
||||
+ && bucket == child_bucket)
|
||||
{
|
||||
++idle_thread_count;
|
||||
}
|
||||
@@ -2768,7 +2768,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
last_non_dead = i;
|
||||
}
|
||||
active_thread_count += child_threads_active;
|
||||
- if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
|
||||
+ if (!ps->pid
|
||||
+ && bucket == child_bucket
|
||||
+ && free_length < retained->idle_spawn_rate[child_bucket])
|
||||
free_slots[free_length++] = i;
|
||||
else if (child_threads_active == threads_per_child)
|
||||
had_healthy_child = 1;
|
||||
@@ -2951,13 +2953,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
retained->total_daemons--;
|
||||
if (processed_status == APEXIT_CHILDSICK) {
|
||||
/* resource shortage, minimize the fork rate */
|
||||
- retained->idle_spawn_rate[ps->bucket] = 1;
|
||||
+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
|
||||
}
|
||||
else if (remaining_children_to_start) {
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot, ps->bucket);
|
||||
+ make_child(ap_server_conf, child_slot,
|
||||
+ child_slot % num_buckets);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
}
|
||||
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
|
||||
index 8efda72..7c00625 100644
|
||||
--- a/server/mpm/prefork/prefork.c
|
||||
+++ b/server/mpm/prefork/prefork.c
|
||||
@@ -637,8 +637,9 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
}
|
||||
|
||||
|
||||
-static int make_child(server_rec *s, int slot, int bucket)
|
||||
+static int make_child(server_rec *s, int slot)
|
||||
{
|
||||
+ int bucket = slot % retained->mpm->num_buckets;
|
||||
int pid;
|
||||
|
||||
if (slot + 1 > retained->max_daemons_limit) {
|
||||
@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
child_main(slot, bucket);
|
||||
}
|
||||
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
prefork_note_child_started(slot, pid);
|
||||
|
||||
return 0;
|
||||
@@ -732,7 +732,7 @@ static void startup_children(int number_to_start)
|
||||
if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
|
||||
continue;
|
||||
}
|
||||
- if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
|
||||
+ if (make_child(ap_server_conf, i) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -741,8 +741,6 @@ static void startup_children(int number_to_start)
|
||||
|
||||
static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
{
|
||||
- static int bucket_make_child_record = -1;
|
||||
- static int bucket_kill_child_record = -1;
|
||||
int i;
|
||||
int idle_count;
|
||||
worker_score *ws;
|
||||
@@ -789,6 +787,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
}
|
||||
retained->max_daemons_limit = last_non_dead + 1;
|
||||
if (idle_count > ap_daemons_max_free) {
|
||||
+ static int bucket_kill_child_record = -1;
|
||||
/* kill off one child... we use the pod because that'll cause it to
|
||||
* shut down gracefully, in case it happened to pick up a request
|
||||
* while we were counting
|
||||
@@ -819,10 +818,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
idle_count, total_non_dead);
|
||||
}
|
||||
for (i = 0; i < free_length; ++i) {
|
||||
- bucket_make_child_record++;
|
||||
- bucket_make_child_record %= retained->mpm->num_buckets;
|
||||
- make_child(ap_server_conf, free_slots[i],
|
||||
- bucket_make_child_record);
|
||||
+ make_child(ap_server_conf, free_slots[i]);
|
||||
}
|
||||
/* the next time around we want to spawn twice as many if this
|
||||
* wasn't good enough, but not if we've just done a graceful
|
||||
@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
|
||||
if (one_process) {
|
||||
AP_MONCONTROL(1);
|
||||
- make_child(ap_server_conf, 0, 0);
|
||||
+ make_child(ap_server_conf, 0);
|
||||
/* NOTREACHED */
|
||||
ap_assert(0);
|
||||
return !OK;
|
||||
@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot,
|
||||
- ap_get_scoreboard_process(child_slot)->bucket);
|
||||
+ make_child(ap_server_conf, child_slot);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
#if APR_HAS_OTHER_CHILD
|
||||
diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
|
||||
index 8012fe2..a927942 100644
|
||||
--- a/server/mpm/worker/worker.c
|
||||
+++ b/server/mpm/worker/worker.c
|
||||
@@ -1339,7 +1339,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
worker_note_child_lost_slot(slot, pid);
|
||||
}
|
||||
ap_scoreboard_image->parent[slot].quiescing = 0;
|
||||
- ap_scoreboard_image->parent[slot].bucket = bucket;
|
||||
worker_note_child_started(slot, pid);
|
||||
return 0;
|
||||
}
|
||||
@@ -1388,6 +1387,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
int any_dead_threads = 0;
|
||||
int all_dead_threads = 1;
|
||||
int child_threads_active = 0;
|
||||
+ int bucket = i % num_buckets;
|
||||
|
||||
if (i >= retained->max_daemons_limit &&
|
||||
totally_free_length == retained->idle_spawn_rate[child_bucket]) {
|
||||
@@ -1420,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
if (status <= SERVER_READY &&
|
||||
!ps->quiescing &&
|
||||
ps->generation == retained->mpm->my_generation &&
|
||||
- ps->bucket == child_bucket) {
|
||||
+ bucket == child_bucket) {
|
||||
++idle_thread_count;
|
||||
}
|
||||
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
|
||||
@@ -1430,6 +1430,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
}
|
||||
active_thread_count += child_threads_active;
|
||||
if (any_dead_threads
|
||||
+ && bucket == child_bucket
|
||||
&& totally_free_length < retained->idle_spawn_rate[child_bucket]
|
||||
&& free_length < MAX_SPAWN_RATE / num_buckets
|
||||
&& (!ps->pid /* no process in the slot */
|
||||
@@ -1615,14 +1616,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
ps->quiescing = 0;
|
||||
if (processed_status == APEXIT_CHILDSICK) {
|
||||
/* resource shortage, minimize the fork rate */
|
||||
- retained->idle_spawn_rate[ps->bucket] = 1;
|
||||
+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
|
||||
}
|
||||
else if (remaining_children_to_start
|
||||
&& child_slot < ap_daemons_limit) {
|
||||
/* we're still doing a 1-for-1 replacement of dead
|
||||
* children with new children
|
||||
*/
|
||||
- make_child(ap_server_conf, child_slot, ps->bucket);
|
||||
+ make_child(ap_server_conf, child_slot,
|
||||
+ child_slot % num_buckets);
|
||||
--remaining_children_to_start;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index cf841b0..7459503 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1154,6 +1154,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server);
|
||||
apr_table_setn(r->notes, "error-notes",
|
||||
"Reason: Cannot perform Post-Handshake Authentication.<br />");
|
||||
+ SSL_set_verify(ssl, vmode_inplace, NULL);
|
||||
return HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
@@ -1175,6 +1176,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
|
||||
* Finally check for acceptable renegotiation results
|
||||
*/
|
||||
if (OK != (rc = ssl_check_post_client_verify(r, sc, dc, sslconn, ssl))) {
|
||||
+ SSL_set_verify(ssl, vmode_inplace, NULL);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@ -1,203 +0,0 @@
|
||||
From 9bc1917a27a2323e535aadb081e38172ae0e3fc2 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Mon, 18 Mar 2019 08:49:59 +0000
|
||||
Subject: [PATCH] Merge of r1855705 from trunk:
|
||||
|
||||
core: merge consecutive slashes in the path
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855737 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
include/http_core.h | 2 +-
|
||||
include/httpd.h | 14 ++++++++++++--
|
||||
server/core.c | 13 +++++++++++++
|
||||
server/request.c | 25 +++++++++----------------
|
||||
server/util.c | 10 +++++++---
|
||||
5 files changed, 43 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/include/http_core.h b/include/http_core.h
|
||||
index 35df5dc9601..8e109882244 100644
|
||||
--- a/include/http_core.h
|
||||
+++ b/include/http_core.h
|
||||
@@ -740,7 +740,7 @@ typedef struct {
|
||||
#define AP_HTTP_METHODS_LENIENT 1
|
||||
#define AP_HTTP_METHODS_REGISTERED 2
|
||||
char http_methods;
|
||||
-
|
||||
+ unsigned int merge_slashes;
|
||||
} core_server_config;
|
||||
|
||||
/* for AddOutputFiltersByType in core.c */
|
||||
diff --git a/include/httpd.h b/include/httpd.h
|
||||
index 65392f83546..99f7f041aea 100644
|
||||
--- a/include/httpd.h
|
||||
+++ b/include/httpd.h
|
||||
@@ -1697,11 +1697,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
|
||||
AP_DECLARE(int) ap_unescape_urlencoded(char *query);
|
||||
|
||||
/**
|
||||
- * Convert all double slashes to single slashes
|
||||
- * @param name The string to convert
|
||||
+ * Convert all double slashes to single slashes, except where significant
|
||||
+ * to the filesystem on the current platform.
|
||||
+ * @param name The string to convert, assumed to be a filesystem path
|
||||
*/
|
||||
AP_DECLARE(void) ap_no2slash(char *name);
|
||||
|
||||
+/**
|
||||
+ * Convert all double slashes to single slashes, except where significant
|
||||
+ * to the filesystem on the current platform.
|
||||
+ * @param name The string to convert
|
||||
+ * @param is_fs_path if set to 0, the significance of any double-slashes is
|
||||
+ * ignored.
|
||||
+ */
|
||||
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path);
|
||||
+
|
||||
/**
|
||||
* Remove all ./ and xx/../ substrings from a file name. Also remove
|
||||
* any leading ../ or /../ substrings.
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index e2a91c7a0c6..eacb54fecec 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -490,6 +490,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
|
||||
|
||||
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
|
||||
conf->protocols_honor_order = -1;
|
||||
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET;
|
||||
|
||||
return (void *)conf;
|
||||
}
|
||||
@@ -555,6 +556,7 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
|
||||
conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
|
||||
base->protocols_honor_order :
|
||||
virt->protocols_honor_order);
|
||||
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
|
||||
|
||||
return conf;
|
||||
}
|
||||
@@ -1863,6 +1865,13 @@ static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag)
|
||||
+{
|
||||
+ core_server_config *conf =
|
||||
+ ap_get_core_module_config(cmd->server->module_config);
|
||||
+ return ap_set_flag_slot(cmd, conf, flag);
|
||||
+}
|
||||
+
|
||||
static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
|
||||
{
|
||||
core_dir_config *d = d_;
|
||||
@@ -4562,6 +4571,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON
|
||||
"'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"),
|
||||
AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
|
||||
"Registers non-standard HTTP methods"),
|
||||
+AP_INIT_FLAG("MergeSlashes", set_core_server_flag,
|
||||
+ (void *)APR_OFFSETOF(core_server_config, merge_slashes),
|
||||
+ RSRC_CONF,
|
||||
+ "Controls whether consecutive slashes in the URI path are merged"),
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
diff --git a/server/request.c b/server/request.c
|
||||
index dbe3e07f150..1ce8908824b 100644
|
||||
--- a/server/request.c
|
||||
+++ b/server/request.c
|
||||
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
int file_req = (r->main && r->filename);
|
||||
int access_status;
|
||||
core_dir_config *d;
|
||||
+ core_server_config *sconf =
|
||||
+ ap_get_core_module_config(r->server->module_config);
|
||||
|
||||
/* Ignore embedded %2F's in path for proxy requests */
|
||||
if (!r->proxyreq && r->parsed_uri.path) {
|
||||
@@ -191,6 +193,10 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
}
|
||||
|
||||
ap_getparents(r->uri); /* OK --- shrinking transformations... */
|
||||
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
|
||||
+ ap_no2slash(r->uri);
|
||||
+ ap_no2slash(r->parsed_uri.path);
|
||||
+ }
|
||||
|
||||
/* All file subrequests are a huge pain... they cannot bubble through the
|
||||
* next several steps. Only file subrequests are allowed an empty uri,
|
||||
@@ -1411,20 +1417,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
|
||||
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
|
||||
cached = (cache->cached != NULL);
|
||||
-
|
||||
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple
|
||||
- * slashes. Location matches multiple slashes with a single slash,
|
||||
- * LocationMatch doesn't. An exception, for backwards brokenness is
|
||||
- * absoluteURIs... in which case neither match multiple slashes.
|
||||
- */
|
||||
- if (r->uri[0] != '/') {
|
||||
- entry_uri = r->uri;
|
||||
- }
|
||||
- else {
|
||||
- char *uri = apr_pstrdup(r->pool, r->uri);
|
||||
- ap_no2slash(uri);
|
||||
- entry_uri = uri;
|
||||
- }
|
||||
+ entry_uri = r->uri;
|
||||
|
||||
/* If we have an cache->cached location that matches r->uri,
|
||||
* and the vhost's list of locations hasn't changed, we can skip
|
||||
@@ -1491,7 +1484,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
|
||||
}
|
||||
|
||||
- if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
|
||||
+ if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1501,7 +1494,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
||||
apr_table_setn(r->subprocess_env,
|
||||
((const char **)entry_core->refs->elts)[i],
|
||||
apr_pstrndup(r->pool,
|
||||
- r->uri + pmatch[i].rm_so,
|
||||
+ entry_uri + pmatch[i].rm_so,
|
||||
pmatch[i].rm_eo - pmatch[i].rm_so));
|
||||
}
|
||||
}
|
||||
diff --git a/server/util.c b/server/util.c
|
||||
index fd7a0a14763..607c4850d86 100644
|
||||
--- a/server/util.c
|
||||
+++ b/server/util.c
|
||||
@@ -561,16 +561,16 @@ AP_DECLARE(void) ap_getparents(char *name)
|
||||
name[l] = '\0';
|
||||
}
|
||||
}
|
||||
-
|
||||
-AP_DECLARE(void) ap_no2slash(char *name)
|
||||
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
|
||||
{
|
||||
+
|
||||
char *d, *s;
|
||||
|
||||
s = d = name;
|
||||
|
||||
#ifdef HAVE_UNC_PATHS
|
||||
/* Check for UNC names. Leave leading two slashes. */
|
||||
- if (s[0] == '/' && s[1] == '/')
|
||||
+ if (is_fs_path && s[0] == '/' && s[1] == '/')
|
||||
*d++ = *s++;
|
||||
#endif
|
||||
|
||||
@@ -587,6 +587,10 @@ AP_DECLARE(void) ap_no2slash(char *name)
|
||||
*d = '\0';
|
||||
}
|
||||
|
||||
+AP_DECLARE(void) ap_no2slash(char *name)
|
||||
+{
|
||||
+ ap_no2slash_ex(name, 1);
|
||||
+}
|
||||
|
||||
/*
|
||||
* copy at most n leading directories of s into d
|
||||
@ -1,50 +0,0 @@
|
||||
From c4ef468b25718a26f2b92cbea3ca093729b79331 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Covener <covener@apache.org>
|
||||
Date: Mon, 18 Mar 2019 12:10:15 +0000
|
||||
Subject: [PATCH] merge 1855743,1855744 ^/httpd/httpd/trunk .
|
||||
|
||||
r->parsed_uri.path safety in recent backport
|
||||
|
||||
*) core: fix SEGFAULT in CONNECT with recent change
|
||||
2.4.x: svn merge -c 1855743,1855744 ^/httpd/httpd/trunk .
|
||||
+1: rpluem, icing, covener
|
||||
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855751 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
server/request.c | 4 +++-
|
||||
server/util.c | 4 ++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/server/request.c b/server/request.c
|
||||
index 1ce8908824b..d5c558afa30 100644
|
||||
--- a/server/request.c
|
||||
+++ b/server/request.c
|
||||
@@ -195,7 +195,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
ap_getparents(r->uri); /* OK --- shrinking transformations... */
|
||||
if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
|
||||
ap_no2slash(r->uri);
|
||||
- ap_no2slash(r->parsed_uri.path);
|
||||
+ if (r->parsed_uri.path) {
|
||||
+ ap_no2slash(r->parsed_uri.path);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* All file subrequests are a huge pain... they cannot bubble through the
|
||||
diff --git a/server/util.c b/server/util.c
|
||||
index 607c4850d86..f3b17f1581e 100644
|
||||
--- a/server/util.c
|
||||
+++ b/server/util.c
|
||||
@@ -566,6 +566,10 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
|
||||
|
||||
char *d, *s;
|
||||
|
||||
+ if (!name || !*name) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
s = d = name;
|
||||
|
||||
#ifdef HAVE_UNC_PATHS
|
||||
@ -1,43 +0,0 @@
|
||||
From 3451fc2bf8708b0dc8cd6a7d0ac0fe5b6401befc Mon Sep 17 00:00:00 2001
|
||||
From: Eric Covener <covener@apache.org>
|
||||
Date: Tue, 19 Mar 2019 18:01:21 +0000
|
||||
Subject: [PATCH] *) maintainer mode fix for util.c no2slash_ex trunk
|
||||
patch: http://svn.apache.org/r1855755 2.4.x patch svn merge -c 1855755
|
||||
^/httpd/httpd/trunk . +1: covener, rpluem, jim, ylavic
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855853 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
STATUS | 6 ------
|
||||
server/util.c | 2 +-
|
||||
2 files changed, 1 insertion(+), 7 deletions(-)
|
||||
|
||||
#diff --git a/STATUS b/STATUS
|
||||
#index ffe5d22550c..1f8cb2f7884 100644
|
||||
#--- a/STATUS
|
||||
#+++ b/STATUS
|
||||
#@@ -126,12 +126,6 @@ RELEASE SHOWSTOPPERS:
|
||||
# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
|
||||
# [ start all new proposals below, under PATCHES PROPOSED. ]
|
||||
#
|
||||
#- *) maintainer mode fix for util.c no2slash_ex
|
||||
#- trunk patch: http://svn.apache.org/r1855755
|
||||
#- 2.4.x patch svn merge -c 1855755 ^/httpd/httpd/trunk .
|
||||
#- +1: covener, rpluem, jim, ylavic
|
||||
#-
|
||||
#-
|
||||
# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
|
||||
# [ New proposals should be added at the end of the list ]
|
||||
#
|
||||
diff --git a/server/util.c b/server/util.c
|
||||
index f3b17f1581e..e0c558cee2d 100644
|
||||
--- a/server/util.c
|
||||
+++ b/server/util.c
|
||||
@@ -566,7 +566,7 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
|
||||
|
||||
char *d, *s;
|
||||
|
||||
- if (!name || !*name) {
|
||||
+ if (!*name) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,211 +0,0 @@
|
||||
From d656b2c1f4a152c5050f4a154461c4f4dbf3952b Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Fri, 2 Aug 2019 09:10:06 +0000
|
||||
Subject: [PATCH 1/2] Merge of r1864191 from trunk:
|
||||
|
||||
*) core, proxy: remove request URL and headers from error docs (CVE-2019-10092)
|
||||
[Eric Covener]
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864207 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http/http_protocol.c | 86 +++++++++++++------------------------------
|
||||
modules/proxy/mod_proxy.c | 7 ++--
|
||||
modules/proxy/mod_proxy_ftp.c | 5 ++-
|
||||
modules/proxy/proxy_util.c | 5 +--
|
||||
4 files changed, 34 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
|
||||
index 8543fd1..b85e2f7 100644
|
||||
--- a/modules/http/http_protocol.c
|
||||
+++ b/modules/http/http_protocol.c
|
||||
@@ -1133,13 +1133,10 @@ static const char *get_canned_error_string(int status,
|
||||
"\">here</a>.</p>\n",
|
||||
NULL));
|
||||
case HTTP_USE_PROXY:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>This resource is only accessible "
|
||||
- "through the proxy\n",
|
||||
- ap_escape_html(r->pool, location),
|
||||
- "<br />\nYou will need to configure "
|
||||
- "your client to use that proxy.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>This resource is only accessible "
|
||||
+ "through the proxy\n"
|
||||
+ "<br />\nYou will need to configure "
|
||||
+ "your client to use that proxy.</p>\n");
|
||||
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
|
||||
case HTTP_UNAUTHORIZED:
|
||||
return("<p>This server could not verify that you\n"
|
||||
@@ -1155,34 +1152,20 @@ static const char *get_canned_error_string(int status,
|
||||
"error-notes",
|
||||
"</p>\n"));
|
||||
case HTTP_FORBIDDEN:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>You don't have permission to access ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "\non this server.<br />\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
+ return(add_optional_notes(r, "<p>You don't have permission to access this resource.", "error-notes", "</p>\n"));
|
||||
case HTTP_NOT_FOUND:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The requested URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " was not found on this server.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The requested URL was not found on this server.</p>\n");
|
||||
case HTTP_METHOD_NOT_ALLOWED:
|
||||
return(apr_pstrcat(p,
|
||||
"<p>The requested method ",
|
||||
ap_escape_html(r->pool, r->method),
|
||||
- " is not allowed for the URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- ".</p>\n",
|
||||
+ " is not allowed for this URL.</p>\n",
|
||||
NULL));
|
||||
case HTTP_NOT_ACCEPTABLE:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>An appropriate representation of the "
|
||||
- "requested resource ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " could not be found on this server.</p>\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "variant-list", ""));
|
||||
+ return(add_optional_notes(r,
|
||||
+ "<p>An appropriate representation of the requested resource "
|
||||
+ "could not be found on this server.</p>\n",
|
||||
+ "variant-list", ""));
|
||||
case HTTP_MULTIPLE_CHOICES:
|
||||
return(add_optional_notes(r, "", "variant-list", ""));
|
||||
case HTTP_LENGTH_REQUIRED:
|
||||
@@ -1193,18 +1176,13 @@ static const char *get_canned_error_string(int status,
|
||||
NULL);
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_PRECONDITION_FAILED:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The precondition on the request "
|
||||
- "for the URL ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " evaluated to false.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The precondition on the request "
|
||||
+ "for this URL evaluated to false.</p>\n");
|
||||
case HTTP_NOT_IMPLEMENTED:
|
||||
s1 = apr_pstrcat(p,
|
||||
"<p>",
|
||||
- ap_escape_html(r->pool, r->method), " to ",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- " not supported.<br />\n",
|
||||
+ ap_escape_html(r->pool, r->method), " ",
|
||||
+ " not supported for current URL.<br />\n",
|
||||
NULL);
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_BAD_GATEWAY:
|
||||
@@ -1212,29 +1190,19 @@ static const char *get_canned_error_string(int status,
|
||||
"response from an upstream server.<br />" CRLF;
|
||||
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
case HTTP_VARIANT_ALSO_VARIES:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>A variant for the requested "
|
||||
- "resource\n<pre>\n",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "\n</pre>\nis itself a negotiable resource. "
|
||||
- "This indicates a configuration error.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>A variant for the requested "
|
||||
+ "resource\n<pre>\n"
|
||||
+ "\n</pre>\nis itself a negotiable resource. "
|
||||
+ "This indicates a configuration error.</p>\n");
|
||||
case HTTP_REQUEST_TIME_OUT:
|
||||
return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
|
||||
case HTTP_GONE:
|
||||
- return(apr_pstrcat(p,
|
||||
- "<p>The requested resource<br />",
|
||||
- ap_escape_html(r->pool, r->uri),
|
||||
- "<br />\nis no longer available on this server "
|
||||
- "and there is no forwarding address.\n"
|
||||
- "Please remove all references to this "
|
||||
- "resource.</p>\n",
|
||||
- NULL));
|
||||
+ return("<p>The requested resource is no longer available on this server"
|
||||
+ " and there is no forwarding address.\n"
|
||||
+ "Please remove all references to this resource.</p>\n");
|
||||
case HTTP_REQUEST_ENTITY_TOO_LARGE:
|
||||
return(apr_pstrcat(p,
|
||||
- "The requested resource<br />",
|
||||
- ap_escape_html(r->pool, r->uri), "<br />\n",
|
||||
- "does not allow request data with ",
|
||||
+ "The requested resource does not allow request data with ",
|
||||
ap_escape_html(r->pool, r->method),
|
||||
" requests, or the amount of data provided in\n"
|
||||
"the request exceeds the capacity limit.\n",
|
||||
@@ -1318,11 +1286,9 @@ static const char *get_canned_error_string(int status,
|
||||
"the Server Name Indication (SNI) in use for this\n"
|
||||
"connection.</p>\n");
|
||||
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
|
||||
- s1 = apr_pstrcat(p,
|
||||
- "<p>Access to ", ap_escape_html(r->pool, r->uri),
|
||||
- "\nhas been denied for legal reasons.<br />\n",
|
||||
- NULL);
|
||||
- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
|
||||
+ return(add_optional_notes(r,
|
||||
+ "<p>Access to this URL has been denied for legal reasons.<br />\n",
|
||||
+ "error-notes", "</p>\n"));
|
||||
default: /* HTTP_INTERNAL_SERVER_ERROR */
|
||||
/*
|
||||
* This comparison to expose error-notes could be modified to
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index 9e5de3d..af56af9 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -1055,9 +1055,10 @@ static int proxy_handler(request_rec *r)
|
||||
char *end;
|
||||
maxfwd = apr_strtoi64(str, &end, 10);
|
||||
if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
|
||||
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
- apr_psprintf(r->pool,
|
||||
- "Max-Forwards value '%s' could not be parsed", str));
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ "Max-Forwards value '%s' could not be parsed", str);
|
||||
+ return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
+ "Max-Forwards request header could not be parsed");
|
||||
}
|
||||
else if (maxfwd == 0) {
|
||||
switch (r->method_number) {
|
||||
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
|
||||
index 4a10987..8f6f853 100644
|
||||
--- a/modules/proxy/mod_proxy_ftp.c
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c
|
||||
@@ -1024,8 +1024,9 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
/* We break the URL into host, port, path-search */
|
||||
if (r->parsed_uri.hostname == NULL) {
|
||||
if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {
|
||||
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
- apr_psprintf(p, "URI cannot be parsed: %s", url));
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ "URI cannot be parsed: %s", url);
|
||||
+ return ap_proxyerror(r, HTTP_BAD_REQUEST, "URI cannot be parsed");
|
||||
}
|
||||
connectname = uri.hostname;
|
||||
connectport = uri.port;
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 8cc9673..f6aef84 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -364,12 +364,9 @@ PROXY_DECLARE(char *)
|
||||
|
||||
PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
|
||||
{
|
||||
- const char *uri = ap_escape_html(r->pool, r->uri);
|
||||
apr_table_setn(r->notes, "error-notes",
|
||||
apr_pstrcat(r->pool,
|
||||
- "The proxy server could not handle the request <em><a href=\"",
|
||||
- uri, "\">", ap_escape_html(r->pool, r->method), " ", uri,
|
||||
- "</a></em>.<p>\n"
|
||||
+ "The proxy server could not handle the request<p>"
|
||||
"Reason: <strong>", ap_escape_html(r->pool, message),
|
||||
"</strong></p>",
|
||||
NULL));
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
From b66f9e4fdae9a75955a478da83a5637afaa6cf38 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Covener <covener@apache.org>
|
||||
Date: Thu, 8 Aug 2019 13:09:10 +0000
|
||||
Subject: [PATCH 2/2] Merge r1864699 from trunk:
|
||||
|
||||
lognos
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864702 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/proxy/mod_proxy.c | 2 +-
|
||||
modules/proxy/mod_proxy_ftp.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
|
||||
index af56af9..eee6a0f 100644
|
||||
--- a/modules/proxy/mod_proxy.c
|
||||
+++ b/modules/proxy/mod_proxy.c
|
||||
@@ -1055,7 +1055,7 @@ static int proxy_handler(request_rec *r)
|
||||
char *end;
|
||||
maxfwd = apr_strtoi64(str, &end, 10);
|
||||
if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10188)
|
||||
"Max-Forwards value '%s' could not be parsed", str);
|
||||
return ap_proxyerror(r, HTTP_BAD_REQUEST,
|
||||
"Max-Forwards request header could not be parsed");
|
||||
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
|
||||
index 8f6f853..1557301 100644
|
||||
--- a/modules/proxy/mod_proxy_ftp.c
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c
|
||||
@@ -1024,7 +1024,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
|
||||
/* We break the URL into host, port, path-search */
|
||||
if (r->parsed_uri.hostname == NULL) {
|
||||
if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10189)
|
||||
"URI cannot be parsed: %s", url);
|
||||
return ap_proxyerror(r, HTTP_BAD_REQUEST, "URI cannot be parsed");
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
From 1c598076631973877437a91fcb37753bd93112eb Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Wed, 7 Aug 2019 11:14:58 +0000
|
||||
Subject: [PATCH] Merge r1864526 from trunk:
|
||||
|
||||
* modules/metadata/mod_remoteip.c (remoteip_process_v2_header,
|
||||
remoteip_input_filter): Add sanity checks.
|
||||
|
||||
Submitted by: jorton, Daniel McCarney <cpu letsencrypt.org>
|
||||
|
||||
Submitted by: jorton
|
||||
Reviewed by: jorton, covener, jim
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864613 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/metadata/mod_remoteip.c | 36 +++++++++++++++++++++++++++---------
|
||||
1 file changed, 27 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c
|
||||
index 4572ce1..a0cbc0f 100644
|
||||
--- a/modules/metadata/mod_remoteip.c
|
||||
+++ b/modules/metadata/mod_remoteip.c
|
||||
@@ -987,15 +987,13 @@ static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c,
|
||||
return HDR_ERROR;
|
||||
#endif
|
||||
default:
|
||||
- /* unsupported protocol, keep local connection address */
|
||||
- return HDR_DONE;
|
||||
+ /* unsupported protocol */
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183)
|
||||
+ "RemoteIPProxyProtocol: unsupported protocol %.2hx",
|
||||
+ (unsigned short)hdr->v2.fam);
|
||||
+ return HDR_ERROR;
|
||||
}
|
||||
break; /* we got a sockaddr now */
|
||||
-
|
||||
- case 0x00: /* LOCAL command */
|
||||
- /* keep local connection address for LOCAL */
|
||||
- return HDR_DONE;
|
||||
-
|
||||
default:
|
||||
/* not a supported command */
|
||||
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03507)
|
||||
@@ -1087,11 +1085,24 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
|
||||
/* try to read a header's worth of data */
|
||||
while (!ctx->done) {
|
||||
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
||||
- ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block,
|
||||
- ctx->need - ctx->rcvd);
|
||||
+ apr_off_t got, want = ctx->need - ctx->rcvd;
|
||||
+
|
||||
+ ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want);
|
||||
if (ret != APR_SUCCESS) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184)
|
||||
+ "failed reading input");
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ ret = apr_brigade_length(ctx->bb, 1, &got);
|
||||
+ if (ret || got > want) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185)
|
||||
+ "RemoteIPProxyProtocol header too long, "
|
||||
+ "got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT,
|
||||
+ got, want);
|
||||
+ f->c->aborted = 1;
|
||||
+ return APR_ECONNABORTED;
|
||||
+ }
|
||||
}
|
||||
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
||||
return block == APR_NONBLOCK_READ ? APR_SUCCESS : APR_EOF;
|
||||
@@ -1139,6 +1150,13 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
|
||||
if (ctx->rcvd >= MIN_V2_HDR_LEN) {
|
||||
ctx->need = MIN_V2_HDR_LEN +
|
||||
remoteip_get_v2_len((proxy_header *) ctx->header);
|
||||
+ if (ctx->need > sizeof(proxy_v2)) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186)
|
||||
+ "RemoteIPProxyProtocol protocol header length too long");
|
||||
+ f->c->aborted = 1;
|
||||
+ apr_brigade_destroy(ctx->bb);
|
||||
+ return APR_ECONNABORTED;
|
||||
+ }
|
||||
}
|
||||
if (ctx->rcvd >= ctx->need) {
|
||||
psts = remoteip_process_v2_header(f->c, conn_conf,
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 950e6da61ffb4a2a616fe4d99550ba664bdeaf17 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Fri, 2 Aug 2019 09:24:58 +0000
|
||||
Subject: [PATCH] Merge of r1864192 from trunk:
|
||||
|
||||
*) core, rewrite: Set PCRE_DOTALL by default
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864213 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
server/util_pcre.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/server/util_pcre.c b/server/util_pcre.c
|
||||
index f2cb1bb..35831f5 100644
|
||||
--- a/server/util_pcre.c
|
||||
+++ b/server/util_pcre.c
|
||||
@@ -120,7 +120,8 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg)
|
||||
* Compile a regular expression *
|
||||
*************************************************/
|
||||
|
||||
-static int default_cflags = AP_REG_DOLLAR_ENDONLY;
|
||||
+static int default_cflags = AP_REG_DOTALL |
|
||||
+ AP_REG_DOLLAR_ENDONLY;
|
||||
|
||||
AP_DECLARE(int) ap_regcomp_get_default_cflags(void)
|
||||
{
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
From 2040a6943df462ef3fafd220043204ecd08f29dc Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Thu, 13 Jun 2019 11:08:29 +0000
|
||||
Subject: [PATCH 1/5] Merge r1860260 from trunk:
|
||||
|
||||
* modules/http2: more copying of data to disentangle worker processing from main connection
|
||||
|
||||
Submitted by: icing
|
||||
Reviewed by: icing, covener, jim
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1861247 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http2/h2_headers.c | 11 +++++++++--
|
||||
modules/http2/h2_headers.h | 8 +++++++-
|
||||
modules/http2/h2_session.c | 1 +
|
||||
3 files changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/http2/h2_headers.c b/modules/http2/h2_headers.c
|
||||
index f01ab88..2be9545 100644
|
||||
--- a/modules/http2/h2_headers.c
|
||||
+++ b/modules/http2/h2_headers.c
|
||||
@@ -101,8 +101,9 @@ apr_bucket *h2_bucket_headers_beam(struct h2_bucket_beam *beam,
|
||||
const apr_bucket *src)
|
||||
{
|
||||
if (H2_BUCKET_IS_HEADERS(src)) {
|
||||
- h2_headers *r = ((h2_bucket_headers *)src->data)->headers;
|
||||
- apr_bucket *b = h2_bucket_headers_create(dest->bucket_alloc, r);
|
||||
+ h2_headers *src_headers = ((h2_bucket_headers *)src->data)->headers;
|
||||
+ apr_bucket *b = h2_bucket_headers_create(dest->bucket_alloc,
|
||||
+ h2_headers_clone(dest->p, src_headers));
|
||||
APR_BRIGADE_INSERT_TAIL(dest, b);
|
||||
return b;
|
||||
}
|
||||
@@ -153,6 +154,12 @@ h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h)
|
||||
apr_table_copy(pool, h->notes), h->raw_bytes, pool);
|
||||
}
|
||||
|
||||
+h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h)
|
||||
+{
|
||||
+ return h2_headers_create(h->status, apr_table_clone(pool, h->headers),
|
||||
+ apr_table_clone(pool, h->notes), h->raw_bytes, pool);
|
||||
+}
|
||||
+
|
||||
h2_headers *h2_headers_die(apr_status_t type,
|
||||
const h2_request *req, apr_pool_t *pool)
|
||||
{
|
||||
diff --git a/modules/http2/h2_headers.h b/modules/http2/h2_headers.h
|
||||
index 840e8c4..b7d95a1 100644
|
||||
--- a/modules/http2/h2_headers.h
|
||||
+++ b/modules/http2/h2_headers.h
|
||||
@@ -59,12 +59,18 @@ h2_headers *h2_headers_rcreate(request_rec *r, int status,
|
||||
apr_table_t *header, apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
- * Clone the headers into another pool. This will not copy any
|
||||
+ * Copy the headers into another pool. This will not copy any
|
||||
* header strings.
|
||||
*/
|
||||
h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h);
|
||||
|
||||
/**
|
||||
+ * Clone the headers into another pool. This will also clone any
|
||||
+ * header strings.
|
||||
+ */
|
||||
+h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h);
|
||||
+
|
||||
+/**
|
||||
* Create the headers for the given error.
|
||||
* @param stream_id id of the stream to create the headers for
|
||||
* @param type the error code
|
||||
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
|
||||
index a1b31d2..3f0e9c9 100644
|
||||
--- a/modules/http2/h2_session.c
|
||||
+++ b/modules/http2/h2_session.c
|
||||
@@ -1950,6 +1950,7 @@ static void on_stream_state_enter(void *ctx, h2_stream *stream)
|
||||
ev_stream_closed(session, stream);
|
||||
break;
|
||||
case H2_SS_CLEANUP:
|
||||
+ nghttp2_session_set_stream_user_data(session->ngh2, stream->id, NULL);
|
||||
h2_mplx_stream_cleanup(session->mplx, stream);
|
||||
break;
|
||||
default:
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,121 +0,0 @@
|
||||
From 04f21f8422dd763da2f09badac965ff03e59aca8 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Thu, 13 Jun 2019 11:09:12 +0000
|
||||
Subject: [PATCH 2/5] Merge r1707084, r1707093, r1707159, r1707362 from trunk:
|
||||
|
||||
eor_bucket: don't destroy the request multiple times should any filter
|
||||
do a copy (e.g. mod_bucketeer).
|
||||
|
||||
eor_bucket: follow up to r1707084: fix comment.
|
||||
|
||||
eor_bucket: follow up to r1707084: use an inner shared bucket.
|
||||
|
||||
eor_bucket: follow up to r1707159.
|
||||
We need an apr_bucket_refcount, as spotted by Ruediger.
|
||||
Submitted by: ylavic
|
||||
Reviewed by: icing, covener, jim
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1861248 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
server/eor_bucket.c | 43 ++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 28 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/server/eor_bucket.c b/server/eor_bucket.c
|
||||
index 4d3e1ec..ecb809c 100644
|
||||
--- a/server/eor_bucket.c
|
||||
+++ b/server/eor_bucket.c
|
||||
@@ -19,17 +19,22 @@
|
||||
#include "http_protocol.h"
|
||||
#include "scoreboard.h"
|
||||
|
||||
+typedef struct {
|
||||
+ apr_bucket_refcount refcount;
|
||||
+ request_rec *data;
|
||||
+} ap_bucket_eor;
|
||||
+
|
||||
static apr_status_t eor_bucket_cleanup(void *data)
|
||||
{
|
||||
- apr_bucket *b = (apr_bucket *)data;
|
||||
- request_rec *r = (request_rec *)b->data;
|
||||
+ request_rec **rp = data;
|
||||
|
||||
- if (r != NULL) {
|
||||
+ if (*rp) {
|
||||
+ request_rec *r = *rp;
|
||||
/*
|
||||
* If eor_bucket_destroy is called after us, this prevents
|
||||
* eor_bucket_destroy from trying to destroy the pool again.
|
||||
*/
|
||||
- b->data = NULL;
|
||||
+ *rp = NULL;
|
||||
/* Update child status and log the transaction */
|
||||
ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
|
||||
ap_run_log_transaction(r);
|
||||
@@ -50,11 +55,13 @@ static apr_status_t eor_bucket_read(apr_bucket *b, const char **str,
|
||||
|
||||
AP_DECLARE(apr_bucket *) ap_bucket_eor_make(apr_bucket *b, request_rec *r)
|
||||
{
|
||||
- b->length = 0;
|
||||
- b->start = 0;
|
||||
- b->data = r;
|
||||
- b->type = &ap_bucket_type_eor;
|
||||
+ ap_bucket_eor *h;
|
||||
+
|
||||
+ h = apr_bucket_alloc(sizeof(*h), b->list);
|
||||
+ h->data = r;
|
||||
|
||||
+ b = apr_bucket_shared_make(b, h, 0, 0);
|
||||
+ b->type = &ap_bucket_type_eor;
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -66,7 +73,9 @@ AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
|
||||
APR_BUCKET_INIT(b);
|
||||
b->free = apr_bucket_free;
|
||||
b->list = list;
|
||||
+ b = ap_bucket_eor_make(b, r);
|
||||
if (r) {
|
||||
+ ap_bucket_eor *h = b->data;
|
||||
/*
|
||||
* Register a cleanup for the request pool as the eor bucket could
|
||||
* have been allocated from a different pool then the request pool
|
||||
@@ -76,18 +85,22 @@ AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
|
||||
* We need to use a pre-cleanup here because a module may create a
|
||||
* sub-pool which is still needed during the log_transaction hook.
|
||||
*/
|
||||
- apr_pool_pre_cleanup_register(r->pool, (void *)b, eor_bucket_cleanup);
|
||||
+ apr_pool_pre_cleanup_register(r->pool, &h->data, eor_bucket_cleanup);
|
||||
}
|
||||
- return ap_bucket_eor_make(b, r);
|
||||
+ return b;
|
||||
}
|
||||
|
||||
static void eor_bucket_destroy(void *data)
|
||||
{
|
||||
- request_rec *r = (request_rec *)data;
|
||||
+ ap_bucket_eor *h = data;
|
||||
|
||||
- if (r) {
|
||||
- /* eor_bucket_cleanup will be called when the pool gets destroyed */
|
||||
- apr_pool_destroy(r->pool);
|
||||
+ if (apr_bucket_shared_destroy(h)) {
|
||||
+ request_rec *r = h->data;
|
||||
+ if (r) {
|
||||
+ /* eor_bucket_cleanup will be called when the pool gets destroyed */
|
||||
+ apr_pool_destroy(r->pool);
|
||||
+ }
|
||||
+ apr_bucket_free(h);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +110,6 @@ AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_eor = {
|
||||
eor_bucket_read,
|
||||
apr_bucket_setaside_noop,
|
||||
apr_bucket_split_notimpl,
|
||||
- apr_bucket_simple_copy
|
||||
+ apr_bucket_shared_copy
|
||||
};
|
||||
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,306 +0,0 @@
|
||||
From 1125fc2240353c41db09eac8fedcc75dfdf44edb Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Wed, 19 Sep 2018 12:55:26 +0000
|
||||
Subject: [PATCH 3/5] Merge r1835118 from trunk:
|
||||
|
||||
On the trunk:
|
||||
|
||||
* silencing gcc uninitialized warning
|
||||
* refrainning from apr_table_addn() use since pool debug assumptions are in conflict
|
||||
* adding more assertions
|
||||
* copy-porting changes to base64 encoding code from mod_md
|
||||
|
||||
Submitted by: icing
|
||||
Reviewed by: icing, minfrin, jim
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1841330 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http2/h2_bucket_beam.c | 2 +-
|
||||
modules/http2/h2_from_h1.c | 4 +-
|
||||
modules/http2/h2_h2.c | 2 +-
|
||||
modules/http2/h2_headers.c | 7 ++--
|
||||
modules/http2/h2_mplx.c | 4 ++
|
||||
modules/http2/h2_proxy_session.c | 4 +-
|
||||
modules/http2/h2_util.c | 86 +++++++++++++++++++++-------------------
|
||||
7 files changed, 58 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/modules/http2/h2_bucket_beam.c b/modules/http2/h2_bucket_beam.c
|
||||
index 9f6fa82..f79cbe3 100644
|
||||
--- a/modules/http2/h2_bucket_beam.c
|
||||
+++ b/modules/http2/h2_bucket_beam.c
|
||||
@@ -775,7 +775,7 @@ static apr_status_t append_bucket(h2_bucket_beam *beam,
|
||||
const char *data;
|
||||
apr_size_t len;
|
||||
apr_status_t status;
|
||||
- int can_beam, check_len;
|
||||
+ int can_beam = 0, check_len;
|
||||
|
||||
if (beam->aborted) {
|
||||
return APR_ECONNABORTED;
|
||||
diff --git a/modules/http2/h2_from_h1.c b/modules/http2/h2_from_h1.c
|
||||
index ae264a9..dd6ad90 100644
|
||||
--- a/modules/http2/h2_from_h1.c
|
||||
+++ b/modules/http2/h2_from_h1.c
|
||||
@@ -164,7 +164,7 @@ static int copy_header(void *ctx, const char *name, const char *value)
|
||||
{
|
||||
apr_table_t *headers = ctx;
|
||||
|
||||
- apr_table_addn(headers, name, value);
|
||||
+ apr_table_add(headers, name, value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ static h2_headers *create_response(h2_task *task, request_rec *r)
|
||||
if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {
|
||||
char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
|
||||
ap_recent_rfc822_date(date, r->request_time);
|
||||
- apr_table_addn(r->headers_out, "Expires", date);
|
||||
+ apr_table_add(r->headers_out, "Expires", date);
|
||||
}
|
||||
|
||||
/* This is a hack, but I can't find anyway around it. The idea is that
|
||||
diff --git a/modules/http2/h2_h2.c b/modules/http2/h2_h2.c
|
||||
index dfee6b5..5580cef 100644
|
||||
--- a/modules/http2/h2_h2.c
|
||||
+++ b/modules/http2/h2_h2.c
|
||||
@@ -694,7 +694,7 @@ static void check_push(request_rec *r, const char *tag)
|
||||
tag, conf->push_list->nelts);
|
||||
for (i = 0; i < conf->push_list->nelts; ++i) {
|
||||
h2_push_res *push = &APR_ARRAY_IDX(conf->push_list, i, h2_push_res);
|
||||
- apr_table_addn(r->headers_out, "Link",
|
||||
+ apr_table_add(r->headers_out, "Link",
|
||||
apr_psprintf(r->pool, "<%s>; rel=preload%s",
|
||||
push->uri_ref, push->critical? "; critical" : ""));
|
||||
}
|
||||
diff --git a/modules/http2/h2_headers.c b/modules/http2/h2_headers.c
|
||||
index 2be9545..49d9c0a 100644
|
||||
--- a/modules/http2/h2_headers.c
|
||||
+++ b/modules/http2/h2_headers.c
|
||||
@@ -117,9 +117,9 @@ h2_headers *h2_headers_create(int status, apr_table_t *headers_in,
|
||||
{
|
||||
h2_headers *headers = apr_pcalloc(pool, sizeof(h2_headers));
|
||||
headers->status = status;
|
||||
- headers->headers = (headers_in? apr_table_copy(pool, headers_in)
|
||||
+ headers->headers = (headers_in? apr_table_clone(pool, headers_in)
|
||||
: apr_table_make(pool, 5));
|
||||
- headers->notes = (notes? apr_table_copy(pool, notes)
|
||||
+ headers->notes = (notes? apr_table_clone(pool, notes)
|
||||
: apr_table_make(pool, 5));
|
||||
return headers;
|
||||
}
|
||||
@@ -150,8 +150,7 @@ h2_headers *h2_headers_rcreate(request_rec *r, int status,
|
||||
|
||||
h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h)
|
||||
{
|
||||
- return h2_headers_create(h->status, apr_table_copy(pool, h->headers),
|
||||
- apr_table_copy(pool, h->notes), h->raw_bytes, pool);
|
||||
+ return h2_headers_create(h->status, h->headers, h->notes, h->raw_bytes, pool);
|
||||
}
|
||||
|
||||
h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h)
|
||||
diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c
|
||||
index 29f040c..db3cb63 100644
|
||||
--- a/modules/http2/h2_mplx.c
|
||||
+++ b/modules/http2/h2_mplx.c
|
||||
@@ -476,6 +476,7 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
|
||||
h2_ihash_iter(m->shold, report_stream_iter, m);
|
||||
}
|
||||
}
|
||||
+ ap_assert(m->tasks_active == 0);
|
||||
m->join_wait = NULL;
|
||||
|
||||
/* 4. close the h2_req_enginge shed */
|
||||
@@ -765,6 +766,9 @@ apr_status_t h2_mplx_pop_task(h2_mplx *m, h2_task **ptask)
|
||||
apr_status_t rv = APR_EOF;
|
||||
|
||||
*ptask = NULL;
|
||||
+ ap_assert(m);
|
||||
+ ap_assert(m->lock);
|
||||
+
|
||||
if (APR_SUCCESS != (rv = apr_thread_mutex_lock(m->lock))) {
|
||||
return rv;
|
||||
}
|
||||
diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c
|
||||
index a077ce1..8389c7c 100644
|
||||
--- a/modules/http2/h2_proxy_session.c
|
||||
+++ b/modules/http2/h2_proxy_session.c
|
||||
@@ -237,7 +237,7 @@ static int before_frame_send(nghttp2_session *ngh2,
|
||||
|
||||
static int add_header(void *table, const char *n, const char *v)
|
||||
{
|
||||
- apr_table_addn(table, n, v);
|
||||
+ apr_table_add(table, n, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ static void h2_proxy_stream_end_headers_out(h2_proxy_stream *stream)
|
||||
}
|
||||
|
||||
/* create a "Via:" response header entry and merge it */
|
||||
- apr_table_addn(r->headers_out, "Via",
|
||||
+ apr_table_add(r->headers_out, "Via",
|
||||
(session->conf->viaopt == via_full)
|
||||
? apr_psprintf(p, "%d.%d %s%s (%s)",
|
||||
HTTP_VERSION_MAJOR(r->proto_num),
|
||||
diff --git a/modules/http2/h2_util.c b/modules/http2/h2_util.c
|
||||
index 3d7ba37..9dacd8b 100644
|
||||
--- a/modules/http2/h2_util.c
|
||||
+++ b/modules/http2/h2_util.c
|
||||
@@ -115,26 +115,28 @@ void h2_util_camel_case_header(char *s, size_t len)
|
||||
|
||||
/* base64 url encoding ****************************************************************************/
|
||||
|
||||
-static const int BASE64URL_UINT6[] = {
|
||||
+#define N6 (unsigned int)-1
|
||||
+
|
||||
+static const unsigned int BASE64URL_UINT6[] = {
|
||||
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0 */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 1 */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, /* 2 */
|
||||
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 3 */
|
||||
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 4 */
|
||||
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, /* 5 */
|
||||
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 6 */
|
||||
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 7 */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 8 */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 9 */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e */
|
||||
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* f */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 0 */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 1 */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, 62, N6, N6, /* 2 */
|
||||
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, N6, N6, N6, N6, N6, N6, /* 3 */
|
||||
+ N6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 4 */
|
||||
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, N6, N6, N6, N6, 63, /* 5 */
|
||||
+ N6, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 6 */
|
||||
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, N6, N6, N6, N6, N6, /* 7 */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 8 */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 9 */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* a */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* b */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* c */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* d */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* e */
|
||||
+ N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6 /* f */
|
||||
};
|
||||
-static const char BASE64URL_CHARS[] = {
|
||||
+static const unsigned char BASE64URL_CHARS[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0 - 9 */
|
||||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10 - 19 */
|
||||
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20 - 29 */
|
||||
@@ -144,21 +146,23 @@ static const char BASE64URL_CHARS[] = {
|
||||
'8', '9', '-', '_', ' ', ' ', ' ', ' ', ' ', ' ', /* 60 - 69 */
|
||||
};
|
||||
|
||||
+#define BASE64URL_CHAR(x) BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ]
|
||||
+
|
||||
apr_size_t h2_util_base64url_decode(const char **decoded, const char *encoded,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const unsigned char *e = (const unsigned char *)encoded;
|
||||
const unsigned char *p = e;
|
||||
unsigned char *d;
|
||||
- int n;
|
||||
- apr_size_t len, mlen, remain, i;
|
||||
+ unsigned int n;
|
||||
+ long len, mlen, remain, i;
|
||||
|
||||
- while (*p && BASE64URL_UINT6[ *p ] != -1) {
|
||||
+ while (*p && BASE64URL_UINT6[ *p ] != N6) {
|
||||
++p;
|
||||
}
|
||||
- len = p - e;
|
||||
+ len = (int)(p - e);
|
||||
mlen = (len/4)*4;
|
||||
- *decoded = apr_pcalloc(pool, len+1);
|
||||
+ *decoded = apr_pcalloc(pool, (apr_size_t)len + 1);
|
||||
|
||||
i = 0;
|
||||
d = (unsigned char*)*decoded;
|
||||
@@ -167,60 +171,60 @@ apr_size_t h2_util_base64url_decode(const char **decoded, const char *encoded,
|
||||
(BASE64URL_UINT6[ e[i+1] ] << 12) +
|
||||
(BASE64URL_UINT6[ e[i+2] ] << 6) +
|
||||
(BASE64URL_UINT6[ e[i+3] ]));
|
||||
- *d++ = n >> 16;
|
||||
- *d++ = n >> 8 & 0xffu;
|
||||
- *d++ = n & 0xffu;
|
||||
+ *d++ = (unsigned char)(n >> 16);
|
||||
+ *d++ = (unsigned char)(n >> 8 & 0xffu);
|
||||
+ *d++ = (unsigned char)(n & 0xffu);
|
||||
}
|
||||
remain = len - mlen;
|
||||
switch (remain) {
|
||||
case 2:
|
||||
n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
|
||||
(BASE64URL_UINT6[ e[mlen+1] ] << 12));
|
||||
- *d++ = n >> 16;
|
||||
+ *d++ = (unsigned char)(n >> 16);
|
||||
remain = 1;
|
||||
break;
|
||||
case 3:
|
||||
n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
|
||||
(BASE64URL_UINT6[ e[mlen+1] ] << 12) +
|
||||
(BASE64URL_UINT6[ e[mlen+2] ] << 6));
|
||||
- *d++ = n >> 16;
|
||||
- *d++ = n >> 8 & 0xffu;
|
||||
+ *d++ = (unsigned char)(n >> 16);
|
||||
+ *d++ = (unsigned char)(n >> 8 & 0xffu);
|
||||
remain = 2;
|
||||
break;
|
||||
default: /* do nothing */
|
||||
break;
|
||||
}
|
||||
- return mlen/4*3 + remain;
|
||||
+ return (apr_size_t)(mlen/4*3 + remain);
|
||||
}
|
||||
|
||||
const char *h2_util_base64url_encode(const char *data,
|
||||
apr_size_t dlen, apr_pool_t *pool)
|
||||
{
|
||||
- long i, len = (int)dlen;
|
||||
+ int i, len = (int)dlen;
|
||||
apr_size_t slen = ((dlen+2)/3)*4 + 1; /* 0 terminated */
|
||||
const unsigned char *udata = (const unsigned char*)data;
|
||||
- char *enc, *p = apr_pcalloc(pool, slen);
|
||||
+ unsigned char *enc, *p = apr_pcalloc(pool, slen);
|
||||
|
||||
enc = p;
|
||||
for (i = 0; i < len-2; i+= 3) {
|
||||
- *p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
|
||||
- *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
|
||||
- *p++ = BASE64URL_CHARS[ ((udata[i+1] << 2) + (udata[i+2] >> 6)) & 0x3fu ];
|
||||
- *p++ = BASE64URL_CHARS[ udata[i+2] & 0x3fu ];
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i] >> 2) );
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i] << 4) + (udata[i+1] >> 4) );
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i+1] << 2) + (udata[i+2] >> 6) );
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i+2]) );
|
||||
}
|
||||
|
||||
if (i < len) {
|
||||
- *p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i] >> 2) );
|
||||
if (i == (len - 1)) {
|
||||
- *p++ = BASE64URL_CHARS[ (udata[i] << 4) & 0x3fu ];
|
||||
+ *p++ = BASE64URL_CHARS[ ((unsigned int)udata[i] << 4) & 0x3fu ];
|
||||
}
|
||||
else {
|
||||
- *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
|
||||
- *p++ = BASE64URL_CHARS[ (udata[i+1] << 2) & 0x3fu ];
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i] << 4) + (udata[i+1] >> 4) );
|
||||
+ *p++ = BASE64URL_CHAR( (udata[i+1] << 2) );
|
||||
}
|
||||
}
|
||||
*p++ = '\0';
|
||||
- return enc;
|
||||
+ return (char *)enc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,860 +0,0 @@
|
||||
From 94de05dacf17a60a8c3b34b5ded37fc4dc04709b Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Thu, 1 Aug 2019 08:18:03 +0000
|
||||
Subject: [PATCH 5/5] Merge of r1861338,1862475,1862583,1862865,1863221,1863276
|
||||
from trunk:
|
||||
|
||||
*) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
|
||||
merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]
|
||||
|
||||
*) mod_http2: fixed a bug that prevented proper stream cleanup when connection
|
||||
throttling was in place. Stream resets by clients on streams initiated by them
|
||||
are counted as possible trigger for throttling. [Stefan Eissing]
|
||||
|
||||
*) mod_http2/mpm_event: Fixes the behaviour when a HTTP/2 connection has nothing
|
||||
more to write with streams ongoing (flow control block). The timeout waiting
|
||||
for the client to send WINODW_UPDATE was incorrectly KeepAliveTimeout and not
|
||||
Timeout as it should be. Fixes PR 63534. [Yann Ylavic, Stefan Eissing]
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864126 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/http2/h2_conn.c | 7 ++
|
||||
modules/http2/h2_filter.c | 52 +++++++++-
|
||||
modules/http2/h2_mplx.c | 249 +++++++++++++++++++++++++++------------------
|
||||
modules/http2/h2_mplx.h | 11 +-
|
||||
modules/http2/h2_session.c | 19 +++-
|
||||
modules/http2/h2_stream.c | 80 +++++++++++----
|
||||
modules/http2/h2_stream.h | 4 +
|
||||
modules/http2/h2_task.c | 8 +-
|
||||
modules/http2/h2_task.h | 2 +
|
||||
server/mpm/event/event.c | 7 +-
|
||||
10 files changed, 304 insertions(+), 135 deletions(-)
|
||||
|
||||
diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c
|
||||
index 9ef0ea0..0b78a84 100644
|
||||
--- a/modules/http2/h2_conn.c
|
||||
+++ b/modules/http2/h2_conn.c
|
||||
@@ -231,6 +231,13 @@ apr_status_t h2_conn_run(conn_rec *c)
|
||||
case H2_SESSION_ST_BUSY:
|
||||
case H2_SESSION_ST_WAIT:
|
||||
c->cs->state = CONN_STATE_WRITE_COMPLETION;
|
||||
+ if (c->cs && (session->open_streams || !session->remote.emitted_count)) {
|
||||
+ /* let the MPM know that we are not done and want
|
||||
+ * the Timeout behaviour instead of a KeepAliveTimeout
|
||||
+ * See PR 63534.
|
||||
+ */
|
||||
+ c->cs->sense = CONN_SENSE_WANT_READ;
|
||||
+ }
|
||||
break;
|
||||
case H2_SESSION_ST_CLEANUP:
|
||||
case H2_SESSION_ST_DONE:
|
||||
diff --git a/modules/http2/h2_filter.c b/modules/http2/h2_filter.c
|
||||
index 5fd237f..2fc5e12 100644
|
||||
--- a/modules/http2/h2_filter.c
|
||||
+++ b/modules/http2/h2_filter.c
|
||||
@@ -493,6 +493,52 @@ static apr_status_t status_event(void *ctx, h2_bucket_event event,
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
+static apr_status_t discard_body(request_rec *r, apr_off_t maxlen)
|
||||
+{
|
||||
+ apr_bucket_brigade *bb;
|
||||
+ int seen_eos;
|
||||
+ apr_status_t rv;
|
||||
+
|
||||
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
||||
+ seen_eos = 0;
|
||||
+ do {
|
||||
+ apr_bucket *bucket;
|
||||
+
|
||||
+ rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
|
||||
+ APR_BLOCK_READ, HUGE_STRING_LEN);
|
||||
+
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ apr_brigade_destroy(bb);
|
||||
+ return rv;
|
||||
+ }
|
||||
+
|
||||
+ for (bucket = APR_BRIGADE_FIRST(bb);
|
||||
+ bucket != APR_BRIGADE_SENTINEL(bb);
|
||||
+ bucket = APR_BUCKET_NEXT(bucket))
|
||||
+ {
|
||||
+ const char *data;
|
||||
+ apr_size_t len;
|
||||
+
|
||||
+ if (APR_BUCKET_IS_EOS(bucket)) {
|
||||
+ seen_eos = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (bucket->length == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ apr_brigade_destroy(bb);
|
||||
+ return rv;
|
||||
+ }
|
||||
+ maxlen -= bucket->length;
|
||||
+ }
|
||||
+ apr_brigade_cleanup(bb);
|
||||
+ } while (!seen_eos && maxlen >= 0);
|
||||
+
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
int h2_filter_h2_status_handler(request_rec *r)
|
||||
{
|
||||
conn_rec *c = r->connection;
|
||||
@@ -510,8 +556,10 @@ int h2_filter_h2_status_handler(request_rec *r)
|
||||
|
||||
task = h2_ctx_get_task(r->connection);
|
||||
if (task) {
|
||||
-
|
||||
- if ((status = ap_discard_request_body(r)) != OK) {
|
||||
+ /* In this handler, we do some special sauce to send footers back,
|
||||
+ * IFF we received footers in the request. This is used in our test
|
||||
+ * cases, since CGI has no way of handling those. */
|
||||
+ if ((status = discard_body(r, 1024)) != OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c
|
||||
index fae77c7..9b504a5 100644
|
||||
--- a/modules/http2/h2_mplx.c
|
||||
+++ b/modules/http2/h2_mplx.c
|
||||
@@ -53,8 +53,12 @@ typedef struct {
|
||||
h2_mplx *m;
|
||||
h2_stream *stream;
|
||||
apr_time_t now;
|
||||
+ apr_size_t count;
|
||||
} stream_iter_ctx;
|
||||
|
||||
+static apr_status_t mplx_be_happy(h2_mplx *m);
|
||||
+static apr_status_t mplx_be_annoyed(h2_mplx *m);
|
||||
+
|
||||
apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s)
|
||||
{
|
||||
return APR_SUCCESS;
|
||||
@@ -98,7 +102,7 @@ static void stream_input_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t len
|
||||
|
||||
static void stream_joined(h2_mplx *m, h2_stream *stream)
|
||||
{
|
||||
- ap_assert(!stream->task || stream->task->worker_done);
|
||||
+ ap_assert(!h2_task_has_started(stream->task) || stream->task->worker_done);
|
||||
|
||||
h2_ihash_remove(m->shold, stream->id);
|
||||
h2_ihash_add(m->spurge, stream);
|
||||
@@ -124,7 +128,7 @@ static void stream_cleanup(h2_mplx *m, h2_stream *stream)
|
||||
h2_ififo_remove(m->readyq, stream->id);
|
||||
h2_ihash_add(m->shold, stream);
|
||||
|
||||
- if (!stream->task || stream->task->worker_done) {
|
||||
+ if (!h2_task_has_started(stream->task) || stream->task->done_done) {
|
||||
stream_joined(m, stream);
|
||||
}
|
||||
else if (stream->task) {
|
||||
@@ -194,7 +198,6 @@ h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *parent,
|
||||
m->stream_max_mem = h2_config_sgeti(s, H2_CONF_STREAM_MAX_MEM);
|
||||
|
||||
m->streams = h2_ihash_create(m->pool, offsetof(h2_stream,id));
|
||||
- m->sredo = h2_ihash_create(m->pool, offsetof(h2_stream,id));
|
||||
m->shold = h2_ihash_create(m->pool, offsetof(h2_stream,id));
|
||||
m->spurge = h2_ihash_create(m->pool, offsetof(h2_stream,id));
|
||||
m->q = h2_iq_create(m->pool, m->max_streams);
|
||||
@@ -208,8 +211,8 @@ h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *parent,
|
||||
m->workers = workers;
|
||||
m->max_active = workers->max_workers;
|
||||
m->limit_active = 6; /* the original h1 max parallel connections */
|
||||
- m->last_limit_change = m->last_idle_block = apr_time_now();
|
||||
- m->limit_change_interval = apr_time_from_msec(100);
|
||||
+ m->last_mood_change = apr_time_now();
|
||||
+ m->mood_update_interval = apr_time_from_msec(100);
|
||||
|
||||
m->spare_slaves = apr_array_make(m->pool, 10, sizeof(conn_rec*));
|
||||
}
|
||||
@@ -431,6 +434,10 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
|
||||
|
||||
/* How to shut down a h2 connection:
|
||||
* 1. cancel all streams still active */
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
+ "h2_mplx(%ld): release, %d/%d/%d streams (total/hold/purge), %d active tasks",
|
||||
+ m->id, (int)h2_ihash_count(m->streams),
|
||||
+ (int)h2_ihash_count(m->shold), (int)h2_ihash_count(m->spurge), m->tasks_active);
|
||||
while (!h2_ihash_iter(m->streams, stream_cancel_iter, m)) {
|
||||
/* until empty */
|
||||
}
|
||||
@@ -456,10 +463,10 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
|
||||
h2_ihash_iter(m->shold, report_stream_iter, m);
|
||||
}
|
||||
}
|
||||
- ap_assert(m->tasks_active == 0);
|
||||
m->join_wait = NULL;
|
||||
-
|
||||
+
|
||||
/* 4. With all workers done, all streams should be in spurge */
|
||||
+ ap_assert(m->tasks_active == 0);
|
||||
if (!h2_ihash_empty(m->shold)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(03516)
|
||||
"h2_mplx(%ld): unexpected %d streams in hold",
|
||||
@@ -470,8 +477,7 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
|
||||
m->c->aborted = old_aborted;
|
||||
H2_MPLX_LEAVE(m);
|
||||
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
- "h2_mplx(%ld): released", m->id);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, "h2_mplx(%ld): released", m->id);
|
||||
}
|
||||
|
||||
apr_status_t h2_mplx_stream_cleanup(h2_mplx *m, h2_stream *stream)
|
||||
@@ -709,7 +715,6 @@ static h2_task *next_stream_task(h2_mplx *m)
|
||||
}
|
||||
|
||||
if (!stream->task) {
|
||||
-
|
||||
if (sid > m->max_stream_started) {
|
||||
m->max_stream_started = sid;
|
||||
}
|
||||
@@ -728,9 +733,9 @@ static h2_task *next_stream_task(h2_mplx *m)
|
||||
"create task"));
|
||||
return NULL;
|
||||
}
|
||||
-
|
||||
}
|
||||
|
||||
+ stream->task->started_at = apr_time_now();
|
||||
++m->tasks_active;
|
||||
return stream->task;
|
||||
}
|
||||
@@ -778,32 +783,18 @@ static void task_done(h2_mplx *m, h2_task *task)
|
||||
"h2_mplx(%s): request done, %f ms elapsed", task->id,
|
||||
(task->done_at - task->started_at) / 1000.0);
|
||||
|
||||
- if (task->started_at > m->last_idle_block) {
|
||||
- /* this task finished without causing an 'idle block', e.g.
|
||||
- * a block by flow control.
|
||||
- */
|
||||
- if (task->done_at- m->last_limit_change >= m->limit_change_interval
|
||||
- && m->limit_active < m->max_active) {
|
||||
- /* Well behaving stream, allow it more workers */
|
||||
- m->limit_active = H2MIN(m->limit_active * 2,
|
||||
- m->max_active);
|
||||
- m->last_limit_change = task->done_at;
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
- "h2_mplx(%ld): increase worker limit to %d",
|
||||
- m->id, m->limit_active);
|
||||
- }
|
||||
+ if (task->c && !task->c->aborted && task->started_at > m->last_mood_change) {
|
||||
+ mplx_be_happy(m);
|
||||
}
|
||||
-
|
||||
+
|
||||
ap_assert(task->done_done == 0);
|
||||
|
||||
stream = h2_ihash_get(m->streams, task->stream_id);
|
||||
if (stream) {
|
||||
/* stream not done yet. */
|
||||
- if (!m->aborted && h2_ihash_get(m->sredo, stream->id)) {
|
||||
+ if (!m->aborted && task->redo) {
|
||||
/* reset and schedule again */
|
||||
- task->worker_done = 0;
|
||||
h2_task_redo(task);
|
||||
- h2_ihash_remove(m->sredo, stream->id);
|
||||
h2_iq_add(m->q, stream->id, NULL, NULL);
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c,
|
||||
H2_STRM_MSG(stream, "redo, added to q"));
|
||||
@@ -848,8 +839,8 @@ void h2_mplx_task_done(h2_mplx *m, h2_task *task, h2_task **ptask)
|
||||
{
|
||||
H2_MPLX_ENTER_ALWAYS(m);
|
||||
|
||||
- task_done(m, task);
|
||||
--m->tasks_active;
|
||||
+ task_done(m, task);
|
||||
|
||||
if (m->join_wait) {
|
||||
apr_thread_cond_signal(m->join_wait);
|
||||
@@ -867,94 +858,161 @@ void h2_mplx_task_done(h2_mplx *m, h2_task *task, h2_task **ptask)
|
||||
* h2_mplx DoS protection
|
||||
******************************************************************************/
|
||||
|
||||
-static int latest_repeatable_unsubmitted_iter(void *data, void *val)
|
||||
+static int timed_out_busy_iter(void *data, void *val)
|
||||
{
|
||||
stream_iter_ctx *ctx = data;
|
||||
h2_stream *stream = val;
|
||||
-
|
||||
- if (stream->task && !stream->task->worker_done
|
||||
- && h2_task_can_redo(stream->task)
|
||||
- && !h2_ihash_get(ctx->m->sredo, stream->id)) {
|
||||
- if (!h2_stream_is_ready(stream)) {
|
||||
- /* this task occupies a worker, the response has not been submitted
|
||||
- * yet, not been cancelled and it is a repeatable request
|
||||
- * -> it can be re-scheduled later */
|
||||
- if (!ctx->stream
|
||||
- || (ctx->stream->task->started_at < stream->task->started_at)) {
|
||||
- /* we did not have one or this one was started later */
|
||||
- ctx->stream = stream;
|
||||
- }
|
||||
- }
|
||||
+ if (h2_task_has_started(stream->task) && !stream->task->worker_done
|
||||
+ && (ctx->now - stream->task->started_at) > stream->task->timeout) {
|
||||
+ /* timed out stream occupying a worker, found */
|
||||
+ ctx->stream = stream;
|
||||
+ return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static h2_stream *get_latest_repeatable_unsubmitted_stream(h2_mplx *m)
|
||||
+static h2_stream *get_timed_out_busy_stream(h2_mplx *m)
|
||||
{
|
||||
stream_iter_ctx ctx;
|
||||
ctx.m = m;
|
||||
ctx.stream = NULL;
|
||||
- h2_ihash_iter(m->streams, latest_repeatable_unsubmitted_iter, &ctx);
|
||||
+ ctx.now = apr_time_now();
|
||||
+ h2_ihash_iter(m->streams, timed_out_busy_iter, &ctx);
|
||||
return ctx.stream;
|
||||
}
|
||||
|
||||
-static int timed_out_busy_iter(void *data, void *val)
|
||||
+static int latest_repeatable_unsubmitted_iter(void *data, void *val)
|
||||
{
|
||||
stream_iter_ctx *ctx = data;
|
||||
h2_stream *stream = val;
|
||||
- if (stream->task && !stream->task->worker_done
|
||||
- && (ctx->now - stream->task->started_at) > stream->task->timeout) {
|
||||
- /* timed out stream occupying a worker, found */
|
||||
- ctx->stream = stream;
|
||||
- return 0;
|
||||
+
|
||||
+ if (!stream->task) goto leave;
|
||||
+ if (!h2_task_has_started(stream->task) || stream->task->worker_done) goto leave;
|
||||
+ if (h2_stream_is_ready(stream)) goto leave;
|
||||
+ if (stream->task->redo) {
|
||||
+ ++ctx->count;
|
||||
+ goto leave;
|
||||
+ }
|
||||
+ if (h2_task_can_redo(stream->task)) {
|
||||
+ /* this task occupies a worker, the response has not been submitted
|
||||
+ * yet, not been cancelled and it is a repeatable request
|
||||
+ * -> we could redo it later */
|
||||
+ if (!ctx->stream
|
||||
+ || (ctx->stream->task->started_at < stream->task->started_at)) {
|
||||
+ /* we did not have one or this one was started later */
|
||||
+ ctx->stream = stream;
|
||||
+ }
|
||||
}
|
||||
+leave:
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static h2_stream *get_timed_out_busy_stream(h2_mplx *m)
|
||||
+static apr_status_t assess_task_to_throttle(h2_task **ptask, h2_mplx *m)
|
||||
{
|
||||
stream_iter_ctx ctx;
|
||||
+
|
||||
+ /* count the running tasks already marked for redo and get one that could
|
||||
+ * be throttled */
|
||||
+ *ptask = NULL;
|
||||
ctx.m = m;
|
||||
ctx.stream = NULL;
|
||||
- ctx.now = apr_time_now();
|
||||
- h2_ihash_iter(m->streams, timed_out_busy_iter, &ctx);
|
||||
- return ctx.stream;
|
||||
+ ctx.count = 0;
|
||||
+ h2_ihash_iter(m->streams, latest_repeatable_unsubmitted_iter, &ctx);
|
||||
+ if (m->tasks_active - ctx.count > m->limit_active) {
|
||||
+ /* we are above the limit of running tasks, accounting for the ones
|
||||
+ * already throttled. */
|
||||
+ if (ctx.stream && ctx.stream->task) {
|
||||
+ *ptask = ctx.stream->task;
|
||||
+ return APR_EAGAIN;
|
||||
+ }
|
||||
+ /* above limit, be seeing no candidate for easy throttling */
|
||||
+ if (get_timed_out_busy_stream(m)) {
|
||||
+ /* Too many busy workers, unable to cancel enough streams
|
||||
+ * and with a busy, timed out stream, we tell the client
|
||||
+ * to go away... */
|
||||
+ return APR_TIMEUP;
|
||||
+ }
|
||||
+ }
|
||||
+ return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t unschedule_slow_tasks(h2_mplx *m)
|
||||
{
|
||||
- h2_stream *stream;
|
||||
- int n;
|
||||
+ h2_task *task;
|
||||
+ apr_status_t rv;
|
||||
|
||||
/* Try to get rid of streams that occupy workers. Look for safe requests
|
||||
* that are repeatable. If none found, fail the connection.
|
||||
*/
|
||||
- n = (m->tasks_active - m->limit_active - (int)h2_ihash_count(m->sredo));
|
||||
- while (n > 0 && (stream = get_latest_repeatable_unsubmitted_stream(m))) {
|
||||
+ while (APR_EAGAIN == (rv = assess_task_to_throttle(&task, m))) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
|
||||
"h2_mplx(%s): unschedule, resetting task for redo later",
|
||||
- stream->task->id);
|
||||
- h2_task_rst(stream->task, H2_ERR_CANCEL);
|
||||
- h2_ihash_add(m->sredo, stream);
|
||||
- --n;
|
||||
+ task->id);
|
||||
+ task->redo = 1;
|
||||
+ h2_task_rst(task, H2_ERR_CANCEL);
|
||||
}
|
||||
|
||||
- if ((m->tasks_active - h2_ihash_count(m->sredo)) > m->limit_active) {
|
||||
- h2_stream *stream = get_timed_out_busy_stream(m);
|
||||
- if (stream) {
|
||||
- /* Too many busy workers, unable to cancel enough streams
|
||||
- * and with a busy, timed out stream, we tell the client
|
||||
- * to go away... */
|
||||
- return APR_TIMEUP;
|
||||
- }
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
+static apr_status_t mplx_be_happy(h2_mplx *m)
|
||||
+{
|
||||
+ apr_time_t now;
|
||||
+
|
||||
+ --m->irritations_since;
|
||||
+ now = apr_time_now();
|
||||
+ if (m->limit_active < m->max_active
|
||||
+ && (now - m->last_mood_change >= m->mood_update_interval
|
||||
+ || m->irritations_since < -m->limit_active)) {
|
||||
+ m->limit_active = H2MIN(m->limit_active * 2, m->max_active);
|
||||
+ m->last_mood_change = now;
|
||||
+ m->irritations_since = 0;
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
+ "h2_mplx(%ld): mood update, increasing worker limit to %d",
|
||||
+ m->id, m->limit_active);
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
-apr_status_t h2_mplx_idle(h2_mplx *m)
|
||||
+static apr_status_t mplx_be_annoyed(h2_mplx *m)
|
||||
{
|
||||
apr_status_t status = APR_SUCCESS;
|
||||
apr_time_t now;
|
||||
+
|
||||
+ ++m->irritations_since;
|
||||
+ now = apr_time_now();
|
||||
+ if (m->limit_active > 2 &&
|
||||
+ ((now - m->last_mood_change >= m->mood_update_interval)
|
||||
+ || (m->irritations_since >= m->limit_active))) {
|
||||
+
|
||||
+ if (m->limit_active > 16) {
|
||||
+ m->limit_active = 16;
|
||||
+ }
|
||||
+ else if (m->limit_active > 8) {
|
||||
+ m->limit_active = 8;
|
||||
+ }
|
||||
+ else if (m->limit_active > 4) {
|
||||
+ m->limit_active = 4;
|
||||
+ }
|
||||
+ else if (m->limit_active > 2) {
|
||||
+ m->limit_active = 2;
|
||||
+ }
|
||||
+ m->last_mood_change = now;
|
||||
+ m->irritations_since = 0;
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
+ "h2_mplx(%ld): mood update, decreasing worker limit to %d",
|
||||
+ m->id, m->limit_active);
|
||||
+ }
|
||||
+
|
||||
+ if (m->tasks_active > m->limit_active) {
|
||||
+ status = unschedule_slow_tasks(m);
|
||||
+ }
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+apr_status_t h2_mplx_idle(h2_mplx *m)
|
||||
+{
|
||||
+ apr_status_t status = APR_SUCCESS;
|
||||
apr_size_t scount;
|
||||
|
||||
H2_MPLX_ENTER(m);
|
||||
@@ -974,31 +1032,7 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
|
||||
* of busy workers we allow for this connection until it
|
||||
* well behaves.
|
||||
*/
|
||||
- now = apr_time_now();
|
||||
- m->last_idle_block = now;
|
||||
- if (m->limit_active > 2
|
||||
- && now - m->last_limit_change >= m->limit_change_interval) {
|
||||
- if (m->limit_active > 16) {
|
||||
- m->limit_active = 16;
|
||||
- }
|
||||
- else if (m->limit_active > 8) {
|
||||
- m->limit_active = 8;
|
||||
- }
|
||||
- else if (m->limit_active > 4) {
|
||||
- m->limit_active = 4;
|
||||
- }
|
||||
- else if (m->limit_active > 2) {
|
||||
- m->limit_active = 2;
|
||||
- }
|
||||
- m->last_limit_change = now;
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
- "h2_mplx(%ld): decrease worker limit to %d",
|
||||
- m->id, m->limit_active);
|
||||
- }
|
||||
-
|
||||
- if (m->tasks_active > m->limit_active) {
|
||||
- status = unschedule_slow_tasks(m);
|
||||
- }
|
||||
+ status = mplx_be_annoyed(m);
|
||||
}
|
||||
else if (!h2_iq_empty(m->q)) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
|
||||
@@ -1093,11 +1127,24 @@ int h2_mplx_awaits_data(h2_mplx *m)
|
||||
if (h2_ihash_empty(m->streams)) {
|
||||
waiting = 0;
|
||||
}
|
||||
- else if (!m->tasks_active && !h2_ififo_count(m->readyq)
|
||||
- && h2_iq_empty(m->q)) {
|
||||
+ else if (!m->tasks_active && !h2_ififo_count(m->readyq) && h2_iq_empty(m->q)) {
|
||||
waiting = 0;
|
||||
}
|
||||
|
||||
H2_MPLX_LEAVE(m);
|
||||
return waiting;
|
||||
}
|
||||
+
|
||||
+apr_status_t h2_mplx_client_rst(h2_mplx *m, int stream_id)
|
||||
+{
|
||||
+ h2_stream *stream;
|
||||
+ apr_status_t status = APR_SUCCESS;
|
||||
+
|
||||
+ H2_MPLX_ENTER_ALWAYS(m);
|
||||
+ stream = h2_ihash_get(m->streams, stream_id);
|
||||
+ if (stream && stream->task) {
|
||||
+ status = mplx_be_annoyed(m);
|
||||
+ }
|
||||
+ H2_MPLX_LEAVE(m);
|
||||
+ return status;
|
||||
+}
|
||||
diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h
|
||||
index 575ccaf..8a4f63f 100644
|
||||
--- a/modules/http2/h2_mplx.h
|
||||
+++ b/modules/http2/h2_mplx.h
|
||||
@@ -63,7 +63,6 @@ struct h2_mplx {
|
||||
unsigned int is_registered; /* is registered at h2_workers */
|
||||
|
||||
struct h2_ihash_t *streams; /* all streams currently processing */
|
||||
- struct h2_ihash_t *sredo; /* all streams that need to be re-started */
|
||||
struct h2_ihash_t *shold; /* all streams done with task ongoing */
|
||||
struct h2_ihash_t *spurge; /* all streams done, ready for destroy */
|
||||
|
||||
@@ -77,10 +76,10 @@ struct h2_mplx {
|
||||
int tasks_active; /* # of tasks being processed from this mplx */
|
||||
int limit_active; /* current limit on active tasks, dynamic */
|
||||
int max_active; /* max, hard limit # of active tasks in a process */
|
||||
- apr_time_t last_idle_block; /* last time, this mplx entered IDLE while
|
||||
- * streams were ready */
|
||||
- apr_time_t last_limit_change; /* last time, worker limit changed */
|
||||
- apr_interval_time_t limit_change_interval;
|
||||
+
|
||||
+ apr_time_t last_mood_change; /* last time, we worker limit changed */
|
||||
+ apr_interval_time_t mood_update_interval; /* how frequent we update at most */
|
||||
+ int irritations_since; /* irritations (>0) or happy events (<0) since last mood change */
|
||||
|
||||
apr_thread_mutex_t *lock;
|
||||
struct apr_thread_cond_t *added_output;
|
||||
@@ -205,6 +204,8 @@ typedef int h2_mplx_stream_cb(struct h2_stream *s, void *ctx);
|
||||
|
||||
apr_status_t h2_mplx_stream_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx);
|
||||
|
||||
+apr_status_t h2_mplx_client_rst(h2_mplx *m, int stream_id);
|
||||
+
|
||||
/*******************************************************************************
|
||||
* Output handling of streams.
|
||||
******************************************************************************/
|
||||
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
|
||||
index f153422..43d26d3 100644
|
||||
--- a/modules/http2/h2_session.c
|
||||
+++ b/modules/http2/h2_session.c
|
||||
@@ -390,9 +390,14 @@ static int on_frame_recv_cb(nghttp2_session *ng2s,
|
||||
(int)frame->rst_stream.error_code);
|
||||
stream = h2_session_stream_get(session, frame->hd.stream_id);
|
||||
if (stream && stream->initiated_on) {
|
||||
+ /* A stream reset on a request we sent it. Normal, when the
|
||||
+ * client does not want it. */
|
||||
++session->pushes_reset;
|
||||
}
|
||||
else {
|
||||
+ /* A stream reset on a request it sent us. Could happen in a browser
|
||||
+ * when the user navigates away or cancels loading - maybe. */
|
||||
+ h2_mplx_client_rst(session->mplx, frame->hd.stream_id);
|
||||
++session->streams_reset;
|
||||
}
|
||||
break;
|
||||
@@ -1699,7 +1704,7 @@ static void transit(h2_session *session, const char *action, h2_session_state ns
|
||||
* that already served requests - not fair. */
|
||||
session->idle_sync_until = apr_time_now() + apr_time_from_sec(1);
|
||||
s = "timeout";
|
||||
- timeout = H2MAX(session->s->timeout, session->s->keep_alive_timeout);
|
||||
+ timeout = session->s->timeout;
|
||||
update_child_status(session, SERVER_BUSY_READ, "idle");
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
H2_SSSN_LOG("", session, "enter idle, timeout = %d sec"),
|
||||
@@ -1707,8 +1712,8 @@ static void transit(h2_session *session, const char *action, h2_session_state ns
|
||||
}
|
||||
else if (session->open_streams) {
|
||||
s = "timeout";
|
||||
- timeout = session->s->keep_alive_timeout;
|
||||
- update_child_status(session, SERVER_BUSY_KEEPALIVE, "idle");
|
||||
+ timeout = session->s->timeout;
|
||||
+ update_child_status(session, SERVER_BUSY_READ, "idle");
|
||||
}
|
||||
else {
|
||||
/* normal keepalive setup */
|
||||
@@ -2166,6 +2171,14 @@ apr_status_t h2_session_process(h2_session *session, int async)
|
||||
session->have_read = 1;
|
||||
}
|
||||
else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) {
|
||||
+ status = h2_mplx_idle(session->mplx);
|
||||
+ if (status == APR_EAGAIN) {
|
||||
+ break;
|
||||
+ }
|
||||
+ else if (status != APR_SUCCESS) {
|
||||
+ dispatch_event(session, H2_SESSION_EV_CONN_ERROR,
|
||||
+ H2_ERR_ENHANCE_YOUR_CALM, "less is more");
|
||||
+ }
|
||||
status = APR_EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c
|
||||
index b5763ac..8c3d305 100644
|
||||
--- a/modules/http2/h2_stream.c
|
||||
+++ b/modules/http2/h2_stream.c
|
||||
@@ -397,13 +397,8 @@ apr_status_t h2_stream_send_frame(h2_stream *stream, int ftype, int flags, size_
|
||||
/* start pushed stream */
|
||||
ap_assert(stream->request == NULL);
|
||||
ap_assert(stream->rtmp != NULL);
|
||||
- status = h2_request_end_headers(stream->rtmp, stream->pool, 1, 0);
|
||||
- if (status != APR_SUCCESS) {
|
||||
- return status;
|
||||
- }
|
||||
- set_policy_for(stream, stream->rtmp);
|
||||
- stream->request = stream->rtmp;
|
||||
- stream->rtmp = NULL;
|
||||
+ status = h2_stream_end_headers(stream, 1, 0);
|
||||
+ if (status != APR_SUCCESS) goto leave;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -415,6 +410,7 @@ apr_status_t h2_stream_send_frame(h2_stream *stream, int ftype, int flags, size_
|
||||
if (status == APR_SUCCESS && eos) {
|
||||
status = transit(stream, on_event(stream, H2_SEV_CLOSED_L));
|
||||
}
|
||||
+leave:
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -455,13 +451,8 @@ apr_status_t h2_stream_recv_frame(h2_stream *stream, int ftype, int flags, size_
|
||||
* to abort the connection here, since this is clearly a protocol error */
|
||||
return APR_EINVAL;
|
||||
}
|
||||
- status = h2_request_end_headers(stream->rtmp, stream->pool, eos, frame_len);
|
||||
- if (status != APR_SUCCESS) {
|
||||
- return status;
|
||||
- }
|
||||
- set_policy_for(stream, stream->rtmp);
|
||||
- stream->request = stream->rtmp;
|
||||
- stream->rtmp = NULL;
|
||||
+ status = h2_stream_end_headers(stream, eos, frame_len);
|
||||
+ if (status != APR_SUCCESS) goto leave;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -472,6 +463,7 @@ apr_status_t h2_stream_recv_frame(h2_stream *stream, int ftype, int flags, size_
|
||||
if (status == APR_SUCCESS && eos) {
|
||||
status = transit(stream, on_event(stream, H2_SEV_CLOSED_R));
|
||||
}
|
||||
+leave:
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -683,6 +675,8 @@ static apr_status_t add_trailer(h2_stream *stream,
|
||||
hvalue = apr_pstrndup(stream->pool, value, vlen);
|
||||
h2_util_camel_case_header(hname, nlen);
|
||||
apr_table_mergen(stream->trailers, hname, hvalue);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
|
||||
+ H2_STRM_MSG(stream, "added trailer '%s: %s'"), hname, hvalue);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
@@ -702,15 +696,19 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
|
||||
if (name[0] == ':') {
|
||||
if ((vlen) > session->s->limit_req_line) {
|
||||
/* pseudo header: approximation of request line size check */
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
- H2_STRM_MSG(stream, "pseudo %s too long"), name);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, session->c,
|
||||
+ H2_STRM_LOG(APLOGNO(10178), stream,
|
||||
+ "Request pseudo header exceeds "
|
||||
+ "LimitRequestFieldSize: %s"), name);
|
||||
error = HTTP_REQUEST_URI_TOO_LARGE;
|
||||
}
|
||||
}
|
||||
else if ((nlen + 2 + vlen) > session->s->limit_req_fieldsize) {
|
||||
/* header too long */
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
- H2_STRM_MSG(stream, "header %s too long"), name);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, session->c,
|
||||
+ H2_STRM_LOG(APLOGNO(10180), stream,"Request header exceeds "
|
||||
+ "LimitRequestFieldSize: %.*s"),
|
||||
+ (int)H2MIN(nlen, 80), name);
|
||||
error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
|
||||
}
|
||||
|
||||
@@ -722,8 +720,9 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
|
||||
h2_stream_rst(stream, H2_ERR_ENHANCE_YOUR_CALM);
|
||||
return APR_ECONNRESET;
|
||||
}
|
||||
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
|
||||
- H2_STRM_MSG(stream, "too many header lines"));
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, session->c,
|
||||
+ H2_STRM_LOG(APLOGNO(10181), stream, "Number of request headers "
|
||||
+ "exceeds LimitRequestFields"));
|
||||
error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
|
||||
}
|
||||
|
||||
@@ -754,6 +753,47 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
|
||||
return status;
|
||||
}
|
||||
|
||||
+typedef struct {
|
||||
+ apr_size_t maxlen;
|
||||
+ const char *failed_key;
|
||||
+} val_len_check_ctx;
|
||||
+
|
||||
+static int table_check_val_len(void *baton, const char *key, const char *value)
|
||||
+{
|
||||
+ val_len_check_ctx *ctx = baton;
|
||||
+
|
||||
+ if (strlen(value) <= ctx->maxlen) return 1;
|
||||
+ ctx->failed_key = key;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+apr_status_t h2_stream_end_headers(h2_stream *stream, int eos, size_t raw_bytes)
|
||||
+{
|
||||
+ apr_status_t status;
|
||||
+ val_len_check_ctx ctx;
|
||||
+
|
||||
+ status = h2_request_end_headers(stream->rtmp, stream->pool, eos, raw_bytes);
|
||||
+ if (APR_SUCCESS == status) {
|
||||
+ set_policy_for(stream, stream->rtmp);
|
||||
+ stream->request = stream->rtmp;
|
||||
+ stream->rtmp = NULL;
|
||||
+
|
||||
+ ctx.maxlen = stream->session->s->limit_req_fieldsize;
|
||||
+ ctx.failed_key = NULL;
|
||||
+ apr_table_do(table_check_val_len, &ctx, stream->request->headers, NULL);
|
||||
+ if (ctx.failed_key) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, stream->session->c,
|
||||
+ H2_STRM_LOG(APLOGNO(), stream,"Request header exceeds "
|
||||
+ "LimitRequestFieldSize: %.*s"),
|
||||
+ (int)H2MIN(strlen(ctx.failed_key), 80), ctx.failed_key);
|
||||
+ set_error_response(stream, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
|
||||
+ /* keep on returning APR_SUCCESS, so that we send a HTTP response and
|
||||
+ * do not RST the stream. */
|
||||
+ }
|
||||
+ }
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
static apr_bucket *get_first_headers_bucket(apr_bucket_brigade *bb)
|
||||
{
|
||||
if (bb) {
|
||||
diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h
|
||||
index 7ecc0ad..79cb39d 100644
|
||||
--- a/modules/http2/h2_stream.h
|
||||
+++ b/modules/http2/h2_stream.h
|
||||
@@ -198,6 +198,10 @@ apr_status_t h2_stream_set_request_rec(h2_stream *stream,
|
||||
apr_status_t h2_stream_add_header(h2_stream *stream,
|
||||
const char *name, size_t nlen,
|
||||
const char *value, size_t vlen);
|
||||
+
|
||||
+/* End the contruction of request headers */
|
||||
+apr_status_t h2_stream_end_headers(h2_stream *stream, int eos, size_t raw_bytes);
|
||||
+
|
||||
|
||||
apr_status_t h2_stream_send_frame(h2_stream *stream, int frame_type, int flags, size_t frame_len);
|
||||
apr_status_t h2_stream_recv_frame(h2_stream *stream, int frame_type, int flags, size_t frame_len);
|
||||
diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c
|
||||
index a395807..c312459 100644
|
||||
--- a/modules/http2/h2_task.c
|
||||
+++ b/modules/http2/h2_task.c
|
||||
@@ -408,8 +408,15 @@ int h2_task_can_redo(h2_task *task) {
|
||||
|| !strcmp("OPTIONS", task->request->method));
|
||||
}
|
||||
|
||||
+int h2_task_has_started(h2_task *task)
|
||||
+{
|
||||
+ return task && task->started_at != 0;
|
||||
+}
|
||||
+
|
||||
void h2_task_redo(h2_task *task)
|
||||
{
|
||||
+ task->started_at = 0;
|
||||
+ task->worker_done = 0;
|
||||
task->rst_error = 0;
|
||||
}
|
||||
|
||||
@@ -548,7 +555,6 @@ apr_status_t h2_task_do(h2_task *task, apr_thread_t *thread, int worker_id)
|
||||
ap_assert(task);
|
||||
c = task->c;
|
||||
task->worker_started = 1;
|
||||
- task->started_at = apr_time_now();
|
||||
|
||||
if (c->master) {
|
||||
/* Each conn_rec->id is supposed to be unique at a point in time. Since
|
||||
diff --git a/modules/http2/h2_task.h b/modules/http2/h2_task.h
|
||||
index 20be429..9a7ad68 100644
|
||||
--- a/modules/http2/h2_task.h
|
||||
+++ b/modules/http2/h2_task.h
|
||||
@@ -80,6 +80,7 @@ struct h2_task {
|
||||
|
||||
unsigned int filters_set : 1;
|
||||
unsigned int worker_started : 1; /* h2_worker started processing */
|
||||
+ unsigned int redo : 1; /* was throttled, should be restarted later */
|
||||
|
||||
int worker_done; /* h2_worker finished */
|
||||
int done_done; /* task_done has been handled */
|
||||
@@ -101,6 +102,7 @@ apr_status_t h2_task_do(h2_task *task, apr_thread_t *thread, int worker_id);
|
||||
|
||||
void h2_task_redo(h2_task *task);
|
||||
int h2_task_can_redo(h2_task *task);
|
||||
+int h2_task_has_started(h2_task *task);
|
||||
|
||||
/**
|
||||
* Reset the task with the given error code, resets all input/output.
|
||||
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
|
||||
index 048ae61..7a8a197 100644
|
||||
--- a/server/mpm/event/event.c
|
||||
+++ b/server/mpm/event/event.c
|
||||
@@ -1112,10 +1112,11 @@ read_request:
|
||||
"network write failure in core output filter");
|
||||
cs->pub.state = CONN_STATE_LINGER;
|
||||
}
|
||||
- else if (c->data_in_output_filters) {
|
||||
+ else if (c->data_in_output_filters ||
|
||||
+ cs->pub.sense == CONN_SENSE_WANT_READ) {
|
||||
/* Still in WRITE_COMPLETION_STATE:
|
||||
- * Set a write timeout for this connection, and let the
|
||||
- * event thread poll for writeability.
|
||||
+ * Set a read/write timeout for this connection, and let the
|
||||
+ * event thread poll for read/writeability.
|
||||
*/
|
||||
cs->queue_timestamp = apr_time_now();
|
||||
notify_suspend(cs);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
From f11d5830759eb50ed366fc0690f9f4f491064ea3 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Tue, 11 Feb 2020 13:16:38 +0000
|
||||
Subject: [PATCH 1/2] Merge r1873747 from trunk:
|
||||
|
||||
factor out default regex flags
|
||||
|
||||
Submitted by: covener
|
||||
Reviewed by: covener, minfrin, jorton
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1873905 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
include/ap_mmn.h | 1 +
|
||||
include/ap_regex.h | 2 ++
|
||||
server/core.c | 2 +-
|
||||
server/util_pcre.c | 3 +--
|
||||
4 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
|
||||
index 839228e..f5043ef 100644
|
||||
--- a/include/ap_mmn.h
|
||||
+++ b/include/ap_mmn.h
|
||||
@@ -515,6 +515,7 @@
|
||||
* 20120211.77 (2.4.34-dev) Add ap_exists_directive()
|
||||
* 20120211.78 (2.4.34-dev) Add response_field_size to proxy_worker_shared
|
||||
* 20120211.79 (2.4.34-dev) Add AP_GETLINE_NOSPC_EOL flag to http_protocol.h
|
||||
+ * 20120211.90 (2.4.42-dev) AP_REG_DEFAULT macro in ap_regex.h
|
||||
*/
|
||||
|
||||
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
|
||||
diff --git a/include/ap_regex.h b/include/ap_regex.h
|
||||
index 7d8df79..e651eea 100644
|
||||
--- a/include/ap_regex.h
|
||||
+++ b/include/ap_regex.h
|
||||
@@ -86,6 +86,8 @@ extern "C" {
|
||||
|
||||
#define AP_REG_MATCH "MATCH_" /** suggested prefix for ap_regname */
|
||||
|
||||
+#define AP_REG_DEFAULT (AP_REG_DOTALL|AP_REG_DOLLAR_ENDONLY)
|
||||
+
|
||||
/* Error values: */
|
||||
enum {
|
||||
AP_REG_ASSERT = 1, /** internal error ? */
|
||||
diff --git a/server/core.c b/server/core.c
|
||||
index e892c87..a8772a3 100644
|
||||
--- a/server/core.c
|
||||
+++ b/server/core.c
|
||||
@@ -4938,7 +4938,7 @@ static int core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptem
|
||||
apr_pool_cleanup_register(pconf, NULL, reset_config_defines,
|
||||
apr_pool_cleanup_null);
|
||||
|
||||
- ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY);
|
||||
+ ap_regcomp_set_default_cflags(AP_REG_DEFAULT);
|
||||
|
||||
mpm_common_pre_config(pconf);
|
||||
|
||||
diff --git a/server/util_pcre.c b/server/util_pcre.c
|
||||
index 35831f5..74722b4 100644
|
||||
--- a/server/util_pcre.c
|
||||
+++ b/server/util_pcre.c
|
||||
@@ -120,8 +120,7 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg)
|
||||
* Compile a regular expression *
|
||||
*************************************************/
|
||||
|
||||
-static int default_cflags = AP_REG_DOTALL |
|
||||
- AP_REG_DOLLAR_ENDONLY;
|
||||
+static int default_cflags = AP_REG_DEFAULT;
|
||||
|
||||
AP_DECLARE(int) ap_regcomp_get_default_cflags(void)
|
||||
{
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
From ff36010963d1c2f2e6b331aa6d7d7d879e3975f6 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Covener <covener@apache.org>
|
||||
Date: Wed, 19 Feb 2020 12:26:31 +0000
|
||||
Subject: [PATCH 2/2] add AP_REG_NO_DEFAULT to allow opt-out of pcre defaults
|
||||
|
||||
... and use it in mod_substitute to avoid DOTALL
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1874191 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
include/ap_mmn.h | 1 +
|
||||
include/ap_regex.h | 4 +++-
|
||||
modules/filters/mod_substitute.c | 6 ++++--
|
||||
server/util_pcre.c | 4 +++-
|
||||
server/util_regex.c | 3 ++-
|
||||
5 files changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
|
||||
index f5043ef..4c74e56 100644
|
||||
--- a/include/ap_mmn.h
|
||||
+++ b/include/ap_mmn.h
|
||||
@@ -516,6 +516,7 @@
|
||||
* 20120211.78 (2.4.34-dev) Add response_field_size to proxy_worker_shared
|
||||
* 20120211.79 (2.4.34-dev) Add AP_GETLINE_NOSPC_EOL flag to http_protocol.h
|
||||
* 20120211.90 (2.4.42-dev) AP_REG_DEFAULT macro in ap_regex.h
|
||||
+ * 20120211.92 (2.4.42-dev) AP_REG_NO_DEFAULT macro in ap_regex.h
|
||||
*/
|
||||
|
||||
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
|
||||
diff --git a/include/ap_regex.h b/include/ap_regex.h
|
||||
index e651eea..7af2f99 100644
|
||||
--- a/include/ap_regex.h
|
||||
+++ b/include/ap_regex.h
|
||||
@@ -84,7 +84,9 @@ extern "C" {
|
||||
|
||||
#define AP_REG_DOLLAR_ENDONLY 0x200 /* '$' matches at end of subject string only */
|
||||
|
||||
-#define AP_REG_MATCH "MATCH_" /** suggested prefix for ap_regname */
|
||||
+#define AP_REG_NO_DEFAULT 0x400 /**< Don't implicitely add AP_REG_DEFAULT options */
|
||||
+
|
||||
+#define AP_REG_MATCH "MATCH_" /**< suggested prefix for ap_regname */
|
||||
|
||||
#define AP_REG_DEFAULT (AP_REG_DOTALL|AP_REG_DOLLAR_ENDONLY)
|
||||
|
||||
diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c
|
||||
index b7d5296..e976c51 100644
|
||||
--- a/modules/filters/mod_substitute.c
|
||||
+++ b/modules/filters/mod_substitute.c
|
||||
@@ -667,8 +667,10 @@ static const char *set_pattern(cmd_parms *cmd, void *cfg, const char *line)
|
||||
|
||||
/* first see if we can compile the regex */
|
||||
if (!is_pattern) {
|
||||
- r = ap_pregcomp(cmd->pool, from, AP_REG_EXTENDED |
|
||||
- (ignore_case ? AP_REG_ICASE : 0));
|
||||
+ int flags = AP_REG_NO_DEFAULT
|
||||
+ | (ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY)
|
||||
+ | (ignore_case ? AP_REG_ICASE : 0);
|
||||
+ r = ap_pregcomp(cmd->pool, from, flags);
|
||||
if (!r)
|
||||
return "Substitute could not compile regex";
|
||||
}
|
||||
diff --git a/server/util_pcre.c b/server/util_pcre.c
|
||||
index 74722b4..8819871 100644
|
||||
--- a/server/util_pcre.c
|
||||
+++ b/server/util_pcre.c
|
||||
@@ -168,7 +168,9 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags)
|
||||
int errcode = 0;
|
||||
int options = PCRE_DUPNAMES;
|
||||
|
||||
- cflags |= default_cflags;
|
||||
+ if ((cflags & AP_REG_NO_DEFAULT) == 0)
|
||||
+ cflags |= default_cflags;
|
||||
+
|
||||
if ((cflags & AP_REG_ICASE) != 0)
|
||||
options |= PCRE_CASELESS;
|
||||
if ((cflags & AP_REG_NEWLINE) != 0)
|
||||
diff --git a/server/util_regex.c b/server/util_regex.c
|
||||
index 2a30d68..5405f8d 100644
|
||||
--- a/server/util_regex.c
|
||||
+++ b/server/util_regex.c
|
||||
@@ -94,6 +94,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool,
|
||||
}
|
||||
|
||||
/* anything after the current delimiter is flags */
|
||||
+ ret->flags = ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY;
|
||||
while (*++endp) {
|
||||
switch (*endp) {
|
||||
case 'i': ret->flags |= AP_REG_ICASE; break;
|
||||
@@ -106,7 +107,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool,
|
||||
default: break; /* we should probably be stricter here */
|
||||
}
|
||||
}
|
||||
- if (ap_regcomp(&ret->rx, rxstr, ret->flags) == 0) {
|
||||
+ if (ap_regcomp(&ret->rx, rxstr, AP_REG_NO_DEFAULT | ret->flags) == 0) {
|
||||
apr_pool_cleanup_register(pool, &ret->rx, rxplus_cleanup,
|
||||
apr_pool_cleanup_null);
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
From 0b59e8ce2d978dfd6b74473df4e1309a5c226498 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Tue, 11 Feb 2020 13:14:42 +0000
|
||||
Subject: [PATCH] Merge r1873745 from trunk:
|
||||
|
||||
trap bad FTP responses
|
||||
|
||||
Submitted by: covener
|
||||
Reviewed by: covener, minfrin, jorton
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1873904 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/proxy/mod_proxy_ftp.c | 20 +++++++++++++++-----
|
||||
1 file changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
|
||||
index 1557301..6318102 100644
|
||||
--- a/modules/proxy/mod_proxy_ftp.c
|
||||
+++ b/modules/proxy/mod_proxy_ftp.c
|
||||
@@ -218,7 +218,7 @@ static int ftp_check_string(const char *x)
|
||||
* (EBCDIC) machines either.
|
||||
*/
|
||||
static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb,
|
||||
- char *buff, apr_size_t bufflen, int *eos)
|
||||
+ char *buff, apr_size_t bufflen, int *eos, apr_size_t *outlen)
|
||||
{
|
||||
apr_bucket *e;
|
||||
apr_status_t rv;
|
||||
@@ -230,6 +230,7 @@ static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb,
|
||||
/* start with an empty string */
|
||||
buff[0] = 0;
|
||||
*eos = 0;
|
||||
+ *outlen = 0;
|
||||
|
||||
/* loop through each brigade */
|
||||
while (!found) {
|
||||
@@ -273,6 +274,7 @@ static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb,
|
||||
if (len > 0) {
|
||||
memcpy(pos, response, len);
|
||||
pos += len;
|
||||
+ *outlen += len;
|
||||
}
|
||||
}
|
||||
apr_bucket_delete(e);
|
||||
@@ -385,28 +387,36 @@ static int ftp_getrc_msg(conn_rec *ftp_ctrl, apr_bucket_brigade *bb, char *msgbu
|
||||
char buff[5];
|
||||
char *mb = msgbuf, *me = &msgbuf[msglen];
|
||||
apr_status_t rv;
|
||||
+ apr_size_t nread;
|
||||
+
|
||||
int eos;
|
||||
|
||||
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
|
||||
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(03233)
|
||||
"<%s", response);
|
||||
*/
|
||||
+ if (nread < 4) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(10229) "Malformed FTP response '%s'", response);
|
||||
+ *mb = '\0';
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
|
||||
- !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
|
||||
+ !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
|
||||
status = 0;
|
||||
else
|
||||
status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0';
|
||||
|
||||
mb = apr_cpystrn(mb, response + 4, me - mb);
|
||||
|
||||
- if (response[3] == '-') {
|
||||
+ if (response[3] == '-') { /* multi-line reply "123-foo\nbar\n123 baz" */
|
||||
memcpy(buff, response, 3);
|
||||
buff[3] = ' ';
|
||||
do {
|
||||
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
|
||||
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) {
|
||||
return -1;
|
||||
}
|
||||
mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,699 +0,0 @@
|
||||
From 98928d02d2473ceb9f81b1c3bc527f8b0a0039e6 Mon Sep 17 00:00:00 2001
|
||||
From: Graham Leggett <minfrin@apache.org>
|
||||
Date: Fri, 21 Sep 2018 13:30:15 +0000
|
||||
Subject: [PATCH 188/504] MPMs: Initialize all runtime/asynchronous objects on
|
||||
a dedicated pool and before signals handling to avoid lifetime issues on
|
||||
restart or shutdown. PR 62658. trunk patch: http://svn.apache.org/r1835845
|
||||
http://svn.apache.org/r1835846
|
||||
http://svn.apache.org/r1837354 http://svn.apache.org/r1837356
|
||||
http://svn.apache.org/r1839571
|
||||
http://svn.apache.org/r1839583 2.4.x patch:
|
||||
http://home.apache.org/~ylavic/patches/2.4.x-mpms_async_objects_lifetime.patch
|
||||
+1: ylavic, jim (but not for 2.4.35), minfrin
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1841586 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 +
|
||||
STATUS | 11 --
|
||||
server/mpm/event/event.c | 203 +++++++++++++++------------
|
||||
server/mpm/mpmt_os2/mpmt_os2_child.c | 1 +
|
||||
server/mpm/netware/mpm_netware.c | 1 +
|
||||
server/mpm/prefork/prefork.c | 6 +-
|
||||
server/mpm/winnt/child.c | 3 +
|
||||
server/mpm/winnt/mpm_winnt.c | 1 +
|
||||
server/mpm/worker/worker.c | 148 +++++++++++--------
|
||||
9 files changed, 215 insertions(+), 163 deletions(-)
|
||||
|
||||
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
|
||||
index f07b757ab9..ffe8a23cbd 100644
|
||||
--- a/server/mpm/event/event.c
|
||||
+++ b/server/mpm/event/event.c
|
||||
@@ -436,6 +436,7 @@ int raise_sigstop_flags;
|
||||
|
||||
static apr_pool_t *pconf; /* Pool for config stuff */
|
||||
static apr_pool_t *pchild; /* Pool for httpd child stuff */
|
||||
+static apr_pool_t *pruntime; /* Pool for MPM threads stuff */
|
||||
|
||||
static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
|
||||
thread. Use this instead */
|
||||
@@ -709,10 +710,10 @@ static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen
|
||||
|
||||
static void event_note_child_started(int slot, pid_t pid)
|
||||
{
|
||||
+ ap_generation_t gen = retained->mpm->my_generation;
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
- ap_run_child_status(ap_server_conf,
|
||||
- ap_scoreboard_image->parent[slot].pid,
|
||||
- retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
+ ap_scoreboard_image->parent[slot].generation = gen;
|
||||
+ ap_run_child_status(ap_server_conf, pid, gen, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
static const char *event_get_name(void)
|
||||
@@ -1270,36 +1271,6 @@ static void dummy_signal_handler(int sig)
|
||||
}
|
||||
|
||||
|
||||
-static apr_status_t init_pollset(apr_pool_t *p)
|
||||
-{
|
||||
- ap_listen_rec *lr;
|
||||
- listener_poll_type *pt;
|
||||
- int i = 0;
|
||||
-
|
||||
- listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
|
||||
- for (lr = my_bucket->listeners; lr != NULL; lr = lr->next, i++) {
|
||||
- apr_pollfd_t *pfd;
|
||||
- AP_DEBUG_ASSERT(i < num_listensocks);
|
||||
- pfd = &listener_pollfd[i];
|
||||
- pt = apr_pcalloc(p, sizeof(*pt));
|
||||
- pfd->desc_type = APR_POLL_SOCKET;
|
||||
- pfd->desc.s = lr->sd;
|
||||
- pfd->reqevents = APR_POLLIN;
|
||||
-
|
||||
- pt->type = PT_ACCEPT;
|
||||
- pt->baton = lr;
|
||||
-
|
||||
- pfd->client_data = pt;
|
||||
-
|
||||
- apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
|
||||
- apr_pollset_add(event_pollset, pfd);
|
||||
-
|
||||
- lr->accept_func = ap_unixd_accept;
|
||||
- }
|
||||
-
|
||||
- return APR_SUCCESS;
|
||||
-}
|
||||
-
|
||||
static apr_status_t push_timer2worker(timer_event_t* te)
|
||||
{
|
||||
return ap_queue_push_timer(worker_queue, te);
|
||||
@@ -1611,7 +1582,6 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
|
||||
proc_info *ti = dummy;
|
||||
int process_slot = ti->pslot;
|
||||
struct process_score *ps = ap_get_scoreboard_process(process_slot);
|
||||
- apr_pool_t *tpool = apr_thread_pool_get(thd);
|
||||
int closed = 0;
|
||||
int have_idle_worker = 0;
|
||||
apr_time_t last_log;
|
||||
@@ -1619,16 +1589,6 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
|
||||
last_log = apr_time_now();
|
||||
free(ti);
|
||||
|
||||
- rc = init_pollset(tpool);
|
||||
- if (rc != APR_SUCCESS) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
|
||||
- "failed to initialize pollset, "
|
||||
- "shutdown process now");
|
||||
- resource_shortage = 1;
|
||||
- signal_threads(ST_UNGRACEFUL);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
/* Unblock the signal used to wake this thread up, and set a handler for
|
||||
* it.
|
||||
*/
|
||||
@@ -2168,8 +2128,6 @@ static int check_signal(int signum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
-
|
||||
static void create_listener_thread(thread_starter * ts)
|
||||
{
|
||||
int my_child_num = ts->child_num_arg;
|
||||
@@ -2181,7 +2139,7 @@ static void create_listener_thread(thread_starter * ts)
|
||||
my_info->pslot = my_child_num;
|
||||
my_info->tslot = -1; /* listener thread doesn't have a thread slot */
|
||||
rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
|
||||
- my_info, pchild);
|
||||
+ my_info, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00474)
|
||||
"apr_thread_create: unable to create listener thread");
|
||||
@@ -2191,25 +2149,12 @@ static void create_listener_thread(thread_starter * ts)
|
||||
apr_os_thread_get(&listener_os_thread, ts->listener);
|
||||
}
|
||||
|
||||
-/* XXX under some circumstances not understood, children can get stuck
|
||||
- * in start_threads forever trying to take over slots which will
|
||||
- * never be cleaned up; for now there is an APLOG_DEBUG message issued
|
||||
- * every so often when this condition occurs
|
||||
- */
|
||||
-static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
+static void setup_threads_runtime(void)
|
||||
{
|
||||
- thread_starter *ts = dummy;
|
||||
- apr_thread_t **threads = ts->threads;
|
||||
- apr_threadattr_t *thread_attr = ts->threadattr;
|
||||
- int my_child_num = ts->child_num_arg;
|
||||
- proc_info *my_info;
|
||||
apr_status_t rv;
|
||||
- int i;
|
||||
- int threads_created = 0;
|
||||
- int listener_started = 0;
|
||||
- int loops;
|
||||
- int prev_threads_created;
|
||||
- int max_recycled_pools = -1;
|
||||
+ ap_listen_rec *lr;
|
||||
+ apr_pool_t *pskip = NULL;
|
||||
+ int max_recycled_pools = -1, i;
|
||||
const int good_methods[] = { APR_POLLSET_KQUEUE,
|
||||
APR_POLLSET_PORT,
|
||||
APR_POLLSET_EPOLL };
|
||||
@@ -2218,10 +2163,39 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
const apr_uint32_t pollset_size = (apr_uint32_t)num_listensocks +
|
||||
(apr_uint32_t)threads_per_child *
|
||||
(async_factor > 2 ? async_factor : 2);
|
||||
+ int pollset_flags;
|
||||
+
|
||||
+ /* Event's skiplist operations will happen concurrently with other modules'
|
||||
+ * runtime so they need their own pool for allocations, and its lifetime
|
||||
+ * should be at least the one of the connections (ptrans). Thus pskip is
|
||||
+ * created as a subpool of pconf like/before ptrans (before so that it's
|
||||
+ * destroyed after). In forked mode pconf is never destroyed so we are good
|
||||
+ * anyway, but in ONE_PROCESS mode this ensures that the skiplist works
|
||||
+ * from connection/ptrans cleanups (even after pchild is destroyed).
|
||||
+ */
|
||||
+ apr_pool_create(&pskip, pconf);
|
||||
+ apr_pool_tag(pskip, "mpm_skiplist");
|
||||
+ apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pskip);
|
||||
+ APR_RING_INIT(&timer_free_ring, timer_event_t, link);
|
||||
+ apr_skiplist_init(&timer_skiplist, pskip);
|
||||
+ apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
|
||||
+
|
||||
+ /* All threads (listener, workers) and synchronization objects (queues,
|
||||
+ * pollset, mutexes...) created here should have at least the lifetime of
|
||||
+ * the connections they handle (i.e. ptrans). We can't use this thread's
|
||||
+ * self pool because all these objects survive it, nor use pchild or pconf
|
||||
+ * directly because this starter thread races with other modules' runtime,
|
||||
+ * nor finally pchild (or subpool thereof) because it is killed explicitely
|
||||
+ * before pconf (thus connections/ptrans can live longer, which matters in
|
||||
+ * ONE_PROCESS mode). So this leaves us with a subpool of pconf, created
|
||||
+ * before any ptrans hence destroyed after.
|
||||
+ */
|
||||
+ apr_pool_create(&pruntime, pconf);
|
||||
+ apr_pool_tag(pruntime, "mpm_runtime");
|
||||
|
||||
/* We must create the fd queues before we start up the listener
|
||||
* and worker threads. */
|
||||
- rv = ap_queue_create(&worker_queue, threads_per_child, pchild);
|
||||
+ rv = ap_queue_create(&worker_queue, threads_per_child, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03100)
|
||||
"ap_queue_create() failed");
|
||||
@@ -2235,7 +2209,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
*/
|
||||
max_recycled_pools = threads_per_child * 3 / 4 ;
|
||||
}
|
||||
- rv = ap_queue_info_create(&worker_queue_info, pchild,
|
||||
+ rv = ap_queue_info_create(&worker_queue_info, pruntime,
|
||||
threads_per_child, max_recycled_pools);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03101)
|
||||
@@ -2247,7 +2221,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
* thread starts.
|
||||
*/
|
||||
rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
|
||||
- pchild);
|
||||
+ pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03102)
|
||||
"creation of the timeout mutex failed.");
|
||||
@@ -2255,25 +2229,30 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
}
|
||||
|
||||
/* Create the main pollset */
|
||||
+ pollset_flags = APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY |
|
||||
+ APR_POLLSET_NODEFAULT | APR_POLLSET_WAKEABLE;
|
||||
for (i = 0; i < sizeof(good_methods) / sizeof(good_methods[0]); i++) {
|
||||
- apr_uint32_t flags = APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY |
|
||||
- APR_POLLSET_NODEFAULT | APR_POLLSET_WAKEABLE;
|
||||
- rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
|
||||
- good_methods[i]);
|
||||
+ rv = apr_pollset_create_ex(&event_pollset, pollset_size, pruntime,
|
||||
+ pollset_flags, good_methods[i]);
|
||||
if (rv == APR_SUCCESS) {
|
||||
listener_is_wakeable = 1;
|
||||
break;
|
||||
}
|
||||
- flags &= ~APR_POLLSET_WAKEABLE;
|
||||
- rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
|
||||
- good_methods[i]);
|
||||
- if (rv == APR_SUCCESS) {
|
||||
- break;
|
||||
+ }
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ pollset_flags &= ~APR_POLLSET_WAKEABLE;
|
||||
+ for (i = 0; i < sizeof(good_methods) / sizeof(good_methods[0]); i++) {
|
||||
+ rv = apr_pollset_create_ex(&event_pollset, pollset_size, pruntime,
|
||||
+ pollset_flags, good_methods[i]);
|
||||
+ if (rv == APR_SUCCESS) {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
if (rv != APR_SUCCESS) {
|
||||
- rv = apr_pollset_create(&event_pollset, pollset_size, pchild,
|
||||
- APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
|
||||
+ pollset_flags &= ~APR_POLLSET_NODEFAULT;
|
||||
+ rv = apr_pollset_create(&event_pollset, pollset_size, pruntime,
|
||||
+ pollset_flags);
|
||||
}
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03103)
|
||||
@@ -2281,12 +2260,57 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
+ /* Add listeners to the main pollset */
|
||||
+ listener_pollfd = apr_pcalloc(pruntime, num_listensocks *
|
||||
+ sizeof(apr_pollfd_t));
|
||||
+ for (i = 0, lr = my_bucket->listeners; lr; lr = lr->next, i++) {
|
||||
+ apr_pollfd_t *pfd;
|
||||
+ listener_poll_type *pt;
|
||||
+
|
||||
+ AP_DEBUG_ASSERT(i < num_listensocks);
|
||||
+ pfd = &listener_pollfd[i];
|
||||
+
|
||||
+ pfd->reqevents = APR_POLLIN;
|
||||
+ pfd->desc_type = APR_POLL_SOCKET;
|
||||
+ pfd->desc.s = lr->sd;
|
||||
+
|
||||
+ pt = apr_pcalloc(pruntime, sizeof(*pt));
|
||||
+ pfd->client_data = pt;
|
||||
+ pt->type = PT_ACCEPT;
|
||||
+ pt->baton = lr;
|
||||
+
|
||||
+ apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
|
||||
+ apr_pollset_add(event_pollset, pfd);
|
||||
+
|
||||
+ lr->accept_func = ap_unixd_accept;
|
||||
+ }
|
||||
+
|
||||
+ worker_sockets = apr_pcalloc(pruntime, threads_per_child *
|
||||
+ sizeof(apr_socket_t *));
|
||||
+}
|
||||
+
|
||||
+/* XXX under some circumstances not understood, children can get stuck
|
||||
+ * in start_threads forever trying to take over slots which will
|
||||
+ * never be cleaned up; for now there is an APLOG_DEBUG message issued
|
||||
+ * every so often when this condition occurs
|
||||
+ */
|
||||
+static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
+{
|
||||
+ thread_starter *ts = dummy;
|
||||
+ apr_thread_t **threads = ts->threads;
|
||||
+ apr_threadattr_t *thread_attr = ts->threadattr;
|
||||
+ int my_child_num = ts->child_num_arg;
|
||||
+ proc_info *my_info;
|
||||
+ apr_status_t rv;
|
||||
+ int threads_created = 0;
|
||||
+ int listener_started = 0;
|
||||
+ int prev_threads_created;
|
||||
+ int loops, i;
|
||||
+
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02471)
|
||||
"start_threads: Using %s (%swakeable)",
|
||||
apr_pollset_method_name(event_pollset),
|
||||
listener_is_wakeable ? "" : "not ");
|
||||
- worker_sockets = apr_pcalloc(pchild, threads_per_child
|
||||
- * sizeof(apr_socket_t *));
|
||||
|
||||
loops = prev_threads_created = 0;
|
||||
while (1) {
|
||||
@@ -2310,7 +2334,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
|
||||
* done because it lets us deal with tid better.
|
||||
*/
|
||||
rv = apr_thread_create(&threads[i], thread_attr,
|
||||
- worker_thread, my_info, pchild);
|
||||
+ worker_thread, my_info, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
|
||||
APLOGNO(03104)
|
||||
@@ -2431,7 +2455,6 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
apr_threadattr_t *thread_attr;
|
||||
apr_thread_t *start_thread_id;
|
||||
int i;
|
||||
- apr_pool_t *pskip;
|
||||
|
||||
/* for benefit of any hooks that run as this child initializes */
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
@@ -2439,7 +2462,12 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
ap_my_pid = getpid();
|
||||
ap_child_slot = child_num_arg;
|
||||
ap_fatal_signal_child_setup(ap_server_conf);
|
||||
+
|
||||
+ /* Get a sub context for global allocations in this child, so that
|
||||
+ * we can have cleanups occur when the child exits.
|
||||
+ */
|
||||
apr_pool_create(&pchild, pconf);
|
||||
+ apr_pool_tag(pchild, "pchild");
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
@@ -2457,12 +2485,6 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
- apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
|
||||
- APR_RING_INIT(&timer_free_ring, timer_event_t, link);
|
||||
- apr_pool_create(&pskip, pchild);
|
||||
- apr_skiplist_init(&timer_skiplist, pskip);
|
||||
- apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
|
||||
-
|
||||
/* Just use the standard apr_setup_signal_thread to block all signals
|
||||
* from being received. The child processes no longer use signals for
|
||||
* any communication with the parent process. Let's also do this before
|
||||
@@ -2486,7 +2508,10 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
conns_this_child = APR_INT32_MAX;
|
||||
}
|
||||
|
||||
- /* Setup worker threads */
|
||||
+ /* Setup threads */
|
||||
+
|
||||
+ /* Globals used by signal_threads() so to be initialized before */
|
||||
+ setup_threads_runtime();
|
||||
|
||||
/* clear the storage; we may not create all our threads immediately,
|
||||
* and we want a 0 entry to indicate a thread which was not created
|
||||
diff --git a/server/mpm/mpmt_os2/mpmt_os2_child.c b/server/mpm/mpmt_os2/mpmt_os2_child.c
|
||||
index ca9f594754..bb7e1369ea 100644
|
||||
--- a/server/mpm/mpmt_os2/mpmt_os2_child.c
|
||||
+++ b/server/mpm/mpmt_os2/mpmt_os2_child.c
|
||||
@@ -110,6 +110,7 @@ void ap_mpm_child_main(apr_pool_t *pconf)
|
||||
|
||||
/* Create pool for child */
|
||||
apr_pool_create(&pchild, pconf);
|
||||
+ apr_pool_tag(pchild, "pchild");
|
||||
|
||||
ap_run_child_init(pchild, ap_server_conf);
|
||||
|
||||
diff --git a/server/mpm/netware/mpm_netware.c b/server/mpm/netware/mpm_netware.c
|
||||
index 2fab52f598..82480334b8 100644
|
||||
--- a/server/mpm/netware/mpm_netware.c
|
||||
+++ b/server/mpm/netware/mpm_netware.c
|
||||
@@ -886,6 +886,7 @@ static int netware_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
|
||||
/* Only set slot 0 since that is all NetWare will ever have. */
|
||||
ap_scoreboard_image->parent[0].pid = getpid();
|
||||
+ ap_scoreboard_image->parent[0].generation = ap_my_generation;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[0].pid,
|
||||
ap_my_generation,
|
||||
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
|
||||
index 3fb328467d..8efda72ee1 100644
|
||||
--- a/server/mpm/prefork/prefork.c
|
||||
+++ b/server/mpm/prefork/prefork.c
|
||||
@@ -208,10 +208,10 @@ static void prefork_note_child_killed(int childnum, pid_t pid,
|
||||
|
||||
static void prefork_note_child_started(int slot, pid_t pid)
|
||||
{
|
||||
+ ap_generation_t gen = retained->mpm->my_generation;
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
- ap_run_child_status(ap_server_conf,
|
||||
- ap_scoreboard_image->parent[slot].pid,
|
||||
- retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
+ ap_scoreboard_image->parent[slot].generation = gen;
|
||||
+ ap_run_child_status(ap_server_conf, pid, gen, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
/* a clean exit from a child with proper cleanup */
|
||||
diff --git a/server/mpm/winnt/child.c b/server/mpm/winnt/child.c
|
||||
index 9ddba18f80..21755f398c 100644
|
||||
--- a/server/mpm/winnt/child.c
|
||||
+++ b/server/mpm/winnt/child.c
|
||||
@@ -917,6 +917,9 @@ void child_main(apr_pool_t *pconf, DWORD parent_pid)
|
||||
int i;
|
||||
int num_events;
|
||||
|
||||
+ /* Get a sub context for global allocations in this child, so that
|
||||
+ * we can have cleanups occur when the child exits.
|
||||
+ */
|
||||
apr_pool_create(&pchild, pconf);
|
||||
apr_pool_tag(pchild, "pchild");
|
||||
|
||||
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
|
||||
index 2487e45be2..3d71f80e72 100644
|
||||
--- a/server/mpm/winnt/mpm_winnt.c
|
||||
+++ b/server/mpm/winnt/mpm_winnt.c
|
||||
@@ -139,6 +139,7 @@ AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
|
||||
static void winnt_note_child_started(int slot, pid_t pid)
|
||||
{
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
+ ap_scoreboard_image->parent[slot].generation = my_generation;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[slot].pid,
|
||||
my_generation, slot, MPM_CHILD_STARTED);
|
||||
diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
|
||||
index 7804efc457..8012fe29d8 100644
|
||||
--- a/server/mpm/worker/worker.c
|
||||
+++ b/server/mpm/worker/worker.c
|
||||
@@ -134,6 +134,8 @@ static int num_listensocks = 0;
|
||||
static int resource_shortage = 0;
|
||||
static fd_queue_t *worker_queue;
|
||||
static fd_queue_info_t *worker_queue_info;
|
||||
+static apr_pollset_t *worker_pollset;
|
||||
+
|
||||
|
||||
/* data retained by worker across load/unload of the module
|
||||
* allocated on first call to pre-config hook; located on
|
||||
@@ -218,6 +220,7 @@ int raise_sigstop_flags;
|
||||
|
||||
static apr_pool_t *pconf; /* Pool for config stuff */
|
||||
static apr_pool_t *pchild; /* Pool for httpd child stuff */
|
||||
+static apr_pool_t *pruntime; /* Pool for MPM threads stuff */
|
||||
|
||||
static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
|
||||
thread. Use this instead */
|
||||
@@ -392,10 +395,10 @@ static void worker_note_child_killed(int childnum, pid_t pid, ap_generation_t ge
|
||||
|
||||
static void worker_note_child_started(int slot, pid_t pid)
|
||||
{
|
||||
+ ap_generation_t gen = retained->mpm->my_generation;
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
- ap_run_child_status(ap_server_conf,
|
||||
- ap_scoreboard_image->parent[slot].pid,
|
||||
- retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
+ ap_scoreboard_image->parent[slot].generation = gen;
|
||||
+ ap_run_child_status(ap_server_conf, pid, gen, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
static void worker_note_child_lost_slot(int slot, pid_t newpid)
|
||||
@@ -538,47 +541,15 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy)
|
||||
{
|
||||
proc_info * ti = dummy;
|
||||
int process_slot = ti->pid;
|
||||
- apr_pool_t *tpool = apr_thread_pool_get(thd);
|
||||
void *csd = NULL;
|
||||
apr_pool_t *ptrans = NULL; /* Pool for per-transaction stuff */
|
||||
- apr_pollset_t *pollset;
|
||||
apr_status_t rv;
|
||||
- ap_listen_rec *lr;
|
||||
+ ap_listen_rec *lr = NULL;
|
||||
int have_idle_worker = 0;
|
||||
int last_poll_idx = 0;
|
||||
|
||||
free(ti);
|
||||
|
||||
- rv = apr_pollset_create(&pollset, num_listensocks, tpool,
|
||||
- APR_POLLSET_NOCOPY);
|
||||
- if (rv != APR_SUCCESS) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
|
||||
- "Couldn't create pollset in thread;"
|
||||
- " check system or user limits");
|
||||
- /* let the parent decide how bad this really is */
|
||||
- clean_child_exit(APEXIT_CHILDSICK);
|
||||
- }
|
||||
-
|
||||
- for (lr = my_bucket->listeners; lr != NULL; lr = lr->next) {
|
||||
- apr_pollfd_t *pfd = apr_pcalloc(tpool, sizeof *pfd);
|
||||
-
|
||||
- pfd->desc_type = APR_POLL_SOCKET;
|
||||
- pfd->desc.s = lr->sd;
|
||||
- pfd->reqevents = APR_POLLIN;
|
||||
- pfd->client_data = lr;
|
||||
-
|
||||
- rv = apr_pollset_add(pollset, pfd);
|
||||
- if (rv != APR_SUCCESS) {
|
||||
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
|
||||
- "Couldn't create add listener to pollset;"
|
||||
- " check system or user limits");
|
||||
- /* let the parent decide how bad this really is */
|
||||
- clean_child_exit(APEXIT_CHILDSICK);
|
||||
- }
|
||||
-
|
||||
- lr->accept_func = ap_unixd_accept;
|
||||
- }
|
||||
-
|
||||
/* Unblock the signal used to wake this thread up, and set a handler for
|
||||
* it.
|
||||
*/
|
||||
@@ -630,7 +601,7 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy)
|
||||
apr_int32_t numdesc;
|
||||
const apr_pollfd_t *pdesc;
|
||||
|
||||
- rv = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
|
||||
+ rv = apr_pollset_poll(worker_pollset, -1, &numdesc, &pdesc);
|
||||
if (rv != APR_SUCCESS) {
|
||||
if (APR_STATUS_IS_EINTR(rv)) {
|
||||
continue;
|
||||
@@ -871,7 +842,7 @@ static void create_listener_thread(thread_starter *ts)
|
||||
my_info->tid = -1; /* listener thread doesn't have a thread slot */
|
||||
my_info->sd = 0;
|
||||
rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
|
||||
- my_info, pchild);
|
||||
+ my_info, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00275)
|
||||
"apr_thread_create: unable to create listener thread");
|
||||
@@ -881,35 +852,34 @@ static void create_listener_thread(thread_starter *ts)
|
||||
apr_os_thread_get(&listener_os_thread, ts->listener);
|
||||
}
|
||||
|
||||
-/* XXX under some circumstances not understood, children can get stuck
|
||||
- * in start_threads forever trying to take over slots which will
|
||||
- * never be cleaned up; for now there is an APLOG_DEBUG message issued
|
||||
- * every so often when this condition occurs
|
||||
- */
|
||||
-static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
|
||||
+static void setup_threads_runtime(void)
|
||||
{
|
||||
- thread_starter *ts = dummy;
|
||||
- apr_thread_t **threads = ts->threads;
|
||||
- apr_threadattr_t *thread_attr = ts->threadattr;
|
||||
- int my_child_num = ts->child_num_arg;
|
||||
- proc_info *my_info;
|
||||
+ ap_listen_rec *lr;
|
||||
apr_status_t rv;
|
||||
- int i;
|
||||
- int threads_created = 0;
|
||||
- int listener_started = 0;
|
||||
- int loops;
|
||||
- int prev_threads_created;
|
||||
+
|
||||
+ /* All threads (listener, workers) and synchronization objects (queues,
|
||||
+ * pollset, mutexes...) created here should have at least the lifetime of
|
||||
+ * the connections they handle (i.e. ptrans). We can't use this thread's
|
||||
+ * self pool because all these objects survive it, nor use pchild or pconf
|
||||
+ * directly because this starter thread races with other modules' runtime,
|
||||
+ * nor finally pchild (or subpool thereof) because it is killed explicitely
|
||||
+ * before pconf (thus connections/ptrans can live longer, which matters in
|
||||
+ * ONE_PROCESS mode). So this leaves us with a subpool of pconf, created
|
||||
+ * before any ptrans hence destroyed after.
|
||||
+ */
|
||||
+ apr_pool_create(&pruntime, pconf);
|
||||
+ apr_pool_tag(pruntime, "mpm_runtime");
|
||||
|
||||
/* We must create the fd queues before we start up the listener
|
||||
* and worker threads. */
|
||||
- rv = ap_queue_create(&worker_queue, threads_per_child, pchild);
|
||||
+ rv = ap_queue_create(&worker_queue, threads_per_child, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03140)
|
||||
"ap_queue_create() failed");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
- rv = ap_queue_info_create(&worker_queue_info, pchild,
|
||||
+ rv = ap_queue_info_create(&worker_queue_info, pruntime,
|
||||
threads_per_child, -1);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03141)
|
||||
@@ -917,8 +887,58 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
- worker_sockets = apr_pcalloc(pchild, threads_per_child
|
||||
- * sizeof(apr_socket_t *));
|
||||
+ /* Create the main pollset */
|
||||
+ rv = apr_pollset_create(&worker_pollset, num_listensocks, pruntime,
|
||||
+ APR_POLLSET_NOCOPY);
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(03285)
|
||||
+ "Couldn't create pollset in thread;"
|
||||
+ " check system or user limits");
|
||||
+ /* let the parent decide how bad this really is */
|
||||
+ clean_child_exit(APEXIT_CHILDSICK);
|
||||
+ }
|
||||
+
|
||||
+ for (lr = my_bucket->listeners; lr != NULL; lr = lr->next) {
|
||||
+ apr_pollfd_t *pfd = apr_pcalloc(pruntime, sizeof *pfd);
|
||||
+
|
||||
+ pfd->desc_type = APR_POLL_SOCKET;
|
||||
+ pfd->desc.s = lr->sd;
|
||||
+ pfd->reqevents = APR_POLLIN;
|
||||
+ pfd->client_data = lr;
|
||||
+
|
||||
+ rv = apr_pollset_add(worker_pollset, pfd);
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(03286)
|
||||
+ "Couldn't create add listener to pollset;"
|
||||
+ " check system or user limits");
|
||||
+ /* let the parent decide how bad this really is */
|
||||
+ clean_child_exit(APEXIT_CHILDSICK);
|
||||
+ }
|
||||
+
|
||||
+ lr->accept_func = ap_unixd_accept;
|
||||
+ }
|
||||
+
|
||||
+ worker_sockets = apr_pcalloc(pruntime, threads_per_child *
|
||||
+ sizeof(apr_socket_t *));
|
||||
+}
|
||||
+
|
||||
+/* XXX under some circumstances not understood, children can get stuck
|
||||
+ * in start_threads forever trying to take over slots which will
|
||||
+ * never be cleaned up; for now there is an APLOG_DEBUG message issued
|
||||
+ * every so often when this condition occurs
|
||||
+ */
|
||||
+static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
|
||||
+{
|
||||
+ thread_starter *ts = dummy;
|
||||
+ apr_thread_t **threads = ts->threads;
|
||||
+ apr_threadattr_t *thread_attr = ts->threadattr;
|
||||
+ int my_child_num = ts->child_num_arg;
|
||||
+ proc_info *my_info;
|
||||
+ apr_status_t rv;
|
||||
+ int threads_created = 0;
|
||||
+ int listener_started = 0;
|
||||
+ int prev_threads_created;
|
||||
+ int loops, i;
|
||||
|
||||
loops = prev_threads_created = 0;
|
||||
while (1) {
|
||||
@@ -942,7 +962,7 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
|
||||
* done because it lets us deal with tid better.
|
||||
*/
|
||||
rv = apr_thread_create(&threads[i], thread_attr,
|
||||
- worker_thread, my_info, pchild);
|
||||
+ worker_thread, my_info, pruntime);
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03142)
|
||||
"apr_thread_create: unable to create worker thread");
|
||||
@@ -1082,7 +1102,12 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
|
||||
ap_my_pid = getpid();
|
||||
ap_fatal_signal_child_setup(ap_server_conf);
|
||||
+
|
||||
+ /* Get a sub context for global allocations in this child, so that
|
||||
+ * we can have cleanups occur when the child exits.
|
||||
+ */
|
||||
apr_pool_create(&pchild, pconf);
|
||||
+ apr_pool_tag(pchild, "pchild");
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
@@ -1132,7 +1157,10 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
requests_this_child = INT_MAX;
|
||||
}
|
||||
|
||||
- /* Setup worker threads */
|
||||
+ /* Setup threads */
|
||||
+
|
||||
+ /* Globals used by signal_threads() so to be initialized before */
|
||||
+ setup_threads_runtime();
|
||||
|
||||
/* clear the storage; we may not create all our threads immediately,
|
||||
* and we want a 0 entry to indicate a thread which was not created
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
From d9f2c7df12a2e51ed78056e2bdc5714abf32390c Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Fri, 8 Feb 2019 09:01:42 +0000
|
||||
Subject: [PATCH 370/504] Merge of r1853133,r1853166 from trunk:
|
||||
|
||||
mod_ssl: Don't unset FIPS mode on restart unless it's forced by
|
||||
configuration (SSLFIPS on) and not active by default in OpenSSL. PR 63136.
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1853197 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 +++-
|
||||
modules/ssl/mod_ssl.c | 3 ---
|
||||
modules/ssl/ssl_engine_init.c | 12 +++++++++++-
|
||||
3 files changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
||||
index 9fdf9e042e..4797c78bb9 100644
|
||||
--- a/modules/ssl/mod_ssl.c
|
||||
+++ b/modules/ssl/mod_ssl.c
|
||||
@@ -331,9 +331,6 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
|
||||
/*
|
||||
* Try to kill the internals of the SSL library.
|
||||
*/
|
||||
-#ifdef HAVE_FIPS
|
||||
- FIPS_mode_set(0);
|
||||
-#endif
|
||||
/* Corresponds to OBJ_create()s */
|
||||
OBJ_cleanup();
|
||||
/* Corresponds to OPENSSL_load_builtin_modules() */
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index 18d18c691f..48d7b96cd8 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -183,6 +183,14 @@ int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef HAVE_FIPS
|
||||
+static apr_status_t modssl_fips_cleanup(void *data)
|
||||
+{
|
||||
+ FIPS_mode_set(0);
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Per-module initialization
|
||||
*/
|
||||
@@ -311,11 +319,13 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
|
||||
ssl_rand_seed(base_server, ptemp, SSL_RSCTX_STARTUP, "Init: ");
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
- if(sc->fips) {
|
||||
+ if (sc->fips) {
|
||||
if (!FIPS_mode()) {
|
||||
if (FIPS_mode_set(1)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01884)
|
||||
"Operating in SSL FIPS mode");
|
||||
+ apr_pool_cleanup_register(p, NULL, modssl_fips_cleanup,
|
||||
+ apr_pool_cleanup_null);
|
||||
}
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed");
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,397 +0,0 @@
|
||||
From fd0648f226ecbc38917ccb076a2147e206d73c8b Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Wed, 15 Aug 2018 15:01:08 +0000
|
||||
Subject: [PATCH 075/504] Merge r1418761, r1418765, r1510295, r1757147,
|
||||
r1805163, r1818924, r1827374, r1831772, r1832351, r1832951, r1815004 from
|
||||
trunk:
|
||||
|
||||
Don't claim "BIO dump follows" if it is not logged due to log level config.
|
||||
|
||||
|
||||
make ssl_io_data_dump respect per-conn loglevel
|
||||
|
||||
|
||||
add high trace level log messages for debugging buffering and write completion
|
||||
|
||||
|
||||
* modules/ssl/ssl_engine_kernel.c (ssl_callback_SessionTicket): Fail
|
||||
if RAND_bytes() fails; possible per API, although not in practice
|
||||
with the OpenSSL implementation.
|
||||
|
||||
|
||||
Fix typo in log message.
|
||||
|
||||
|
||||
ap_add_common_vars(): use apr_pstrmemdup().
|
||||
|
||||
This avoids a transient replacement/restore of '?' by '\0' in r->filename.
|
||||
|
||||
|
||||
Use 'ap_request_has_body()' instead of duplicating its implemenation.
|
||||
|
||||
The logic in 'ap_request_has_body()' is:
|
||||
has_body = (!r->header_only
|
||||
&& (r->kept_body
|
||||
|| apr_table_get(r->headers_in, "Transfer-Encoding")
|
||||
|| ( (cls = apr_table_get(r->headers_in, "Content-Length"))
|
||||
&& (apr_strtoff(&cl, cls, &estr, 10) == APR_SUCCESS)
|
||||
&& (!*estr)
|
||||
&& (cl > 0) )
|
||||
)
|
||||
);
|
||||
So the test is slighly different from the original code. (but this looks fine to me)
|
||||
|
||||
This also has the advantage to avoid a redundant call to 'apr_table_get()' and to improve readability.
|
||||
|
||||
While at it, move the test '!r->expecting_100' a few lines above because it is cheap.
|
||||
|
||||
PR62368: Print the unparsed URI in AH03454
|
||||
|
||||
... to include r->args and get otherwise get as close to possible to
|
||||
what came in over the wire.
|
||||
|
||||
Submitted By: Hank Ibell <hwibell gmail.com>
|
||||
Committed By: covener
|
||||
|
||||
|
||||
|
||||
|
||||
All error handling paths of this function call 'apr_brigade_destroy()' , except this one.
|
||||
So add it here too.
|
||||
|
||||
Probably spotted with the help of the Coccinelle software (Thx Julia for the patch and for Coccinelle)
|
||||
|
||||
See PR 53016
|
||||
|
||||
* modules/proxy/proxy_util.c (ap_proxy_share_worker): Skip creating subpool
|
||||
for debugging unless debug-level logging is enabled. No functional change.
|
||||
|
||||
|
||||
mod_watchdog: Correct some log messages and fix
|
||||
compiler warning
|
||||
"'rv' may be used uninitialized in this function".
|
||||
|
||||
Follow up to r1722154.
|
||||
|
||||
Submitted by: sf, jorton, jorton, ylavic, jailletc36, covener, jailletc36, jorton, rjung
|
||||
Reviewed by: jailletc36, jim, jorton
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1838103 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 2 ++
|
||||
STATUS | 26 ---------------------
|
||||
modules/core/mod_watchdog.c | 10 +++++----
|
||||
modules/proxy/mod_proxy_ajp.c | 1 +
|
||||
modules/proxy/proxy_util.c | 3 ++-
|
||||
modules/ssl/ssl_engine_io.c | 31 ++++++++++++++++---------
|
||||
modules/ssl/ssl_engine_kernel.c | 12 +++++-----
|
||||
server/core_filters.c | 40 ++++++++++++++++++++++++++++++---
|
||||
server/protocol.c | 2 +-
|
||||
server/util_script.c | 5 ++---
|
||||
10 files changed, 77 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/modules/core/mod_watchdog.c b/modules/core/mod_watchdog.c
|
||||
index b6deaba306..61f4675252 100644
|
||||
--- a/modules/core/mod_watchdog.c
|
||||
+++ b/modules/core/mod_watchdog.c
|
||||
@@ -534,11 +534,13 @@ static int wd_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
w->name, s,
|
||||
wd_server_conf->pool, 0);
|
||||
if (rv != APR_SUCCESS) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(10095)
|
||||
+ "Watchdog: Failed to create singleton mutex.");
|
||||
return rv;
|
||||
}
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979)
|
||||
+ "Watchdog: Created singleton mutex (%s).", w->name);
|
||||
}
|
||||
- ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979)
|
||||
- "Watchdog: Created child worker thread (%s).", w->name);
|
||||
wd_server_conf->child_workers++;
|
||||
}
|
||||
}
|
||||
@@ -580,12 +582,12 @@ static void wd_child_init_hook(apr_pool_t *p, server_rec *s)
|
||||
*/
|
||||
if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01573)
|
||||
- "Watchdog: Failed to create worker thread.");
|
||||
+ "Watchdog: Failed to create child worker thread.");
|
||||
/* No point to continue */
|
||||
return;
|
||||
}
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02981)
|
||||
- "Watchdog: Created worker thread (%s).", wn[i].provider_name);
|
||||
+ "Watchdog: Created child worker thread (%s).", wn[i].provider_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
|
||||
index 8669db6308..73716aff51 100644
|
||||
--- a/modules/proxy/mod_proxy_ajp.c
|
||||
+++ b/modules/proxy/mod_proxy_ajp.c
|
||||
@@ -322,6 +322,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
|
||||
* Close it to clean things up.
|
||||
*/
|
||||
conn->close = 1;
|
||||
+ apr_brigade_destroy(input_brigade);
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 7b76144ba7..2bd0edbfbc 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -1879,7 +1879,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_wo
|
||||
}
|
||||
worker->s = shm;
|
||||
worker->s->index = i;
|
||||
- {
|
||||
+
|
||||
+ if (APLOGdebug(ap_server_conf)) {
|
||||
apr_pool_t *pool;
|
||||
apr_pool_create(&pool, ap_server_conf->process->pool);
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02338)
|
||||
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
|
||||
index 1a47b0e982..d52d5e30ca 100644
|
||||
--- a/modules/ssl/ssl_engine_io.c
|
||||
+++ b/modules/ssl/ssl_engine_io.c
|
||||
@@ -877,6 +877,8 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
|
||||
*/
|
||||
outctx->c->cs->sense = CONN_SENSE_WANT_READ;
|
||||
outctx->rc = APR_EAGAIN;
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, outctx->c,
|
||||
+ "Want read during nonblocking write");
|
||||
}
|
||||
else if (ssl_err == SSL_ERROR_SYSCALL) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01993)
|
||||
@@ -2071,6 +2073,8 @@ void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
|
||||
/* write is non blocking for the benefit of async mpm */
|
||||
if (c->cs) {
|
||||
BIO_set_nbio(filter_ctx->pbioWrite, 1);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, c,
|
||||
+ "Enabling non-blocking writes");
|
||||
}
|
||||
|
||||
ssl_io_input_add_filter(filter_ctx, c, r, ssl);
|
||||
@@ -2114,9 +2118,8 @@ void ssl_io_filter_register(apr_pool_t *p)
|
||||
|
||||
#define DUMP_WIDTH 16
|
||||
|
||||
-static void ssl_io_data_dump(server_rec *s,
|
||||
- const char *b,
|
||||
- long len)
|
||||
+static void ssl_io_data_dump(conn_rec *c, server_rec *s,
|
||||
+ const char *b, long len)
|
||||
{
|
||||
char buf[256];
|
||||
char tmp[64];
|
||||
@@ -2129,7 +2132,7 @@ static void ssl_io_data_dump(server_rec *s,
|
||||
rows = (len / DUMP_WIDTH);
|
||||
if ((rows * DUMP_WIDTH) < len)
|
||||
rows++;
|
||||
- ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, s,
|
||||
+ ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s,
|
||||
"+-------------------------------------------------------------------------+");
|
||||
for(i = 0 ; i< rows; i++) {
|
||||
#if APR_CHARSET_EBCDIC
|
||||
@@ -2168,12 +2171,12 @@ static void ssl_io_data_dump(server_rec *s,
|
||||
}
|
||||
}
|
||||
apr_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));
|
||||
- ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, s, "%s", buf);
|
||||
+ ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s, "%s", buf);
|
||||
}
|
||||
if (trunc > 0)
|
||||
- ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, s,
|
||||
+ ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s,
|
||||
"| %04ld - <SPACES/NULS>", len + trunc);
|
||||
- ap_log_error(APLOG_MARK, APLOG_TRACE7, 0, s,
|
||||
+ ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s,
|
||||
"+-------------------------------------------------------------------------+");
|
||||
return;
|
||||
}
|
||||
@@ -2195,15 +2198,21 @@ long ssl_io_data_cb(BIO *bio, int cmd,
|
||||
if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
|
||||
|| cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
|
||||
if (rc >= 0) {
|
||||
+ const char *dump = "";
|
||||
+ if (APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7)) {
|
||||
+ if (argp != NULL)
|
||||
+ dump = "(BIO dump follows)";
|
||||
+ else
|
||||
+ dump = "(Oops, no memory buffer?)";
|
||||
+ }
|
||||
ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s,
|
||||
"%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s",
|
||||
MODSSL_LIBRARY_NAME,
|
||||
(cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
|
||||
rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
|
||||
- bio, argp,
|
||||
- (argp != NULL ? "(BIO dump follows)" : "(Oops, no memory buffer?)"));
|
||||
- if ((argp != NULL) && APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7))
|
||||
- ssl_io_data_dump(s, argp, rc);
|
||||
+ bio, argp, dump);
|
||||
+ if (*dump != '\0' && argp != NULL)
|
||||
+ ssl_io_data_dump(c, s, argp, rc);
|
||||
}
|
||||
else {
|
||||
ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s,
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index e34fc55fa2..9a89ff9da8 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -839,10 +839,8 @@ int ssl_hook_Access(request_rec *r)
|
||||
* request body, and then to reinject that request body later.
|
||||
*/
|
||||
if (renegotiate && !renegotiate_quick
|
||||
- && (apr_table_get(r->headers_in, "transfer-encoding")
|
||||
- || (apr_table_get(r->headers_in, "content-length")
|
||||
- && strcmp(apr_table_get(r->headers_in, "content-length"), "0")))
|
||||
- && !r->expecting_100) {
|
||||
+ && !r->expecting_100
|
||||
+ && ap_request_has_body(r)) {
|
||||
int rv;
|
||||
apr_size_t rsize;
|
||||
|
||||
@@ -2162,7 +2160,7 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
|
||||
|
||||
if (SSL_check_private_key(ssl) < 1) {
|
||||
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10088)
|
||||
- "Challenbge certificate and private key %s "
|
||||
+ "Challenge certificate and private key %s "
|
||||
"do not match", servername);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
@@ -2334,7 +2332,9 @@ int ssl_callback_SessionTicket(SSL *ssl,
|
||||
}
|
||||
|
||||
memcpy(keyname, ticket_key->key_name, 16);
|
||||
- RAND_bytes(iv, EVP_MAX_IV_LENGTH);
|
||||
+ if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) != 1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
EVP_EncryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL,
|
||||
ticket_key->aes_key, iv);
|
||||
HMAC_Init_ex(hctx, ticket_key->hmac_secret, 16, tlsext_tick_md(), NULL);
|
||||
diff --git a/server/core_filters.c b/server/core_filters.c
|
||||
index ddc2ff7f0f..a6c2bd666b 100644
|
||||
--- a/server/core_filters.c
|
||||
+++ b/server/core_filters.c
|
||||
@@ -378,6 +378,7 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
|
||||
int eor_buckets_in_brigade, morphing_bucket_in_brigade;
|
||||
apr_status_t rv;
|
||||
+ int loglevel = ap_get_conn_module_loglevel(c, APLOG_MODULE_INDEX);
|
||||
|
||||
/* Fail quickly if the connection has already been aborted. */
|
||||
if (c->aborted) {
|
||||
@@ -513,7 +514,7 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
|| eor_buckets_in_brigade > MAX_REQUESTS_IN_PIPELINE) {
|
||||
/* this segment of the brigade MUST be sent before returning. */
|
||||
|
||||
- if (APLOGctrace6(c)) {
|
||||
+ if (loglevel >= APLOG_TRACE6) {
|
||||
char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
|
||||
"FLUSH bucket" :
|
||||
(non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ?
|
||||
@@ -521,8 +522,17 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
morphing_bucket_in_brigade ? "morphing bucket" :
|
||||
"MAX_REQUESTS_IN_PIPELINE";
|
||||
ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, c,
|
||||
- "core_output_filter: flushing because of %s",
|
||||
- reason);
|
||||
+ "will flush because of %s", reason);
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
|
||||
+ "seen in brigade%s: bytes: %" APR_SIZE_T_FMT
|
||||
+ ", non-file bytes: %" APR_SIZE_T_FMT ", eor "
|
||||
+ "buckets: %d, morphing buckets: %d",
|
||||
+ flush_upto == NULL ? " so far"
|
||||
+ : " since last flush point",
|
||||
+ bytes_in_brigade,
|
||||
+ non_file_bytes_in_brigade,
|
||||
+ eor_buckets_in_brigade,
|
||||
+ morphing_bucket_in_brigade);
|
||||
}
|
||||
/*
|
||||
* Defer the actual blocking write to avoid doing many writes.
|
||||
@@ -539,6 +549,10 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
if (flush_upto != NULL) {
|
||||
ctx->tmp_flush_bb = apr_brigade_split_ex(bb, flush_upto,
|
||||
ctx->tmp_flush_bb);
|
||||
+ if (loglevel >= APLOG_TRACE8) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
|
||||
+ "flushing now");
|
||||
+ }
|
||||
rv = send_brigade_blocking(net->client_socket, bb,
|
||||
&(ctx->bytes_written), c);
|
||||
if (rv != APR_SUCCESS) {
|
||||
@@ -549,9 +563,23 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
c->aborted = 1;
|
||||
return rv;
|
||||
}
|
||||
+ if (loglevel >= APLOG_TRACE8) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
|
||||
+ "total bytes written: %" APR_SIZE_T_FMT,
|
||||
+ ctx->bytes_written);
|
||||
+ }
|
||||
APR_BRIGADE_CONCAT(bb, ctx->tmp_flush_bb);
|
||||
}
|
||||
|
||||
+ if (loglevel >= APLOG_TRACE8) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
|
||||
+ "brigade contains: bytes: %" APR_SIZE_T_FMT
|
||||
+ ", non-file bytes: %" APR_SIZE_T_FMT
|
||||
+ ", eor buckets: %d, morphing buckets: %d",
|
||||
+ bytes_in_brigade, non_file_bytes_in_brigade,
|
||||
+ eor_buckets_in_brigade, morphing_bucket_in_brigade);
|
||||
+ }
|
||||
+
|
||||
if (bytes_in_brigade >= THRESHOLD_MIN_WRITE) {
|
||||
rv = send_brigade_nonblocking(net->client_socket, bb,
|
||||
&(ctx->bytes_written), c);
|
||||
@@ -563,6 +591,12 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
|
||||
c->aborted = 1;
|
||||
return rv;
|
||||
}
|
||||
+ if (loglevel >= APLOG_TRACE8) {
|
||||
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
|
||||
+ "tried nonblocking write, total bytes "
|
||||
+ "written: %" APR_SIZE_T_FMT,
|
||||
+ ctx->bytes_written);
|
||||
+ }
|
||||
}
|
||||
|
||||
setaside_remaining_output(f, ctx, bb, c);
|
||||
diff --git a/server/protocol.c b/server/protocol.c
|
||||
index 708160f30b..2ca6b124a8 100644
|
||||
--- a/server/protocol.c
|
||||
+++ b/server/protocol.c
|
||||
@@ -894,7 +894,7 @@ rrl_done:
|
||||
else if (deferred_error == rrl_baduri)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03454)
|
||||
"HTTP Request Line; URI incorrectly encoded: '%.*s'",
|
||||
- field_name_len(r->uri), r->uri);
|
||||
+ field_name_len(r->unparsed_uri), r->unparsed_uri);
|
||||
else if (deferred_error == rrl_badwhitespace)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03447)
|
||||
"HTTP Request Line; Invalid whitespace");
|
||||
diff --git a/server/util_script.c b/server/util_script.c
|
||||
index 4121ae0aec..599ba58e71 100644
|
||||
--- a/server/util_script.c
|
||||
+++ b/server/util_script.c
|
||||
@@ -260,9 +260,8 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r)
|
||||
apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r));
|
||||
apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
|
||||
if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) {
|
||||
- *q = '\0';
|
||||
- apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename));
|
||||
- *q = '?';
|
||||
+ char *script_filename = apr_pstrmemdup(r->pool, r->filename, q - r->filename);
|
||||
+ apr_table_addn(e, "SCRIPT_FILENAME", script_filename);
|
||||
}
|
||||
else {
|
||||
apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
From 5e6fa5d12a569b7b780139c30542a49c78993bce Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Tue, 11 Dec 2018 14:09:11 +0000
|
||||
Subject: [PATCH 293/504] Merge r1831773 from trunk:
|
||||
|
||||
PR62311: only create the rewritelock when needed
|
||||
|
||||
Submitted By: Hank Ibell <hwibell gmail.com>
|
||||
Committed By: covener
|
||||
|
||||
|
||||
|
||||
Submitted by: covener
|
||||
Reviewed by: jailletc36, icing (by inspection), covener
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1848681 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
STATUS | 5 -----
|
||||
modules/mappers/mod_rewrite.c | 21 ++++++++++++---------
|
||||
3 files changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
|
||||
index fb897a9760..68a33b68a5 100644
|
||||
--- a/modules/mappers/mod_rewrite.c
|
||||
+++ b/modules/mappers/mod_rewrite.c
|
||||
@@ -416,6 +416,7 @@ static cache *cachep;
|
||||
static int proxy_available;
|
||||
|
||||
/* Locks/Mutexes */
|
||||
+static int rewrite_lock_needed = 0;
|
||||
static apr_global_mutex_t *rewrite_mapr_lock_acquire = NULL;
|
||||
static const char *rewritemap_mutex_type = "rewrite-map";
|
||||
|
||||
@@ -2687,9 +2688,6 @@ static apr_status_t rewritelock_create(server_rec *s, apr_pool_t *p)
|
||||
apr_status_t rc;
|
||||
|
||||
/* create the lockfile */
|
||||
- /* XXX See if there are any rewrite map programs before creating
|
||||
- * the mutex.
|
||||
- */
|
||||
rc = ap_global_mutex_create(&rewrite_mapr_lock_acquire, NULL,
|
||||
rewritemap_mutex_type, NULL, s, p, 0);
|
||||
if (rc != APR_SUCCESS) {
|
||||
@@ -3163,6 +3161,8 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1,
|
||||
|
||||
newmap->type = MAPTYPE_PRG;
|
||||
newmap->checkfile = newmap->argv[0];
|
||||
+ rewrite_lock_needed = 1;
|
||||
+
|
||||
if (a3) {
|
||||
char *tok_cntx;
|
||||
newmap->user = apr_strtok(apr_pstrdup(cmd->pool, a3), ":", &tok_cntx);
|
||||
@@ -4469,6 +4469,7 @@ static int pre_config(apr_pool_t *pconf,
|
||||
{
|
||||
APR_OPTIONAL_FN_TYPE(ap_register_rewrite_mapfunc) *map_pfn_register;
|
||||
|
||||
+ rewrite_lock_needed = 0;
|
||||
ap_mutex_register(pconf, rewritemap_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
|
||||
|
||||
/* register int: rewritemap handlers */
|
||||
@@ -4494,13 +4495,15 @@ static int post_config(apr_pool_t *p,
|
||||
/* check if proxy module is available */
|
||||
proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
|
||||
|
||||
- rv = rewritelock_create(s, p);
|
||||
- if (rv != APR_SUCCESS) {
|
||||
- return HTTP_INTERNAL_SERVER_ERROR;
|
||||
- }
|
||||
+ if (rewrite_lock_needed) {
|
||||
+ rv = rewritelock_create(s, p);
|
||||
+ if (rv != APR_SUCCESS) {
|
||||
+ return HTTP_INTERNAL_SERVER_ERROR;
|
||||
+ }
|
||||
|
||||
- apr_pool_cleanup_register(p, (void *)s, rewritelock_remove,
|
||||
- apr_pool_cleanup_null);
|
||||
+ apr_pool_cleanup_register(p, (void *)s, rewritelock_remove,
|
||||
+ apr_pool_cleanup_null);
|
||||
+ }
|
||||
|
||||
/* if we are not doing the initial config, step through the servers and
|
||||
* open the RewriteMap prg:xxx programs,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,108 +0,0 @@
|
||||
From ae583b572b6ce34e5fdeb92c88fde44d18db2db7 Mon Sep 17 00:00:00 2001
|
||||
From: Yann Ylavic <ylavic@apache.org>
|
||||
Date: Tue, 28 Aug 2018 20:07:07 +0000
|
||||
Subject: [PATCH 102/504] Merge r1837130 from trunk:
|
||||
|
||||
mod_ratelimit: Don't interfere with "chunked" encoding.
|
||||
|
||||
By the time ap_http_header_filter() sends the header brigade and adds the
|
||||
"CHUNK" filter, we need to garantee that the header went through all the
|
||||
filters' stack, and more specifically above ap_http_chunk_filter() which
|
||||
assumes that all it receives is content data.
|
||||
Since rate_limit_filter() may retain the header brigade, make it run after
|
||||
ap_http_chunk_filter(), just before AP_FTYPE_CONNECTION filters.
|
||||
|
||||
Also, ap_http_header_filter() shouldn't eat the EOS for HEAD/no-body responses.
|
||||
For instance mod_ratelimit depends on it since r1835168, but any next request
|
||||
filter may as well to flush and/or bail out approprietely.
|
||||
|
||||
This fixes the regression introduced in 2.4.34 (r1835168).
|
||||
PR 62568.
|
||||
|
||||
Submitted by: ylavic
|
||||
Reviewed by: covener, ylavic, jim
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1839497 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
STATUS | 7 -------
|
||||
modules/filters/mod_ratelimit.c | 3 +--
|
||||
modules/http/chunk_filter.c | 3 ++-
|
||||
modules/http/http_filters.c | 13 ++++++++++++-
|
||||
5 files changed, 18 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/modules/filters/mod_ratelimit.c b/modules/filters/mod_ratelimit.c
|
||||
index cf79973120..d16eb39059 100644
|
||||
--- a/modules/filters/mod_ratelimit.c
|
||||
+++ b/modules/filters/mod_ratelimit.c
|
||||
@@ -65,7 +65,6 @@ rate_limit_filter(ap_filter_t *f, apr_bucket_brigade *bb)
|
||||
|
||||
/* Set up our rl_ctx_t on first use */
|
||||
if (ctx == NULL) {
|
||||
-
|
||||
const char *rl = NULL;
|
||||
int ratelimit;
|
||||
int burst = 0;
|
||||
@@ -327,7 +326,7 @@ static void register_hooks(apr_pool_t *p)
|
||||
{
|
||||
/* run after mod_deflate etc etc, but not at connection level, ie, mod_ssl. */
|
||||
ap_register_output_filter(RATE_LIMIT_FILTER_NAME, rate_limit_filter,
|
||||
- NULL, AP_FTYPE_PROTOCOL + 3);
|
||||
+ NULL, AP_FTYPE_CONNECTION - 1);
|
||||
}
|
||||
|
||||
AP_DECLARE_MODULE(ratelimit) = {
|
||||
diff --git a/modules/http/chunk_filter.c b/modules/http/chunk_filter.c
|
||||
index 17fbabdb0a..cb1501aebf 100644
|
||||
--- a/modules/http/chunk_filter.c
|
||||
+++ b/modules/http/chunk_filter.c
|
||||
@@ -69,6 +69,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
|
||||
{
|
||||
if (APR_BUCKET_IS_EOS(e)) {
|
||||
/* there shouldn't be anything after the eos */
|
||||
+ ap_remove_output_filter(f);
|
||||
eos = e;
|
||||
break;
|
||||
}
|
||||
@@ -186,11 +187,11 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
|
||||
|
||||
/* pass the brigade to the next filter. */
|
||||
rv = ap_pass_brigade(f->next, b);
|
||||
+ apr_brigade_cleanup(b);
|
||||
if (rv != APR_SUCCESS || eos != NULL) {
|
||||
return rv;
|
||||
}
|
||||
tmp = b;
|
||||
- apr_brigade_cleanup(tmp);
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
|
||||
index 5fa40635d8..37c0113e5b 100644
|
||||
--- a/modules/http/http_filters.c
|
||||
+++ b/modules/http/http_filters.c
|
||||
@@ -1308,8 +1308,19 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
|
||||
else if (ctx->headers_sent) {
|
||||
/* Eat body if response must not have one. */
|
||||
if (r->header_only || r->status == HTTP_NO_CONTENT) {
|
||||
+ /* Still next filters may be waiting for EOS, so pass it (alone)
|
||||
+ * when encountered and be done with this filter.
|
||||
+ */
|
||||
+ e = APR_BRIGADE_LAST(b);
|
||||
+ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
|
||||
+ APR_BUCKET_REMOVE(e);
|
||||
+ apr_brigade_cleanup(b);
|
||||
+ APR_BRIGADE_INSERT_HEAD(b, e);
|
||||
+ ap_remove_output_filter(f);
|
||||
+ rv = ap_pass_brigade(f->next, b);
|
||||
+ }
|
||||
apr_brigade_cleanup(b);
|
||||
- return APR_SUCCESS;
|
||||
+ return rv;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
From 657d20fe0dbe55a793ca48fb6f58ee497d241934 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Jagielski <jim@apache.org>
|
||||
Date: Wed, 7 Nov 2018 15:18:42 +0000
|
||||
Subject: [PATCH 261/504] Merge r1837250 from trunk:
|
||||
|
||||
If ProxyPassReverse is used for reverse mapping of relative redirects, subsequent ProxyPassReverse statements, whether they are relative or absolute, may fail.
|
||||
|
||||
PR 60408 [Peter Haworth <pmh1wheel gmail.com>]
|
||||
Submitted by: jailletc36
|
||||
Reviewed by: jailletc36, rpluem, jim
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1846044 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
STATUS | 6 ------
|
||||
modules/proxy/proxy_util.c | 8 ++++++--
|
||||
3 files changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index 6501c68064..cbf8826777 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -837,7 +837,7 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
|
||||
{
|
||||
proxy_req_conf *rconf;
|
||||
struct proxy_alias *ent;
|
||||
- int i, l1, l2;
|
||||
+ int i, l1, l1_orig, l2;
|
||||
char *u;
|
||||
|
||||
/*
|
||||
@@ -849,7 +849,7 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
|
||||
return url;
|
||||
}
|
||||
|
||||
- l1 = strlen(url);
|
||||
+ l1_orig = strlen(url);
|
||||
if (conf->interpolate_env == 1) {
|
||||
rconf = ap_get_module_config(r->request_config, &proxy_module);
|
||||
ent = (struct proxy_alias *)rconf->raliases->elts;
|
||||
@@ -862,6 +862,10 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
|
||||
ap_get_module_config(r->server->module_config, &proxy_module);
|
||||
proxy_balancer *balancer;
|
||||
const char *real = ent[i].real;
|
||||
+
|
||||
+ /* Restore the url length, if it had been changed by the code below */
|
||||
+ l1 = l1_orig;
|
||||
+
|
||||
/*
|
||||
* First check if mapping against a balancer and see
|
||||
* if we have such a entity. If so, then we need to
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
From 5c1995151ab80cd71bc845bd288b90fd55665e2e Mon Sep 17 00:00:00 2001
|
||||
From: Eric Covener <covener@apache.org>
|
||||
Date: Tue, 9 Oct 2018 23:26:35 +0000
|
||||
Subject: [PATCH 209/504] Merge r1842540 from trunk:
|
||||
|
||||
* Pickup the proxy related configuration for verify mode and verify depth and
|
||||
not the configuration settings for frontend connections in case of
|
||||
connections by the proxy to the backend.
|
||||
|
||||
PR: 62769
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1843370 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
STATUS | 9 ---------
|
||||
modules/ssl/ssl_engine_kernel.c | 25 ++++++++++++++++++-------
|
||||
3 files changed, 22 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index d576a298ec..6cd0da527f 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1740,7 +1740,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
|
||||
/* Get verify ingredients */
|
||||
int errnum = X509_STORE_CTX_get_error(ctx);
|
||||
int errdepth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
- int depth, verify;
|
||||
+ int depth = UNSET;
|
||||
+ int verify = SSL_CVERIFY_UNSET;
|
||||
|
||||
/*
|
||||
* Log verification information
|
||||
@@ -1756,10 +1757,15 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
|
||||
/*
|
||||
* Check for optionally acceptable non-verifiable issuer situation
|
||||
*/
|
||||
- if (dc && (dc->nVerifyClient != SSL_CVERIFY_UNSET)) {
|
||||
- verify = dc->nVerifyClient;
|
||||
+ if (dc) {
|
||||
+ if (sslconn->is_proxy) {
|
||||
+ verify = dc->proxy->auth.verify_mode;
|
||||
+ }
|
||||
+ else {
|
||||
+ verify = dc->nVerifyClient;
|
||||
+ }
|
||||
}
|
||||
- else {
|
||||
+ if (!dc || (verify == SSL_CVERIFY_UNSET)) {
|
||||
verify = mctx->auth.verify_mode;
|
||||
}
|
||||
|
||||
@@ -1863,10 +1869,15 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
|
||||
/*
|
||||
* Finally check the depth of the certificate verification
|
||||
*/
|
||||
- if (dc && (dc->nVerifyDepth != UNSET)) {
|
||||
- depth = dc->nVerifyDepth;
|
||||
+ if (dc) {
|
||||
+ if (sslconn->is_proxy) {
|
||||
+ depth = dc->proxy->auth.verify_depth;
|
||||
+ }
|
||||
+ else {
|
||||
+ depth = dc->nVerifyDepth;
|
||||
+ }
|
||||
}
|
||||
- else {
|
||||
+ if (!dc || (depth == UNSET)) {
|
||||
depth = mctx->auth.verify_depth;
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
From b34ce8ef855714a8a90e4e97cd7f2b8f8027c7fe Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Jaillet <jailletc36@apache.org>
|
||||
Date: Fri, 15 Feb 2019 15:57:51 +0000
|
||||
Subject: [PATCH 390/504] Merge r1851093 from trunk
|
||||
|
||||
* mod_proxy_wstunnel: Fix websocket proxy over UDS.
|
||||
|
||||
PR: 62932
|
||||
Submitted by: <pavel dcmsys.com>
|
||||
Reviewed by: jailletc36 (by inspection), jim, ylavic
|
||||
Backported by: jailletc36
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1853653 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
|
||||
index 9dda010dbc..1056d5cb72 100644
|
||||
--- a/modules/proxy/mod_proxy_wstunnel.c
|
||||
+++ b/modules/proxy/mod_proxy_wstunnel.c
|
||||
@@ -77,7 +77,10 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
|
||||
if (path == NULL)
|
||||
return HTTP_BAD_REQUEST;
|
||||
|
||||
- apr_snprintf(sport, sizeof(sport), ":%d", port);
|
||||
+ if (port != def_port)
|
||||
+ apr_snprintf(sport, sizeof(sport), ":%d", port);
|
||||
+ else
|
||||
+ sport[0] = '\0';
|
||||
|
||||
if (ap_strchr_c(host, ':')) {
|
||||
/* if literal IPv6 address */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From 7e6e9c0a7b9653af14ddce21c9cebf9765c70823 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Jaillet <jailletc36@apache.org>
|
||||
Date: Fri, 15 Feb 2019 16:06:24 +0000
|
||||
Subject: [PATCH 391/504] Merge r1851093 from trunk
|
||||
|
||||
* mod_proxy_wstunnel: Fix websocket proxy over UDS.
|
||||
|
||||
PR: 62932
|
||||
Submitted by: <pavel dcmsys.com>
|
||||
Reviewed by: jailletc36 (by inspection), jim, ylavic
|
||||
Backported by: jailletc36
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1853654 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
modules/aaa/mod_authn_dbm.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/modules/aaa/mod_authn_dbm.c b/modules/aaa/mod_authn_dbm.c
|
||||
index f4fb73672e..6eae9e052a 100644
|
||||
--- a/modules/aaa/mod_authn_dbm.c
|
||||
+++ b/modules/aaa/mod_authn_dbm.c
|
||||
@@ -102,7 +102,11 @@ static apr_status_t fetch_dbm_value(const char *dbmtype, const char *dbmfile,
|
||||
|
||||
apr_dbm_close(f);
|
||||
|
||||
- return rv;
|
||||
+ /* NOT FOUND is not an error case; this is indicated by a NULL result.
|
||||
+ * Treat all NULL lookup/error results as success for the simple case
|
||||
+ * of auth credential lookup, these are DECLINED in both cases.
|
||||
+ */
|
||||
+ return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static authn_status check_dbm_pw(request_rec *r, const char *user,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
From 44b3ddc560c490c60600998fa2bf59b142d08e05 Mon Sep 17 00:00:00 2001
|
||||
From: Joe Orton <jorton@apache.org>
|
||||
Date: Tue, 12 Mar 2019 09:24:26 +0000
|
||||
Subject: [PATCH 408/504] Merge r1853190 from trunk:
|
||||
|
||||
Fix a race condition. Authentication with valid credentials could be
|
||||
refused in case of concurrent accesses from different users.
|
||||
|
||||
PR: 63124
|
||||
Submitted by: Simon Kappel <simon.kappel axis.com>
|
||||
Reviewed by: jailletc36, icing, jorton
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855298 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
modules/aaa/mod_auth_digest.c | 26 ++++++++++++--------------
|
||||
2 files changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
|
||||
index a67f06986f..b76094114d 100644
|
||||
--- a/modules/aaa/mod_auth_digest.c
|
||||
+++ b/modules/aaa/mod_auth_digest.c
|
||||
@@ -92,7 +92,6 @@ typedef struct digest_config_struct {
|
||||
int check_nc;
|
||||
const char *algorithm;
|
||||
char *uri_list;
|
||||
- const char *ha1;
|
||||
} digest_config_rec;
|
||||
|
||||
|
||||
@@ -153,6 +152,7 @@ typedef struct digest_header_struct {
|
||||
apr_time_t nonce_time;
|
||||
enum hdr_sts auth_hdr_sts;
|
||||
int needed_auth;
|
||||
+ const char *ha1;
|
||||
client_entry *client;
|
||||
} digest_header_rec;
|
||||
|
||||
@@ -1304,7 +1304,7 @@ static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type)
|
||||
*/
|
||||
|
||||
static authn_status get_hash(request_rec *r, const char *user,
|
||||
- digest_config_rec *conf)
|
||||
+ digest_config_rec *conf, const char **rethash)
|
||||
{
|
||||
authn_status auth_result;
|
||||
char *password;
|
||||
@@ -1356,7 +1356,7 @@ static authn_status get_hash(request_rec *r, const char *user,
|
||||
} while (current_provider);
|
||||
|
||||
if (auth_result == AUTH_USER_FOUND) {
|
||||
- conf->ha1 = password;
|
||||
+ *rethash = password;
|
||||
}
|
||||
|
||||
return auth_result;
|
||||
@@ -1483,25 +1483,24 @@ static int check_nonce(request_rec *r, digest_header_rec *resp,
|
||||
|
||||
/* RFC-2069 */
|
||||
static const char *old_digest(const request_rec *r,
|
||||
- const digest_header_rec *resp, const char *ha1)
|
||||
+ const digest_header_rec *resp)
|
||||
{
|
||||
const char *ha2;
|
||||
|
||||
ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":",
|
||||
resp->uri, NULL));
|
||||
return ap_md5(r->pool,
|
||||
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,
|
||||
- ":", ha2, NULL));
|
||||
+ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":",
|
||||
+ resp->nonce, ":", ha2, NULL));
|
||||
}
|
||||
|
||||
/* RFC-2617 */
|
||||
static const char *new_digest(const request_rec *r,
|
||||
- digest_header_rec *resp,
|
||||
- const digest_config_rec *conf)
|
||||
+ digest_header_rec *resp)
|
||||
{
|
||||
const char *ha1, *ha2, *a2;
|
||||
|
||||
- ha1 = conf->ha1;
|
||||
+ ha1 = resp->ha1;
|
||||
|
||||
a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
|
||||
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
|
||||
@@ -1514,7 +1513,6 @@ static const char *new_digest(const request_rec *r,
|
||||
NULL));
|
||||
}
|
||||
|
||||
-
|
||||
static void copy_uri_components(apr_uri_t *dst,
|
||||
apr_uri_t *src, request_rec *r) {
|
||||
if (src->scheme && src->scheme[0] != '\0') {
|
||||
@@ -1759,7 +1757,7 @@ static int authenticate_digest_user(request_rec *r)
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
- return_code = get_hash(r, r->user, conf);
|
||||
+ return_code = get_hash(r, r->user, conf, &resp->ha1);
|
||||
|
||||
if (return_code == AUTH_USER_NOT_FOUND) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790)
|
||||
@@ -1789,7 +1787,7 @@ static int authenticate_digest_user(request_rec *r)
|
||||
|
||||
if (resp->message_qop == NULL) {
|
||||
/* old (rfc-2069) style digest */
|
||||
- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
|
||||
+ if (strcmp(resp->digest, old_digest(r, resp))) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792)
|
||||
"user %s: password mismatch: %s", r->user,
|
||||
r->uri);
|
||||
@@ -1819,7 +1817,7 @@ static int authenticate_digest_user(request_rec *r)
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
- exp_digest = new_digest(r, resp, conf);
|
||||
+ exp_digest = new_digest(r, resp);
|
||||
if (!exp_digest) {
|
||||
/* we failed to allocate a client struct */
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
@@ -1903,7 +1901,7 @@ static int add_auth_info(request_rec *r)
|
||||
|
||||
/* calculate rspauth attribute
|
||||
*/
|
||||
- ha1 = conf->ha1;
|
||||
+ ha1 = resp->ha1;
|
||||
|
||||
a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
|
||||
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,143 +0,0 @@
|
||||
From 0dcd178c561f3293775a3d5953c764d64a5af233 Mon Sep 17 00:00:00 2001
|
||||
From: Joe Orton <jorton@apache.org>
|
||||
Date: Wed, 20 Mar 2019 15:50:44 +0000
|
||||
Subject: [PATCH 475/504] Merge r1855646, r1855748 from trunk:
|
||||
|
||||
mod_proxy/ssl: cleanup per-request SSL configuration for recycled proxy conns.
|
||||
|
||||
The SSL dir config of proxy/backend connections is stored in r->per_dir_config
|
||||
but those connections have a lifetime independent of the requests they handle.
|
||||
|
||||
So we need to allow the external ssl_engine_set() function to reset mod_ssl's
|
||||
dir config in between proxy requests, or the first sslconn->dc could be used
|
||||
after free for the next requests.
|
||||
|
||||
mod_proxy can then reset/reinit the request config when recycling its backend
|
||||
connections.
|
||||
|
||||
* Solve a chicken and egg problem here:
|
||||
We need to have sslconn->dc set correctly when we want to
|
||||
init sslconn, but we need to allocate memory for it first.
|
||||
|
||||
PR 63256.
|
||||
Submitted by: ylavic, rpluem
|
||||
Reviewed by: ylavic, jorton, jim
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855918 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
modules/proxy/proxy_util.c | 13 +++++++++++++
|
||||
modules/ssl/mod_ssl.c | 38 ++++++++++++++++++++++++--------------
|
||||
3 files changed, 41 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
|
||||
index cbf8826777..b131ec07f6 100644
|
||||
--- a/modules/proxy/proxy_util.c
|
||||
+++ b/modules/proxy/proxy_util.c
|
||||
@@ -1532,6 +1532,13 @@ static apr_status_t connection_cleanup(void *theconn)
|
||||
socket_cleanup(conn);
|
||||
conn->close = 0;
|
||||
}
|
||||
+ else if (conn->is_ssl) {
|
||||
+ /* Unbind/reset the SSL connection dir config (sslconn->dc) from
|
||||
+ * r->per_dir_config, r will likely get destroyed before this proxy
|
||||
+ * conn is reused.
|
||||
+ */
|
||||
+ ap_proxy_ssl_engine(conn->connection, worker->section_config, 1);
|
||||
+ }
|
||||
|
||||
if (worker->s->hmax && worker->cp->res) {
|
||||
conn->inreslist = 1;
|
||||
@@ -3172,6 +3179,12 @@ static int proxy_connection_create(const char *proxy_function,
|
||||
apr_bucket_alloc_t *bucket_alloc;
|
||||
|
||||
if (conn->connection) {
|
||||
+ if (conn->is_ssl) {
|
||||
+ /* on reuse, reinit the SSL connection dir config with the current
|
||||
+ * r->per_dir_config, the previous one was reset on release.
|
||||
+ */
|
||||
+ ap_proxy_ssl_engine(conn->connection, per_dir_config, 1);
|
||||
+ }
|
||||
return OK;
|
||||
}
|
||||
|
||||
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
||||
index 4797c78bb9..e857f50647 100644
|
||||
--- a/modules/ssl/mod_ssl.c
|
||||
+++ b/modules/ssl/mod_ssl.c
|
||||
@@ -442,17 +442,20 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
|
||||
}
|
||||
|
||||
static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
|
||||
- ap_conf_vector_t *per_dir_config)
|
||||
+ ap_conf_vector_t *per_dir_config,
|
||||
+ int new_proxy)
|
||||
{
|
||||
SSLConnRec *sslconn = myConnConfig(c);
|
||||
- SSLSrvConfigRec *sc;
|
||||
+ int need_setup = 0;
|
||||
|
||||
- if (sslconn) {
|
||||
- return sslconn;
|
||||
+ if (!sslconn) {
|
||||
+ sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
|
||||
+ need_setup = 1;
|
||||
}
|
||||
|
||||
- sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
|
||||
-
|
||||
+ /* Reinit dc in any case because it may be r->per_dir_config scoped
|
||||
+ * and thus a caller like mod_proxy needs to update it per request.
|
||||
+ */
|
||||
if (per_dir_config) {
|
||||
sslconn->dc = ap_get_module_config(per_dir_config, &ssl_module);
|
||||
}
|
||||
@@ -461,12 +464,20 @@ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
|
||||
&ssl_module);
|
||||
}
|
||||
|
||||
- sslconn->server = c->base_server;
|
||||
- sslconn->verify_depth = UNSET;
|
||||
- sc = mySrvConfig(c->base_server);
|
||||
- sslconn->cipher_suite = sc->server->auth.cipher_suite;
|
||||
+ if (need_setup) {
|
||||
+ sslconn->server = c->base_server;
|
||||
+ sslconn->verify_depth = UNSET;
|
||||
+ if (new_proxy) {
|
||||
+ sslconn->is_proxy = 1;
|
||||
+ sslconn->cipher_suite = sslconn->dc->proxy->auth.cipher_suite;
|
||||
+ }
|
||||
+ else {
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
|
||||
+ sslconn->cipher_suite = sc->server->auth.cipher_suite;
|
||||
+ }
|
||||
|
||||
- myConnConfigSet(c, sslconn);
|
||||
+ myConnConfigSet(c, sslconn);
|
||||
+ }
|
||||
|
||||
return sslconn;
|
||||
}
|
||||
@@ -507,8 +518,7 @@ static int ssl_engine_set(conn_rec *c,
|
||||
int status;
|
||||
|
||||
if (proxy) {
|
||||
- sslconn = ssl_init_connection_ctx(c, per_dir_config);
|
||||
- sslconn->is_proxy = 1;
|
||||
+ sslconn = ssl_init_connection_ctx(c, per_dir_config, 1);
|
||||
}
|
||||
else {
|
||||
sslconn = myConnConfig(c);
|
||||
@@ -555,7 +565,7 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
|
||||
/*
|
||||
* Create or retrieve SSL context
|
||||
*/
|
||||
- sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL);
|
||||
+ sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL, 0);
|
||||
server = sslconn->server;
|
||||
sc = mySrvConfig(server);
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,178 +0,0 @@
|
||||
From c0457a9d97bc7b50cbc54f587fcca419d1a2ca2e Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Eissing <icing@apache.org>
|
||||
Date: Fri, 3 Aug 2018 10:54:47 +0000
|
||||
Subject: [PATCH 056/504] On the 2.4.x branch:
|
||||
|
||||
backport of r1837357 from trunk.
|
||||
*) mod_md: When the last domain name from an MD is moved to another one,
|
||||
that now empty MD gets moved to the store archive. PR 62572.
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1837358 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
modules/md/md_reg.c | 60 +++++++++++++++++++++++------------------
|
||||
modules/md/md_reg.h | 2 ++
|
||||
modules/md/md_version.h | 4 +--
|
||||
4 files changed, 41 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/modules/md/md_reg.c b/modules/md/md_reg.c
|
||||
index 459c15f157..233fea79d7 100644
|
||||
--- a/modules/md/md_reg.c
|
||||
+++ b/modules/md/md_reg.c
|
||||
@@ -635,11 +635,10 @@ apr_status_t md_reg_creds_get(const md_creds_t **pcreds, md_reg_t *reg,
|
||||
|
||||
typedef struct {
|
||||
apr_pool_t *p;
|
||||
- apr_array_header_t *conf_mds;
|
||||
apr_array_header_t *store_mds;
|
||||
} sync_ctx;
|
||||
|
||||
-static int find_changes(void *baton, md_store_t *store, md_t *md, apr_pool_t *ptemp)
|
||||
+static int do_add_md(void *baton, md_store_t *store, md_t *md, apr_pool_t *ptemp)
|
||||
{
|
||||
sync_ctx *ctx = baton;
|
||||
|
||||
@@ -649,6 +648,18 @@ static int find_changes(void *baton, md_store_t *store, md_t *md, apr_pool_t *pt
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static apr_status_t read_store_mds(md_reg_t *reg, sync_ctx *ctx)
|
||||
+{
|
||||
+ int rv;
|
||||
+
|
||||
+ apr_array_clear(ctx->store_mds);
|
||||
+ rv = md_store_md_iter(do_add_md, ctx, reg->store, ctx->p, MD_SG_DOMAINS, "*");
|
||||
+ if (APR_STATUS_IS_ENOENT(rv)) {
|
||||
+ rv = APR_SUCCESS;
|
||||
+ }
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
apr_status_t md_reg_set_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https)
|
||||
{
|
||||
if (reg->can_http != can_http || reg->can_https != can_https) {
|
||||
@@ -686,17 +697,11 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
apr_array_header_t *master_mds)
|
||||
{
|
||||
sync_ctx ctx;
|
||||
- md_store_t *store = reg->store;
|
||||
apr_status_t rv;
|
||||
|
||||
ctx.p = ptemp;
|
||||
- ctx.conf_mds = master_mds;
|
||||
- ctx.store_mds = apr_array_make(ptemp, 100, sizeof(md_t *));
|
||||
-
|
||||
- rv = md_store_md_iter(find_changes, &ctx, store, ptemp, MD_SG_DOMAINS, "*");
|
||||
- if (APR_STATUS_IS_ENOENT(rv)) {
|
||||
- rv = APR_SUCCESS;
|
||||
- }
|
||||
+ ctx.store_mds = apr_array_make(ptemp,100, sizeof(md_t *));
|
||||
+ rv = read_store_mds(reg, &ctx);
|
||||
|
||||
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
||||
"sync: found %d mds in store", ctx.store_mds->nelts);
|
||||
@@ -705,8 +710,8 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
md_t *md, *config_md, *smd, *omd;
|
||||
const char *common;
|
||||
|
||||
- for (i = 0; i < ctx.conf_mds->nelts; ++i) {
|
||||
- md = APR_ARRAY_IDX(ctx.conf_mds, i, md_t *);
|
||||
+ for (i = 0; i < master_mds->nelts; ++i) {
|
||||
+ md = APR_ARRAY_IDX(master_mds, i, md_t *);
|
||||
|
||||
/* find the store md that is closest match for the configured md */
|
||||
smd = md_find_closest_match(ctx.store_mds, md);
|
||||
@@ -734,7 +739,7 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
assert(common);
|
||||
|
||||
/* Is this md still configured or has it been abandoned in the config? */
|
||||
- config_md = md_get_by_name(ctx.conf_mds, omd->name);
|
||||
+ config_md = md_get_by_name(master_mds, omd->name);
|
||||
if (config_md && md_contains(config_md, common, 0)) {
|
||||
/* domain used in two configured mds, not allowed */
|
||||
rv = APR_EINVAL;
|
||||
@@ -742,21 +747,19 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
"domain %s used in md %s and %s",
|
||||
common, md->name, omd->name);
|
||||
}
|
||||
- else if (config_md) {
|
||||
- /* domain stored in omd, but no longer has the offending domain,
|
||||
- remove it from the store md. */
|
||||
- omd->domains = md_array_str_remove(ptemp, omd->domains, common, 0);
|
||||
- rv = md_reg_update(reg, ptemp, omd->name, omd, MD_UPD_DOMAINS);
|
||||
- }
|
||||
else {
|
||||
- /* domain in a store md that is no longer configured, warn about it.
|
||||
- * Remove the domain here, so we can progress, but never save it. */
|
||||
+ /* remove it from the other md and update store, or, if it
|
||||
+ * is now empty, move it into the archive */
|
||||
omd->domains = md_array_str_remove(ptemp, omd->domains, common, 0);
|
||||
- md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p,
|
||||
- "domain %s, configured in md %s, is part of the stored md %s."
|
||||
- " That md however is no longer mentioned in the config. "
|
||||
- "If you longer want it, remove the md from the store.",
|
||||
- common, md->name, omd->name);
|
||||
+ if (apr_is_empty_array(omd->domains)) {
|
||||
+ md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p,
|
||||
+ "All domains of the MD %s have moved elsewhere, "
|
||||
+ " moving it to the archive. ", omd->name);
|
||||
+ md_reg_remove(reg, ptemp, omd->name, 1); /* best effort */
|
||||
+ }
|
||||
+ else {
|
||||
+ rv = md_reg_update(reg, ptemp, omd->name, omd, MD_UPD_DOMAINS);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,6 +844,11 @@ apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
return rv;
|
||||
}
|
||||
|
||||
+apr_status_t md_reg_remove(md_reg_t *reg, apr_pool_t *p, const char *name, int archive)
|
||||
+{
|
||||
+ return md_store_move(reg->store, p, MD_SG_DOMAINS, MD_SG_ARCHIVE, name, archive);
|
||||
+}
|
||||
+
|
||||
|
||||
/**************************************************************************************************/
|
||||
/* driving */
|
||||
diff --git a/modules/md/md_reg.h b/modules/md/md_reg.h
|
||||
index 2bf738583c..d976b7fe80 100644
|
||||
--- a/modules/md/md_reg.h
|
||||
+++ b/modules/md/md_reg.h
|
||||
@@ -124,6 +124,8 @@ apr_status_t md_reg_get_cred_files(md_reg_t *reg, const md_t *md, apr_pool_t *p,
|
||||
apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
||||
apr_array_header_t *master_mds);
|
||||
|
||||
+apr_status_t md_reg_remove(md_reg_t *reg, apr_pool_t *p, const char *name, int archive);
|
||||
+
|
||||
/**************************************************************************************************/
|
||||
/* protocol drivers */
|
||||
|
||||
diff --git a/modules/md/md_version.h b/modules/md/md_version.h
|
||||
index b87f19c1db..34ab4eb61e 100644
|
||||
--- a/modules/md/md_version.h
|
||||
+++ b/modules/md/md_version.h
|
||||
@@ -27,7 +27,7 @@
|
||||
* @macro
|
||||
* Version number of the md module as c string
|
||||
*/
|
||||
-#define MOD_MD_VERSION "1.1.15"
|
||||
+#define MOD_MD_VERSION "1.1.16"
|
||||
|
||||
/**
|
||||
* @macro
|
||||
@@ -35,7 +35,7 @@
|
||||
* release. This is a 24 bit number with 8 bits for major number, 8 bits
|
||||
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
|
||||
*/
|
||||
-#define MOD_MD_VERSION_NUM 0x01010f
|
||||
+#define MOD_MD_VERSION_NUM 0x010110
|
||||
|
||||
#define MD_ACME_DEF_URL "https://acme-v01.api.letsencrypt.org/directory"
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,39 +1,3 @@
|
||||
diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
|
||||
diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
|
||||
diff -uap httpd-2.4.25/acinclude.m4.detectsystemd httpd-2.4.25/acinclude.m4
|
||||
--- httpd-2.4.25/acinclude.m4.detectsystemd
|
||||
+++ httpd-2.4.25/acinclude.m4
|
||||
@@ -604,6 +604,30 @@
|
||||
fi
|
||||
])
|
||||
|
||||
+AC_DEFUN(APACHE_CHECK_SYSTEMD, [
|
||||
+dnl Check for systemd support for listen.c's socket activation.
|
||||
+case $host in
|
||||
+*-linux-*)
|
||||
+ if test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd; then
|
||||
+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd`
|
||||
+ elif test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd-daemon; then
|
||||
+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd-daemon`
|
||||
+ else
|
||||
+ AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon")
|
||||
+ fi
|
||||
+ if test -n "$SYSTEMD_LIBS"; then
|
||||
+ AC_CHECK_HEADERS(systemd/sd-daemon.h)
|
||||
+ if test "${ac_cv_header_systemd_sd_daemon_h}" = "no" || test -z "${SYSTEMD_LIBS}"; then
|
||||
+ AC_MSG_WARN([Your system does not support systemd.])
|
||||
+ else
|
||||
+ APR_ADDTO(HTTPD_LIBS, [$SYSTEMD_LIBS])
|
||||
+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is supported])
|
||||
+ fi
|
||||
+ fi
|
||||
+ ;;
|
||||
+esac
|
||||
+])
|
||||
+
|
||||
dnl
|
||||
dnl APACHE_EXPORT_ARGUMENTS
|
||||
dnl Export (via APACHE_SUBST) the various path-related variables that
|
||||
diff -uap httpd-2.4.25/configure.in.detectsystemd httpd-2.4.25/configure.in
|
||||
--- httpd-2.4.25/configure.in.detectsystemd
|
||||
+++ httpd-2.4.25/configure.in
|
||||
@ -45,15 +9,6 @@ diff -uap httpd-2.4.25/configure.in.detectsystemd httpd-2.4.25/configure.in
|
||||
else
|
||||
AC_MSG_ERROR([pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/])
|
||||
fi
|
||||
@@ -504,6 +510,8 @@
|
||||
AC_DEFINE(HAVE_GMTOFF, 1, [Define if struct tm has a tm_gmtoff field])
|
||||
fi
|
||||
|
||||
+APACHE_CHECK_SYSTEMD
|
||||
+
|
||||
dnl ## Set up any appropriate OS-specific environment variables for apachectl
|
||||
|
||||
case $host in
|
||||
@@ -668,6 +676,7 @@
|
||||
APACHE_SUBST(BUILTIN_LIBS)
|
||||
APACHE_SUBST(SHLIBPATH_VAR)
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
|
||||
Override default.
|
||||
|
||||
--- httpd-2.4.33/modules/md/mod_md_config.c.mddefault
|
||||
+++ httpd-2.4.33/modules/md/mod_md_config.c
|
||||
@@ -54,10 +54,14 @@
|
||||
|
||||
#define DEF_VAL (-1)
|
||||
|
||||
+#ifndef MD_DEFAULT_STORE_DIR
|
||||
+#define MD_DEFAULT_STORE_DIR "state/md"
|
||||
+#endif
|
||||
+
|
||||
/* Default settings for the global conf */
|
||||
static md_mod_conf_t defmc = {
|
||||
NULL,
|
||||
- "md",
|
||||
+ MD_DEFAULT_STORE_DIR,
|
||||
NULL,
|
||||
NULL,
|
||||
80,
|
||||
@ -1,690 +0,0 @@
|
||||
# ./pullrev.sh 1830819 1830836 1830912 1830913 1830927 1831168 1831173
|
||||
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1830819
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1830912
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1830913
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1830927
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1831168
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1831173
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1835240
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1835242
|
||||
|
||||
--- httpd-2.4.33/modules/ssl/ssl_engine_config.c.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_engine_config.c
|
||||
@@ -891,7 +891,9 @@
|
||||
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
const char *err;
|
||||
|
||||
- if ((err = ssl_cmd_check_file(cmd, &arg))) {
|
||||
+ /* Only check for non-ENGINE based certs. */
|
||||
+ if (!modssl_is_engine_id(arg)
|
||||
+ && (err = ssl_cmd_check_file(cmd, &arg))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -907,7 +909,9 @@
|
||||
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
const char *err;
|
||||
|
||||
- if ((err = ssl_cmd_check_file(cmd, &arg))) {
|
||||
+ /* Check keyfile exists for non-ENGINE keys. */
|
||||
+ if (!modssl_is_engine_id(arg)
|
||||
+ && (err = ssl_cmd_check_file(cmd, &arg))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
--- httpd-2.4.33/modules/ssl/ssl_engine_init.c.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_engine_init.c
|
||||
@@ -1181,12 +1182,18 @@
|
||||
(certfile = APR_ARRAY_IDX(mctx->pks->cert_files, i,
|
||||
const char *));
|
||||
i++) {
|
||||
+ EVP_PKEY *pkey;
|
||||
+ const char *engine_certfile = NULL;
|
||||
+
|
||||
key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
/* first the certificate (public key) */
|
||||
- if (mctx->cert_chain) {
|
||||
+ if (modssl_is_engine_id(certfile)) {
|
||||
+ engine_certfile = certfile;
|
||||
+ }
|
||||
+ else if (mctx->cert_chain) {
|
||||
if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile,
|
||||
SSL_FILETYPE_PEM) < 1)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561)
|
||||
@@ -1215,12 +1222,46 @@
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
- if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
|
||||
- SSL_FILETYPE_PEM) < 1) &&
|
||||
- (ERR_GET_FUNC(ERR_peek_last_error())
|
||||
- != X509_F_X509_CHECK_PRIVATE_KEY)) {
|
||||
+ if (modssl_is_engine_id(keyfile)) {
|
||||
+ apr_status_t rv;
|
||||
+
|
||||
+ cert = NULL;
|
||||
+
|
||||
+ if ((rv = modssl_load_engine_keypair(s, ptemp, vhost_id,
|
||||
+ engine_certfile, keyfile,
|
||||
+ &cert, &pkey))) {
|
||||
+ return rv;
|
||||
+ }
|
||||
+
|
||||
+ if (cert) {
|
||||
+ if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) < 1) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10137)
|
||||
+ "Failed to configure engine certificate %s, check %s",
|
||||
+ key_id, certfile);
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return APR_EGENERAL;
|
||||
+ }
|
||||
+
|
||||
+ /* SSL_CTX now owns the cert. */
|
||||
+ X509_free(cert);
|
||||
+ }
|
||||
+
|
||||
+ if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)
|
||||
+ "Failed to configure private key %s from engine",
|
||||
+ keyfile);
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return APR_EGENERAL;
|
||||
+ }
|
||||
+
|
||||
+ /* SSL_CTX now owns the key */
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ }
|
||||
+ else if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
|
||||
+ SSL_FILETYPE_PEM) < 1)
|
||||
+ && (ERR_GET_FUNC(ERR_peek_last_error())
|
||||
+ != X509_F_X509_CHECK_PRIVATE_KEY)) {
|
||||
ssl_asn1_t *asn1;
|
||||
- EVP_PKEY *pkey;
|
||||
const unsigned char *ptr;
|
||||
|
||||
ERR_clear_error();
|
||||
@@ -1307,8 +1348,9 @@
|
||||
/*
|
||||
* Try to read DH parameters from the (first) SSLCertificateFile
|
||||
*/
|
||||
- if ((certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *)) &&
|
||||
- (dhparams = ssl_dh_GetParamFromFile(certfile))) {
|
||||
+ certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *);
|
||||
+ if (certfile && !modssl_is_engine_id(certfile)
|
||||
+ && (dhparams = ssl_dh_GetParamFromFile(certfile))) {
|
||||
SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
|
||||
"Custom DH parameters (%d bits) for %s loaded from %s",
|
||||
@@ -1320,10 +1362,10 @@
|
||||
/*
|
||||
* Similarly, try to read the ECDH curve name from SSLCertificateFile...
|
||||
*/
|
||||
- if ((certfile != NULL) &&
|
||||
- (ecparams = ssl_ec_GetParamFromFile(certfile)) &&
|
||||
- (nid = EC_GROUP_get_curve_name(ecparams)) &&
|
||||
- (eckey = EC_KEY_new_by_curve_name(nid))) {
|
||||
+ if (certfile && !modssl_is_engine_id(certfile)
|
||||
+ && (ecparams = ssl_ec_GetParamFromFile(certfile))
|
||||
+ && (nid = EC_GROUP_get_curve_name(ecparams))
|
||||
+ && (eckey = EC_KEY_new_by_curve_name(nid))) {
|
||||
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541)
|
||||
"ECDH curve %s for %s specified in %s",
|
||||
--- httpd-2.4.33/modules/ssl/ssl_engine_pphrase.c.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_engine_pphrase.c
|
||||
@@ -143,9 +143,6 @@
|
||||
const char *key_id = asn1_table_vhost_key(mc, p, sc->vhost_id, idx);
|
||||
EVP_PKEY *pPrivateKey = NULL;
|
||||
ssl_asn1_t *asn1;
|
||||
- unsigned char *ucp;
|
||||
- long int length;
|
||||
- BOOL bReadable;
|
||||
int nPassPhrase = (*pphrases)->nelts;
|
||||
int nPassPhraseRetry = 0;
|
||||
apr_time_t pkey_mtime = 0;
|
||||
@@ -222,16 +219,12 @@
|
||||
* is not empty. */
|
||||
ERR_clear_error();
|
||||
|
||||
- bReadable = ((pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file,
|
||||
- NULL, ssl_pphrase_Handle_CB, &ppcb_arg)) != NULL ?
|
||||
- TRUE : FALSE);
|
||||
-
|
||||
- /*
|
||||
- * when the private key file now was readable,
|
||||
- * it's fine and we go out of the loop
|
||||
- */
|
||||
- if (bReadable)
|
||||
- break;
|
||||
+ pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file,
|
||||
+ ssl_pphrase_Handle_CB, &ppcb_arg);
|
||||
+ /* If the private key was successfully read, nothing more to
|
||||
+ do here. */
|
||||
+ if (pPrivateKey != NULL)
|
||||
+ break;
|
||||
|
||||
/*
|
||||
* when we have more remembered pass phrases
|
||||
@@ -356,19 +349,12 @@
|
||||
nPassPhrase++;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Insert private key into the global module configuration
|
||||
- * (we convert it to a stand-alone DER byte sequence
|
||||
- * because the SSL library uses static variables inside a
|
||||
- * RSA structure which do not survive DSO reloads!)
|
||||
- */
|
||||
- length = i2d_PrivateKey(pPrivateKey, NULL);
|
||||
- ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
|
||||
- (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
|
||||
+ /* Cache the private key in the global module configuration so it
|
||||
+ * can be used after subsequent reloads. */
|
||||
+ asn1 = ssl_asn1_table_set(mc->tPrivateKey, key_id, pPrivateKey);
|
||||
|
||||
if (ppcb_arg.nPassPhraseDialogCur != 0) {
|
||||
/* remember mtime of encrypted keys */
|
||||
- asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
|
||||
asn1->source_mtime = pkey_mtime;
|
||||
}
|
||||
|
||||
@@ -619,3 +605,288 @@
|
||||
*/
|
||||
return (len);
|
||||
}
|
||||
+
|
||||
+
|
||||
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
|
||||
+
|
||||
+/* OpenSSL UI implementation for passphrase entry; largely duplicated
|
||||
+ * from ssl_pphrase_Handle_CB but adjusted for UI API. TODO: Might be
|
||||
+ * worth trying to shift pphrase handling over to the UI API
|
||||
+ * completely. */
|
||||
+static int passphrase_ui_open(UI *ui)
|
||||
+{
|
||||
+ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
|
||||
+
|
||||
+ ppcb->nPassPhraseDialog++;
|
||||
+ ppcb->nPassPhraseDialogCur++;
|
||||
+
|
||||
+ /*
|
||||
+ * Builtin or Pipe dialog
|
||||
+ */
|
||||
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
|
||||
+ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
|
||||
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
|
||||
+ if (!readtty) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s,
|
||||
+ APLOGNO(10143)
|
||||
+ "Init: Creating pass phrase dialog pipe child "
|
||||
+ "'%s'", sc->server->pphrase_dialog_path);
|
||||
+ if (ssl_pipe_child_create(ppcb->p,
|
||||
+ sc->server->pphrase_dialog_path)
|
||||
+ != APR_SUCCESS) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s,
|
||||
+ APLOGNO(10144)
|
||||
+ "Init: Failed to create pass phrase pipe '%s'",
|
||||
+ sc->server->pphrase_dialog_path);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10145)
|
||||
+ "Init: Requesting pass phrase via piped dialog");
|
||||
+ }
|
||||
+ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
|
||||
+#ifdef WIN32
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb->s, APLOGNO(10146)
|
||||
+ "Init: Failed to create pass phrase pipe '%s'",
|
||||
+ sc->server->pphrase_dialog_path);
|
||||
+ return 0;
|
||||
+#else
|
||||
+ /*
|
||||
+ * stderr has already been redirected to the error_log.
|
||||
+ * rather than attempting to temporarily rehook it to the terminal,
|
||||
+ * we print the prompt to stdout before EVP_read_pw_string turns
|
||||
+ * off tty echo
|
||||
+ */
|
||||
+ apr_file_open_stdout(&writetty, ppcb->p);
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10147)
|
||||
+ "Init: Requesting pass phrase via builtin terminal "
|
||||
+ "dialog");
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The first time display a header to inform the user about what
|
||||
+ * program he actually speaks to, which module is responsible for
|
||||
+ * this terminal dialog and why to the hell he has to enter
|
||||
+ * something...
|
||||
+ */
|
||||
+ if (ppcb->nPassPhraseDialog == 1) {
|
||||
+ apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n",
|
||||
+ AP_SERVER_BASEVERSION);
|
||||
+ apr_file_printf(writetty,
|
||||
+ "A pass phrase is required to access the private key.\n");
|
||||
+ }
|
||||
+ if (ppcb->bPassPhraseDialogOnce) {
|
||||
+ ppcb->bPassPhraseDialogOnce = FALSE;
|
||||
+ apr_file_printf(writetty, "\n");
|
||||
+ apr_file_printf(writetty, "Private key %s (%s)\n",
|
||||
+ ppcb->key_id, ppcb->pkey_file);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int passphrase_ui_read(UI *ui, UI_STRING *uis)
|
||||
+{
|
||||
+ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(ppcb->s);
|
||||
+ const char *prompt;
|
||||
+ int i;
|
||||
+ int bufsize;
|
||||
+ int len;
|
||||
+ char *buf;
|
||||
+
|
||||
+ prompt = UI_get0_output_string(uis);
|
||||
+ if (prompt == NULL) {
|
||||
+ prompt = "Enter pass phrase:";
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Get the maximum expected size and allocate the buffer
|
||||
+ */
|
||||
+ bufsize = UI_get_result_maxsize(uis);
|
||||
+ buf = apr_pcalloc(ppcb->p, bufsize);
|
||||
+
|
||||
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
|
||||
+ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
|
||||
+ /*
|
||||
+ * Get the pass phrase through a callback.
|
||||
+ * Empty input is not accepted.
|
||||
+ */
|
||||
+ for (;;) {
|
||||
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
|
||||
+ i = pipe_get_passwd_cb(buf, bufsize, "", FALSE);
|
||||
+ }
|
||||
+ else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
|
||||
+ i = EVP_read_pw_string(buf, bufsize, "", FALSE);
|
||||
+ }
|
||||
+ if (i != 0) {
|
||||
+ OPENSSL_cleanse(buf, bufsize);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ len = strlen(buf);
|
||||
+ if (len < 1){
|
||||
+ apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase"
|
||||
+ "empty (needs to be at least 1 character).\n");
|
||||
+ apr_file_puts(prompt, writetty);
|
||||
+ }
|
||||
+ else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ /*
|
||||
+ * Filter program
|
||||
+ */
|
||||
+ else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) {
|
||||
+ const char *cmd = sc->server->pphrase_dialog_path;
|
||||
+ const char **argv = apr_palloc(ppcb->p, sizeof(char *) * 3);
|
||||
+ char *result;
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb->s, APLOGNO(10148)
|
||||
+ "Init: Requesting pass phrase from dialog filter "
|
||||
+ "program (%s)", cmd);
|
||||
+
|
||||
+ argv[0] = cmd;
|
||||
+ argv[1] = ppcb->key_id;
|
||||
+ argv[2] = NULL;
|
||||
+
|
||||
+ result = ssl_util_readfilter(ppcb->s, ppcb->p, cmd, argv);
|
||||
+ apr_cpystrn(buf, result, bufsize);
|
||||
+ len = strlen(buf);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Ok, we now have the pass phrase, so give it back
|
||||
+ */
|
||||
+ ppcb->cpPassPhraseCur = apr_pstrdup(ppcb->p, buf);
|
||||
+ UI_set_result(ui, uis, buf);
|
||||
+
|
||||
+ /* Clear sensitive data. */
|
||||
+ OPENSSL_cleanse(buf, bufsize);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int passphrase_ui_write(UI *ui, UI_STRING *uis)
|
||||
+{
|
||||
+ pphrase_cb_arg_t *ppcb = UI_get0_user_data(ui);
|
||||
+ SSLSrvConfigRec *sc;
|
||||
+ const char *prompt;
|
||||
+
|
||||
+ sc = mySrvConfig(ppcb->s);
|
||||
+
|
||||
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
|
||||
+ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
|
||||
+ prompt = UI_get0_output_string(uis);
|
||||
+ apr_file_puts(prompt, writetty);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int passphrase_ui_close(UI *ui)
|
||||
+{
|
||||
+ /*
|
||||
+ * Close the pipes if they were opened
|
||||
+ */
|
||||
+ if (readtty) {
|
||||
+ apr_file_close(readtty);
|
||||
+ apr_file_close(writetty);
|
||||
+ readtty = writetty = NULL;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static apr_status_t pp_ui_method_cleanup(void *uip)
|
||||
+{
|
||||
+ UI_METHOD *uim = uip;
|
||||
+
|
||||
+ UI_destroy_method(uim);
|
||||
+
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+static UI_METHOD *get_passphrase_ui(apr_pool_t *p)
|
||||
+{
|
||||
+ UI_METHOD *ui_method = UI_create_method("Passphrase UI");
|
||||
+
|
||||
+ UI_method_set_opener(ui_method, passphrase_ui_open);
|
||||
+ UI_method_set_reader(ui_method, passphrase_ui_read);
|
||||
+ UI_method_set_writer(ui_method, passphrase_ui_write);
|
||||
+ UI_method_set_closer(ui_method, passphrase_ui_close);
|
||||
+
|
||||
+ apr_pool_cleanup_register(p, ui_method, pp_ui_method_cleanup,
|
||||
+ pp_ui_method_cleanup);
|
||||
+
|
||||
+ return ui_method;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
|
||||
+ const char *vhostid,
|
||||
+ const char *certid, const char *keyid,
|
||||
+ X509 **pubkey, EVP_PKEY **privkey)
|
||||
+{
|
||||
+ SSLModConfigRec *mc = myModConfig(s);
|
||||
+ ENGINE *e;
|
||||
+ UI_METHOD *ui_method = get_passphrase_ui(p);
|
||||
+ pphrase_cb_arg_t ppcb;
|
||||
+
|
||||
+ memset(&ppcb, 0, sizeof ppcb);
|
||||
+ ppcb.s = s;
|
||||
+ ppcb.p = p;
|
||||
+ ppcb.bPassPhraseDialogOnce = TRUE;
|
||||
+ ppcb.key_id = vhostid;
|
||||
+ ppcb.pkey_file = keyid;
|
||||
+
|
||||
+ if (!mc->szCryptoDevice) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
|
||||
+ "Init: Cannot load private key `%s' without engine",
|
||||
+ keyid);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
|
||||
+ "Init: Failed to load Crypto Device API `%s'",
|
||||
+ mc->szCryptoDevice);
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ if (APLOGdebug(s)) {
|
||||
+ ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
|
||||
+ }
|
||||
+
|
||||
+ if (certid) {
|
||||
+ struct {
|
||||
+ const char *cert_id;
|
||||
+ X509 *cert;
|
||||
+ } params = { certid, NULL };
|
||||
+
|
||||
+ if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10136)
|
||||
+ "Init: Unable to get the certificate");
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ *pubkey = params.cert;
|
||||
+ }
|
||||
+
|
||||
+ *privkey = ENGINE_load_private_key(e, keyid, ui_method, &ppcb);
|
||||
+ if (*privkey == NULL) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
|
||||
+ "Init: Unable to get the private key");
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+
|
||||
+ ENGINE_free(e);
|
||||
+
|
||||
+ return APR_SUCCESS;
|
||||
+}
|
||||
+#endif
|
||||
--- httpd-2.4.33/modules/ssl/ssl_private.h.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_private.h
|
||||
@@ -976,21 +976,28 @@
|
||||
apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
|
||||
const char *, apr_array_header_t **);
|
||||
|
||||
+/* Load public and/or private key from the configured ENGINE. Private
|
||||
+ * key returned as *pkey. certid can be NULL, in which case *pubkey
|
||||
+ * is not altered. Errors logged on failure. */
|
||||
+apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
|
||||
+ const char *vhostid,
|
||||
+ const char *certid, const char *keyid,
|
||||
+ X509 **pubkey, EVP_PKEY **privkey);
|
||||
+
|
||||
/** Diffie-Hellman Parameter Support */
|
||||
DH *ssl_dh_GetParamFromFile(const char *);
|
||||
#ifdef HAVE_ECC
|
||||
EC_GROUP *ssl_ec_GetParamFromFile(const char *);
|
||||
#endif
|
||||
|
||||
-unsigned char *ssl_asn1_table_set(apr_hash_t *table,
|
||||
- const char *key,
|
||||
- long int length);
|
||||
-
|
||||
-ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
|
||||
- const char *key);
|
||||
-
|
||||
-void ssl_asn1_table_unset(apr_hash_t *table,
|
||||
- const char *key);
|
||||
+/* Store the EVP_PKEY key (serialized into DER) in the hash table with
|
||||
+ * key, returning the ssl_asn1_t structure pointer. */
|
||||
+ssl_asn1_t *ssl_asn1_table_set(apr_hash_t *table, const char *key,
|
||||
+ EVP_PKEY *pkey);
|
||||
+/* Retrieve the ssl_asn1_t structure with given key from the hash. */
|
||||
+ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table, const char *key);
|
||||
+/* Remove and free the ssl_asn1_t structure with given key. */
|
||||
+void ssl_asn1_table_unset(apr_hash_t *table, const char *key);
|
||||
|
||||
/** Mutex Support */
|
||||
int ssl_mutex_init(server_rec *, apr_pool_t *);
|
||||
@@ -1078,6 +1085,10 @@
|
||||
int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
X509 **pcert, EVP_PKEY **pkey);
|
||||
|
||||
+/* Returns non-zero if the cert/key filename should be handled through
|
||||
+ * the configured ENGINE. */
|
||||
+int modssl_is_engine_id(const char *name);
|
||||
+
|
||||
#endif /* SSL_PRIVATE_H */
|
||||
/** @} */
|
||||
|
||||
--- httpd-2.4.33/modules/ssl/ssl_util.c.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_util.c
|
||||
@@ -181,45 +181,37 @@
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * certain key data needs to survive restarts,
|
||||
- * which are stored in the user data table of s->process->pool.
|
||||
- * to prevent "leaking" of this data, we use malloc/free
|
||||
- * rather than apr_palloc and these wrappers to help make sure
|
||||
- * we do not leak the malloc-ed data.
|
||||
- */
|
||||
-unsigned char *ssl_asn1_table_set(apr_hash_t *table,
|
||||
- const char *key,
|
||||
- long int length)
|
||||
+/* Decrypted private keys are cached to survive restarts. The cached
|
||||
+ * data must have lifetime of the process (hence malloc/free rather
|
||||
+ * than pools), and uses raw DER since the EVP_PKEY structure
|
||||
+ * internals may not survive across a module reload. */
|
||||
+ssl_asn1_t *ssl_asn1_table_set(apr_hash_t *table, const char *key,
|
||||
+ EVP_PKEY *pkey)
|
||||
{
|
||||
apr_ssize_t klen = strlen(key);
|
||||
ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
|
||||
+ apr_size_t length = i2d_PrivateKey(pkey, NULL);
|
||||
+ unsigned char *p;
|
||||
|
||||
- /*
|
||||
- * if a value for this key already exists,
|
||||
- * reuse as much of the already malloc-ed data
|
||||
- * as possible.
|
||||
- */
|
||||
+ /* Re-use structure if cached previously. */
|
||||
if (asn1) {
|
||||
if (asn1->nData != length) {
|
||||
- free(asn1->cpData); /* XXX: realloc? */
|
||||
- asn1->cpData = NULL;
|
||||
+ asn1->cpData = ap_realloc(asn1->cpData, length);
|
||||
}
|
||||
}
|
||||
else {
|
||||
asn1 = ap_malloc(sizeof(*asn1));
|
||||
asn1->source_mtime = 0; /* used as a note for encrypted private keys */
|
||||
- asn1->cpData = NULL;
|
||||
- }
|
||||
-
|
||||
- asn1->nData = length;
|
||||
- if (!asn1->cpData) {
|
||||
asn1->cpData = ap_malloc(length);
|
||||
+
|
||||
+ apr_hash_set(table, key, klen, asn1);
|
||||
}
|
||||
|
||||
- apr_hash_set(table, key, klen, asn1);
|
||||
+ asn1->nData = length;
|
||||
+ p = asn1->cpData;
|
||||
+ i2d_PrivateKey(pkey, &p); /* increases p by length */
|
||||
|
||||
- return asn1->cpData; /* caller will assign a value to this */
|
||||
+ return asn1;
|
||||
}
|
||||
|
||||
ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
|
||||
@@ -469,3 +461,13 @@
|
||||
}
|
||||
|
||||
#endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
|
||||
+
|
||||
+int modssl_is_engine_id(const char *name)
|
||||
+{
|
||||
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
|
||||
+ /* ### Can handle any other special ENGINE key names here? */
|
||||
+ return strncmp(name, "pkcs11:", 7) == 0;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
--- httpd-2.4.33/modules/ssl/ssl_util_ssl.c.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_util_ssl.c
|
||||
@@ -74,7 +74,7 @@
|
||||
** _________________________________________________________________
|
||||
*/
|
||||
|
||||
-EVP_PKEY *modssl_read_privatekey(const char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s)
|
||||
+EVP_PKEY *modssl_read_privatekey(const char *filename, pem_password_cb *cb, void *s)
|
||||
{
|
||||
EVP_PKEY *rc;
|
||||
BIO *bioS;
|
||||
@@ -83,7 +83,7 @@
|
||||
/* 1. try PEM (= DER+Base64+headers) */
|
||||
if ((bioS=BIO_new_file(filename, "r")) == NULL)
|
||||
return NULL;
|
||||
- rc = PEM_read_bio_PrivateKey(bioS, key, cb, s);
|
||||
+ rc = PEM_read_bio_PrivateKey(bioS, NULL, cb, s);
|
||||
BIO_free(bioS);
|
||||
|
||||
if (rc == NULL) {
|
||||
@@ -107,41 +107,9 @@
|
||||
BIO_free(bioS);
|
||||
}
|
||||
}
|
||||
- if (rc != NULL && key != NULL) {
|
||||
- if (*key != NULL)
|
||||
- EVP_PKEY_free(*key);
|
||||
- *key = rc;
|
||||
- }
|
||||
return rc;
|
||||
}
|
||||
|
||||
-typedef struct {
|
||||
- const char *pass;
|
||||
- int pass_len;
|
||||
-} pass_ctx;
|
||||
-
|
||||
-static int provide_pass(char *buf, int size, int rwflag, void *baton)
|
||||
-{
|
||||
- pass_ctx *ctx = baton;
|
||||
- if (ctx->pass_len > 0) {
|
||||
- if (ctx->pass_len < size) {
|
||||
- size = (int)ctx->pass_len;
|
||||
- }
|
||||
- memcpy(buf, ctx->pass, size);
|
||||
- }
|
||||
- return ctx->pass_len;
|
||||
-}
|
||||
-
|
||||
-EVP_PKEY *modssl_read_encrypted_pkey(const char *filename, EVP_PKEY **key,
|
||||
- const char *pass, apr_size_t pass_len)
|
||||
-{
|
||||
- pass_ctx ctx;
|
||||
-
|
||||
- ctx.pass = pass;
|
||||
- ctx.pass_len = pass_len;
|
||||
- return modssl_read_privatekey(filename, key, provide_pass, &ctx);
|
||||
-}
|
||||
-
|
||||
/* _________________________________________________________________
|
||||
**
|
||||
** Smart shutdown
|
||||
--- httpd-2.4.33/modules/ssl/ssl_util_ssl.h.r1830819+
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_util_ssl.h
|
||||
@@ -64,8 +64,11 @@
|
||||
void modssl_init_app_data2_idx(void);
|
||||
void *modssl_get_app_data2(SSL *);
|
||||
void modssl_set_app_data2(SSL *, void *);
|
||||
-EVP_PKEY *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, void *);
|
||||
-EVP_PKEY *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t);
|
||||
+
|
||||
+/* Read private key from filename in either PEM or raw base64(DER)
|
||||
+ * format, using password entry callback cb and userdata. */
|
||||
+EVP_PKEY *modssl_read_privatekey(const char *filename, pem_password_cb *cb, void *ud);
|
||||
+
|
||||
int modssl_smart_shutdown(SSL *ssl);
|
||||
BOOL modssl_X509_getBC(X509 *, int *, int *);
|
||||
char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne,
|
||||
@ -1,126 +0,0 @@
|
||||
From ce2d1d7d4b2bebe34cf37fdeb30d35050092c5b5 Mon Sep 17 00:00:00 2001
|
||||
From: Rob Crittenden <rcrit@cow.greyoak.com>
|
||||
Date: Thu, 12 Apr 2018 14:36:28 -0400
|
||||
Subject: [PATCH] httpd-2.4.18-sslmultiproxy.patch
|
||||
|
||||
---
|
||||
modules/ssl/mod_ssl.c | 24 ++++++++++++++++++++++--
|
||||
modules/ssl/ssl_engine_vars.c | 18 +++++++++++++++++-
|
||||
2 files changed, 39 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
||||
index 48d64cb..42e85a3 100644
|
||||
diff -uap httpd-2.4.33/modules/ssl/mod_ssl.c.sslmultiproxy httpd-2.4.33/modules/ssl/mod_ssl.c
|
||||
--- httpd-2.4.33/modules/ssl/mod_ssl.c.sslmultiproxy
|
||||
+++ httpd-2.4.33/modules/ssl/mod_ssl.c
|
||||
@@ -444,12 +444,19 @@
|
||||
return OK;
|
||||
}
|
||||
|
||||
+static APR_OPTIONAL_FN_TYPE(ssl_engine_disable) *othermod_engine_disable;
|
||||
+static APR_OPTIONAL_FN_TYPE(ssl_engine_set) *othermod_engine_set;
|
||||
+
|
||||
static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
|
||||
ap_conf_vector_t *per_dir_config)
|
||||
{
|
||||
SSLConnRec *sslconn = myConnConfig(c);
|
||||
SSLSrvConfigRec *sc;
|
||||
|
||||
+ if (othermod_engine_disable) {
|
||||
+ othermod_engine_disable(c);
|
||||
+ }
|
||||
+
|
||||
if (sslconn) {
|
||||
return sslconn;
|
||||
}
|
||||
@@ -508,6 +515,10 @@
|
||||
{
|
||||
SSLConnRec *sslconn;
|
||||
int status;
|
||||
+
|
||||
+ if (othermod_engine_set) {
|
||||
+ return othermod_engine_set(c, per_dir_config, proxy, enable);
|
||||
+ }
|
||||
|
||||
if (proxy) {
|
||||
sslconn = ssl_init_connection_ctx(c, per_dir_config);
|
||||
@@ -537,12 +548,18 @@
|
||||
|
||||
static int ssl_proxy_enable(conn_rec *c)
|
||||
{
|
||||
- return ssl_engine_set(c, NULL, 1, 1);
|
||||
+ if (othermod_engine_set)
|
||||
+ return othermod_engine_set(c, NULL, 1, 1);
|
||||
+ else
|
||||
+ return ssl_engine_set(c, NULL, 1, 1);
|
||||
}
|
||||
|
||||
static int ssl_engine_disable(conn_rec *c)
|
||||
{
|
||||
- return ssl_engine_set(c, NULL, 0, 0);
|
||||
+ if (othermod_engine_set)
|
||||
+ return othermod_engine_set(c, NULL, 0, 0);
|
||||
+ else
|
||||
+ return ssl_engine_set(c, NULL, 0, 0);
|
||||
}
|
||||
|
||||
int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
|
||||
@@ -730,6 +747,9 @@
|
||||
APR_HOOK_MIDDLE);
|
||||
|
||||
ssl_var_register(p);
|
||||
+
|
||||
+ othermod_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
|
||||
+ othermod_engine_set = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_set);
|
||||
|
||||
APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
|
||||
APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
|
||||
diff -uap httpd-2.4.33/modules/ssl/ssl_engine_vars.c.sslmultiproxy httpd-2.4.33/modules/ssl/ssl_engine_vars.c
|
||||
--- httpd-2.4.33/modules/ssl/ssl_engine_vars.c.sslmultiproxy
|
||||
+++ httpd-2.4.33/modules/ssl/ssl_engine_vars.c
|
||||
@@ -54,6 +54,8 @@
|
||||
static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
|
||||
static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var);
|
||||
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
|
||||
+static APR_OPTIONAL_FN_TYPE(ssl_is_https) *othermod_is_https;
|
||||
+static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *othermod_var_lookup;
|
||||
|
||||
static SSLConnRec *ssl_get_effective_config(conn_rec *c)
|
||||
{
|
||||
@@ -68,7 +70,9 @@
|
||||
static int ssl_is_https(conn_rec *c)
|
||||
{
|
||||
SSLConnRec *sslconn = ssl_get_effective_config(c);
|
||||
- return sslconn && sslconn->ssl;
|
||||
+
|
||||
+ return (sslconn && sslconn->ssl)
|
||||
+ || (othermod_is_https && othermod_is_https(c));
|
||||
}
|
||||
|
||||
static const char var_interface[] = "mod_ssl/" AP_SERVER_BASEREVISION;
|
||||
@@ -137,6 +141,9 @@
|
||||
{
|
||||
char *cp, *cp2;
|
||||
|
||||
+ othermod_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
|
||||
+ othermod_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
|
||||
+
|
||||
APR_REGISTER_OPTIONAL_FN(ssl_is_https);
|
||||
APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
|
||||
APR_REGISTER_OPTIONAL_FN(ssl_ext_list);
|
||||
@@ -271,6 +278,15 @@
|
||||
*/
|
||||
if (result == NULL && c != NULL) {
|
||||
SSLConnRec *sslconn = ssl_get_effective_config(c);
|
||||
+
|
||||
+ if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
|
||||
+ && (!sslconn || !sslconn->ssl) && othermod_var_lookup) {
|
||||
+ /* For an SSL_* variable, if mod_ssl is not enabled for
|
||||
+ * this connection and another SSL module is present, pass
|
||||
+ * through to that module. */
|
||||
+ return othermod_var_lookup(p, s, c, r, var);
|
||||
+ }
|
||||
+
|
||||
if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
|
||||
&& sslconn && sslconn->ssl)
|
||||
result = ssl_var_lookup_ssl(p, sslconn, r, var+4);
|
||||
@ -1,245 +0,0 @@
|
||||
--- httpd-2.4.33/modules/arch/unix/config5.m4.systemd
|
||||
+++ httpd-2.4.33/modules/arch/unix/config5.m4
|
||||
@@ -18,6 +18,16 @@
|
||||
fi
|
||||
])
|
||||
|
||||
+APACHE_MODULE(systemd, Systemd support, , , all, [
|
||||
+ if test "${ac_cv_header_systemd_sd_daemon_h}" = "no" || test -z "${SYSTEMD_LIBS}"; then
|
||||
+ AC_MSG_WARN([Your system does not support systemd.])
|
||||
+ enable_systemd="no"
|
||||
+ else
|
||||
+ APR_ADDTO(MOD_SYSTEMD_LDADD, [$SYSTEMD_LIBS])
|
||||
+ enable_systemd="yes"
|
||||
+ fi
|
||||
+])
|
||||
+
|
||||
APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
|
||||
|
||||
APACHE_MODPATH_FINISH
|
||||
--- httpd-2.4.33/modules/arch/unix/mod_systemd.c.systemd
|
||||
+++ httpd-2.4.33/modules/arch/unix/mod_systemd.c
|
||||
@@ -0,0 +1,223 @@
|
||||
+/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
+ * contributor license agreements. See the NOTICE file distributed with
|
||||
+ * this work for additional information regarding copyright ownership.
|
||||
+ * The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
+ * (the "License"); you may not use this file except in compliance with
|
||||
+ * the License. You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include <ap_config.h>
|
||||
+#include "ap_mpm.h"
|
||||
+#include <http_core.h>
|
||||
+#include <httpd.h>
|
||||
+#include <http_log.h>
|
||||
+#include <apr_version.h>
|
||||
+#include <apr_pools.h>
|
||||
+#include <apr_strings.h>
|
||||
+#include "unixd.h"
|
||||
+#include "scoreboard.h"
|
||||
+#include "mpm_common.h"
|
||||
+
|
||||
+#include "systemd/sd-daemon.h"
|
||||
+#include "systemd/sd-journal.h"
|
||||
+
|
||||
+#if APR_HAVE_UNISTD_H
|
||||
+#include <unistd.h>
|
||||
+#endif
|
||||
+
|
||||
+static int shutdown_timer = 0;
|
||||
+static int shutdown_counter = 0;
|
||||
+static unsigned long bytes_served;
|
||||
+static pid_t mainpid;
|
||||
+static char describe_listeners[50];
|
||||
+
|
||||
+static int systemd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
+ apr_pool_t *ptemp)
|
||||
+{
|
||||
+ sd_notify(0,
|
||||
+ "RELOADING=1\n"
|
||||
+ "STATUS=Reading configuration...\n");
|
||||
+ ap_extended_status = 1;
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
+static char *dump_listener(ap_listen_rec *lr, apr_pool_t *p)
|
||||
+{
|
||||
+ apr_sockaddr_t *sa = lr->bind_addr;
|
||||
+ char addr[128];
|
||||
+
|
||||
+ if (apr_sockaddr_is_wildcard(sa)) {
|
||||
+ return apr_pstrcat(p, "port ", apr_itoa(p, sa->port), NULL);
|
||||
+ }
|
||||
+
|
||||
+ apr_sockaddr_ip_getbuf(addr, sizeof addr, sa);
|
||||
+
|
||||
+ return apr_psprintf(p, "%s port %u", addr, sa->port);
|
||||
+}
|
||||
+
|
||||
+static int systemd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
+ apr_pool_t *ptemp, server_rec *s)
|
||||
+{
|
||||
+ ap_listen_rec *lr;
|
||||
+ apr_size_t plen = sizeof describe_listeners;
|
||||
+ char *p = describe_listeners;
|
||||
+
|
||||
+ if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
|
||||
+ return OK;
|
||||
+
|
||||
+ for (lr = ap_listeners; lr; lr = lr->next) {
|
||||
+ char *s = dump_listener(lr, ptemp);
|
||||
+
|
||||
+ if (strlen(s) + 3 < plen) {
|
||||
+ char *newp = apr_cpystrn(p, s, plen);
|
||||
+ if (lr->next)
|
||||
+ newp = apr_cpystrn(newp, ", ", 3);
|
||||
+ plen -= newp - p;
|
||||
+ p = newp;
|
||||
+ }
|
||||
+ else {
|
||||
+ if (plen < 4) {
|
||||
+ p = describe_listeners + sizeof describe_listeners - 4;
|
||||
+ plen = 4;
|
||||
+ }
|
||||
+ apr_cpystrn(p, "...", plen);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ sd_journal_print(LOG_INFO, "Server configured, listening on: %s", describe_listeners);
|
||||
+
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
+static int systemd_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
|
||||
+{
|
||||
+ int rv;
|
||||
+
|
||||
+ mainpid = getpid();
|
||||
+
|
||||
+ rv = sd_notifyf(0, "READY=1\n"
|
||||
+ "STATUS=Started, listening on: %s\n"
|
||||
+ "MAINPID=%" APR_PID_T_FMT,
|
||||
+ describe_listeners, mainpid);
|
||||
+ if (rv < 0) {
|
||||
+ ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p, APLOGNO(02395)
|
||||
+ "sd_notifyf returned an error %d", rv);
|
||||
+ }
|
||||
+
|
||||
+ return OK;
|
||||
+}
|
||||
+
|
||||
+static int systemd_monitor(apr_pool_t *p, server_rec *s)
|
||||
+{
|
||||
+ ap_sload_t sload;
|
||||
+ apr_interval_time_t up_time;
|
||||
+ char bps[5];
|
||||
+ int rv;
|
||||
+
|
||||
+ if (!ap_extended_status) {
|
||||
+ /* Nothing useful to report if ExtendedStatus disabled. */
|
||||
+ return DECLINED;
|
||||
+ }
|
||||
+
|
||||
+ ap_get_sload(&sload);
|
||||
+
|
||||
+ if (sload.access_count == 0) {
|
||||
+ rv = sd_notifyf(0, "READY=1\n"
|
||||
+ "STATUS=Running, listening on: %s\n",
|
||||
+ describe_listeners);
|
||||
+ }
|
||||
+ else {
|
||||
+ /* up_time in seconds */
|
||||
+ up_time = (apr_uint32_t) apr_time_sec(apr_time_now() -
|
||||
+ ap_scoreboard_image->global->restart_time);
|
||||
+
|
||||
+ apr_strfsize((unsigned long)((float) (sload.bytes_served)
|
||||
+ / (float) up_time), bps);
|
||||
+
|
||||
+ rv = sd_notifyf(0, "READY=1\n"
|
||||
+ "STATUS=Total requests: %lu; Idle/Busy workers %d/%d;"
|
||||
+ "Requests/sec: %.3g; Bytes served/sec: %sB/sec\n",
|
||||
+ sload.access_count, sload.idle, sload.busy,
|
||||
+ ((float) sload.access_count) / (float) up_time, bps);
|
||||
+ }
|
||||
+
|
||||
+ if (rv < 0) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02396)
|
||||
+ "sd_notifyf returned an error %d", rv);
|
||||
+ }
|
||||
+
|
||||
+ /* Shutdown httpd when nothing is sent for shutdown_timer seconds. */
|
||||
+ if (sload.bytes_served == bytes_served) {
|
||||
+ /* mpm_common.c: INTERVAL_OF_WRITABLE_PROBES is 10 */
|
||||
+ shutdown_counter += 10;
|
||||
+ if (shutdown_timer > 0 && shutdown_counter >= shutdown_timer) {
|
||||
+ rv = sd_notifyf(0, "READY=1\n"
|
||||
+ "STATUS=Stopped as result of IdleShutdown "
|
||||
+ "timeout.");
|
||||
+ if (rv < 0) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02804)
|
||||
+ "sd_notifyf returned an error %d", rv);
|
||||
+ }
|
||||
+ kill(mainpid, AP_SIG_GRACEFUL);
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ shutdown_counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ bytes_served = sload.bytes_served;
|
||||
+
|
||||
+ return DECLINED;
|
||||
+}
|
||||
+
|
||||
+static void systemd_register_hooks(apr_pool_t *p)
|
||||
+{
|
||||
+ /* Enable ap_extended_status. */
|
||||
+ ap_hook_pre_config(systemd_pre_config, NULL, NULL, APR_HOOK_LAST);
|
||||
+ /* Grab the listener config. */
|
||||
+ ap_hook_post_config(systemd_post_config, NULL, NULL, APR_HOOK_LAST);
|
||||
+ /* We know the PID in this hook ... */
|
||||
+ ap_hook_pre_mpm(systemd_pre_mpm, NULL, NULL, APR_HOOK_LAST);
|
||||
+ /* Used to update httpd's status line using sd_notifyf */
|
||||
+ ap_hook_monitor(systemd_monitor, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
+}
|
||||
+
|
||||
+static const char *set_shutdown_timer(cmd_parms *cmd, void *dummy,
|
||||
+ const char *arg)
|
||||
+{
|
||||
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
||||
+ if (err != NULL) {
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ shutdown_timer = atoi(arg);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static const command_rec systemd_cmds[] =
|
||||
+{
|
||||
+AP_INIT_TAKE1("IdleShutdown", set_shutdown_timer, NULL, RSRC_CONF,
|
||||
+ "Number of seconds in idle-state after which httpd is shutdown"),
|
||||
+ {NULL}
|
||||
+};
|
||||
+
|
||||
+AP_DECLARE_MODULE(systemd) = {
|
||||
+ STANDARD20_MODULE_STUFF,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ systemd_cmds,
|
||||
+ systemd_register_hooks,
|
||||
+};
|
||||
@ -1,14 +0,0 @@
|
||||
# ./pullrev.sh 1555631
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1555631
|
||||
|
||||
--- httpd-2.4.34/modules/ssl/ssl_engine_ocsp.c
|
||||
+++ httpd-2.4.34/modules/ssl/ssl_engine_ocsp.c
|
||||
@@ -61,7 +61,7 @@
|
||||
/* Use default responder URL if forced by configuration, else use
|
||||
* certificate-specified responder, falling back to default if
|
||||
* necessary and possible. */
|
||||
- if (sc->server->ocsp_force_default) {
|
||||
+ if (sc->server->ocsp_force_default == TRUE) {
|
||||
s = sc->server->ocsp_responder;
|
||||
}
|
||||
else {
|
||||
@ -1,130 +0,0 @@
|
||||
--- httpd-2.4.34/modules/proxy/ajp_header.c.r1738878
|
||||
+++ httpd-2.4.34/modules/proxy/ajp_header.c
|
||||
@@ -213,7 +213,8 @@
|
||||
|
||||
static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
|
||||
request_rec *r,
|
||||
- apr_uri_t *uri)
|
||||
+ apr_uri_t *uri,
|
||||
+ const char *secret)
|
||||
{
|
||||
int method;
|
||||
apr_uint32_t i, num_headers = 0;
|
||||
@@ -293,17 +294,15 @@
|
||||
i, elts[i].key, elts[i].val);
|
||||
}
|
||||
|
||||
-/* XXXX need to figure out how to do this
|
||||
- if (s->secret) {
|
||||
+ if (secret) {
|
||||
if (ajp_msg_append_uint8(msg, SC_A_SECRET) ||
|
||||
- ajp_msg_append_string(msg, s->secret)) {
|
||||
+ ajp_msg_append_string(msg, secret)) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(03228)
|
||||
- "Error ajp_marshal_into_msgb - "
|
||||
+ "ajp_marshal_into_msgb: "
|
||||
"Error appending secret");
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
}
|
||||
- */
|
||||
|
||||
if (r->user) {
|
||||
if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
|
||||
@@ -671,7 +670,8 @@
|
||||
apr_status_t ajp_send_header(apr_socket_t *sock,
|
||||
request_rec *r,
|
||||
apr_size_t buffsize,
|
||||
- apr_uri_t *uri)
|
||||
+ apr_uri_t *uri,
|
||||
+ const char *secret)
|
||||
{
|
||||
ajp_msg_t *msg;
|
||||
apr_status_t rc;
|
||||
@@ -683,7 +683,7 @@
|
||||
return rc;
|
||||
}
|
||||
|
||||
- rc = ajp_marshal_into_msgb(msg, r, uri);
|
||||
+ rc = ajp_marshal_into_msgb(msg, r, uri, secret);
|
||||
if (rc != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00988)
|
||||
"ajp_send_header: ajp_marshal_into_msgb failed");
|
||||
--- httpd-2.4.34/modules/proxy/ajp.h.r1738878
|
||||
+++ httpd-2.4.34/modules/proxy/ajp.h
|
||||
@@ -413,12 +413,14 @@
|
||||
* @param sock backend socket
|
||||
* @param r current request
|
||||
* @param buffsize max size of the AJP packet.
|
||||
+ * @param secret authentication secret
|
||||
* @param uri requested uri
|
||||
* @return APR_SUCCESS or error
|
||||
*/
|
||||
apr_status_t ajp_send_header(apr_socket_t *sock, request_rec *r,
|
||||
apr_size_t buffsize,
|
||||
- apr_uri_t *uri);
|
||||
+ apr_uri_t *uri,
|
||||
+ const char *secret);
|
||||
|
||||
/**
|
||||
* Read the ajp message and return the type of the message.
|
||||
--- httpd-2.4.34/modules/proxy/mod_proxy_ajp.c.r1738878
|
||||
+++ httpd-2.4.34/modules/proxy/mod_proxy_ajp.c
|
||||
@@ -193,6 +193,7 @@
|
||||
apr_off_t content_length = 0;
|
||||
int original_status = r->status;
|
||||
const char *original_status_line = r->status_line;
|
||||
+ const char *secret = NULL;
|
||||
|
||||
if (psf->io_buffer_size_set)
|
||||
maxsize = psf->io_buffer_size;
|
||||
@@ -202,12 +203,15 @@
|
||||
maxsize = AJP_MSG_BUFFER_SZ;
|
||||
maxsize = APR_ALIGN(maxsize, 1024);
|
||||
|
||||
+ if (*conn->worker->s->secret)
|
||||
+ secret = conn->worker->s->secret;
|
||||
+
|
||||
/*
|
||||
* Send the AJP request to the remote server
|
||||
*/
|
||||
|
||||
/* send request headers */
|
||||
- status = ajp_send_header(conn->sock, r, maxsize, uri);
|
||||
+ status = ajp_send_header(conn->sock, r, maxsize, uri, secret);
|
||||
if (status != APR_SUCCESS) {
|
||||
conn->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00868)
|
||||
--- httpd-2.4.34/modules/proxy/mod_proxy.c.r1738878
|
||||
+++ httpd-2.4.34/modules/proxy/mod_proxy.c
|
||||
@@ -319,6 +319,12 @@
|
||||
(int)sizeof(worker->s->upgrade));
|
||||
}
|
||||
}
|
||||
+ else if (!strcasecmp(key, "secret")) {
|
||||
+ if (PROXY_STRNCPY(worker->s->secret, val) != APR_SUCCESS) {
|
||||
+ return apr_psprintf(p, "Secret length must be < %d characters",
|
||||
+ (int)sizeof(worker->s->secret));
|
||||
+ }
|
||||
+ }
|
||||
else if (!strcasecmp(key, "responsefieldsize")) {
|
||||
long s = atol(val);
|
||||
if (s < 0) {
|
||||
--- httpd-2.4.34/modules/proxy/mod_proxy.h.r1738878
|
||||
+++ httpd-2.4.34/modules/proxy/mod_proxy.h
|
||||
@@ -357,6 +357,7 @@
|
||||
#define PROXY_WORKER_MAX_HOSTNAME_SIZE 64
|
||||
#define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE
|
||||
#define PROXY_BALANCER_MAX_STICKY_SIZE 64
|
||||
+#define PROXY_WORKER_MAX_SECRET_SIZE 64
|
||||
|
||||
#define PROXY_RFC1035_HOSTNAME_SIZE 256
|
||||
|
||||
@@ -453,6 +454,7 @@
|
||||
char hostname_ex[PROXY_RFC1035_HOSTNAME_SIZE]; /* RFC1035 compliant version of the remote backend address */
|
||||
apr_size_t response_field_size; /* Size of proxy response buffer in bytes. */
|
||||
unsigned int response_field_size_set:1;
|
||||
+ char secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */
|
||||
} proxy_worker_shared;
|
||||
|
||||
#define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared)))
|
||||
@ -1,858 +0,0 @@
|
||||
|
||||
Pull all changes from upstream integration branch:
|
||||
|
||||
svn diff -r1840105:1841219 https://svn.apache.org/repos/asf/httpd/httpd/branches/tlsv1.3-for-2.4.x
|
||||
|
||||
--- httpd-2.4.34/modules/ssl/mod_ssl.c.r1827912+
|
||||
+++ httpd-2.4.34/modules/ssl/mod_ssl.c
|
||||
@@ -93,9 +93,9 @@
|
||||
SSL_CMD_SRV(FIPS, FLAG,
|
||||
"Enable FIPS-140 mode "
|
||||
"(`on', `off')")
|
||||
- SSL_CMD_ALL(CipherSuite, TAKE1,
|
||||
- "Colon-delimited list of permitted SSL Ciphers "
|
||||
- "('XXX:...:XXX' - see manual)")
|
||||
+ SSL_CMD_ALL(CipherSuite, TAKE12,
|
||||
+ "Colon-delimited list of permitted SSL Ciphers, optional preceeded "
|
||||
+ "by protocol identifier ('XXX:...:XXX' - see manual)")
|
||||
SSL_CMD_SRV(CertificateFile, TAKE1,
|
||||
"SSL Server Certificate file "
|
||||
"('/path/to/file' - PEM or DER encoded)")
|
||||
@@ -185,9 +185,9 @@
|
||||
SSL_CMD_PXY(ProxyProtocol, RAW_ARGS,
|
||||
"SSL Proxy: enable or disable SSL protocol flavors "
|
||||
"('[+-][" SSL_PROTOCOLS "] ...' - see manual)")
|
||||
- SSL_CMD_PXY(ProxyCipherSuite, TAKE1,
|
||||
+ SSL_CMD_PXY(ProxyCipherSuite, TAKE12,
|
||||
"SSL Proxy: colon-delimited list of permitted SSL ciphers "
|
||||
- "('XXX:...:XXX' - see manual)")
|
||||
+ ", optionally preceeded by protocol specifier ('XXX:...:XXX' - see manual)")
|
||||
SSL_CMD_PXY(ProxyVerify, TAKE1,
|
||||
"SSL Proxy: whether to verify the remote certificate "
|
||||
"('on' or 'off')")
|
||||
@@ -398,7 +398,7 @@
|
||||
/* We must register the library in full, to ensure our configuration
|
||||
* code can successfully test the SSL environment.
|
||||
*/
|
||||
-#if MODSSL_USE_OPENSSL_PRE_1_1_API
|
||||
+#if MODSSL_USE_OPENSSL_PRE_1_1_API || defined(LIBRESSL_VERSION_NUMBER)
|
||||
(void)CRYPTO_malloc_init();
|
||||
#else
|
||||
OPENSSL_malloc_init();
|
||||
--- httpd-2.4.34/modules/ssl/ssl_engine_config.c.r1827912+
|
||||
+++ httpd-2.4.34/modules/ssl/ssl_engine_config.c
|
||||
@@ -136,6 +136,7 @@
|
||||
mctx->auth.cipher_suite = NULL;
|
||||
mctx->auth.verify_depth = UNSET;
|
||||
mctx->auth.verify_mode = SSL_CVERIFY_UNSET;
|
||||
+ mctx->auth.tls13_ciphers = NULL;
|
||||
|
||||
mctx->ocsp_mask = UNSET;
|
||||
mctx->ocsp_force_default = UNSET;
|
||||
@@ -280,6 +281,7 @@
|
||||
cfgMergeString(auth.cipher_suite);
|
||||
cfgMergeInt(auth.verify_depth);
|
||||
cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET);
|
||||
+ cfgMergeString(auth.tls13_ciphers);
|
||||
|
||||
cfgMergeInt(ocsp_mask);
|
||||
cfgMergeBool(ocsp_force_default);
|
||||
@@ -761,22 +763,37 @@
|
||||
|
||||
const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
|
||||
void *dcfg,
|
||||
- const char *arg)
|
||||
+ const char *arg1, const char *arg2)
|
||||
{
|
||||
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
|
||||
|
||||
- /* always disable null and export ciphers */
|
||||
- arg = apr_pstrcat(cmd->pool, arg, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
-
|
||||
- if (cmd->path) {
|
||||
- dc->szCipherSuite = arg;
|
||||
+ if (arg2 == NULL) {
|
||||
+ arg2 = arg1;
|
||||
+ arg1 = "SSL";
|
||||
}
|
||||
- else {
|
||||
- sc->server->auth.cipher_suite = arg;
|
||||
+
|
||||
+ if (!strcmp("SSL", arg1)) {
|
||||
+ /* always disable null and export ciphers */
|
||||
+ arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
+ if (cmd->path) {
|
||||
+ dc->szCipherSuite = arg2;
|
||||
+ }
|
||||
+ else {
|
||||
+ sc->server->auth.cipher_suite = arg2;
|
||||
+ }
|
||||
+ return NULL;
|
||||
}
|
||||
-
|
||||
- return NULL;
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ else if (!strcmp("TLSv1.3", arg1)) {
|
||||
+ if (cmd->path) {
|
||||
+ return "TLSv1.3 ciphers cannot be set inside a directory context";
|
||||
+ }
|
||||
+ sc->server->auth.tls13_ciphers = arg2;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif
|
||||
+ return apr_pstrcat(cmd->pool, "procotol '", arg1, "' not supported", NULL);
|
||||
}
|
||||
|
||||
#define SSL_FLAGS_CHECK_FILE \
|
||||
@@ -1449,6 +1466,9 @@
|
||||
else if (strcEQ(w, "TLSv1.2")) {
|
||||
thisopt = SSL_PROTOCOL_TLSV1_2;
|
||||
}
|
||||
+ else if (SSL_HAVE_PROTOCOL_TLSV1_3 && strcEQ(w, "TLSv1.3")) {
|
||||
+ thisopt = SSL_PROTOCOL_TLSV1_3;
|
||||
+ }
|
||||
#endif
|
||||
else if (strcEQ(w, "all")) {
|
||||
thisopt = SSL_PROTOCOL_ALL;
|
||||
@@ -1510,16 +1530,28 @@
|
||||
|
||||
const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
|
||||
void *dcfg,
|
||||
- const char *arg)
|
||||
+ const char *arg1, const char *arg2)
|
||||
{
|
||||
SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
|
||||
-
|
||||
- /* always disable null and export ciphers */
|
||||
- arg = apr_pstrcat(cmd->pool, arg, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
-
|
||||
- dc->proxy->auth.cipher_suite = arg;
|
||||
-
|
||||
- return NULL;
|
||||
+
|
||||
+ if (arg2 == NULL) {
|
||||
+ arg2 = arg1;
|
||||
+ arg1 = "SSL";
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp("SSL", arg1)) {
|
||||
+ /* always disable null and export ciphers */
|
||||
+ arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
|
||||
+ dc->proxy->auth.cipher_suite = arg2;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ else if (!strcmp("TLSv1.3", arg1)) {
|
||||
+ dc->proxy->auth.tls13_ciphers = arg2;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif
|
||||
+ return apr_pstrcat(cmd->pool, "procotol '", arg1, "' not supported", NULL);
|
||||
}
|
||||
|
||||
const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd,
|
||||
--- httpd-2.4.34/modules/ssl/ssl_engine_init.c.r1827912+
|
||||
+++ httpd-2.4.34/modules/ssl/ssl_engine_init.c
|
||||
@@ -568,6 +568,9 @@
|
||||
#ifdef HAVE_TLSV1_X
|
||||
(protocol & SSL_PROTOCOL_TLSV1_1 ? "TLSv1.1, " : ""),
|
||||
(protocol & SSL_PROTOCOL_TLSV1_2 ? "TLSv1.2, " : ""),
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ (protocol & SSL_PROTOCOL_TLSV1_3 ? "TLSv1.3, " : ""),
|
||||
+#endif
|
||||
#endif
|
||||
NULL);
|
||||
cp[strlen(cp)-2] = NUL;
|
||||
@@ -600,6 +603,13 @@
|
||||
TLSv1_2_client_method() : /* proxy */
|
||||
TLSv1_2_server_method(); /* server */
|
||||
}
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ else if (protocol == SSL_PROTOCOL_TLSV1_3) {
|
||||
+ method = mctx->pkp ?
|
||||
+ TLSv1_3_client_method() : /* proxy */
|
||||
+ TLSv1_3_server_method(); /* server */
|
||||
+ }
|
||||
+#endif
|
||||
#endif
|
||||
else { /* For multiple protocols, we need a flexible method */
|
||||
method = mctx->pkp ?
|
||||
@@ -617,7 +627,8 @@
|
||||
|
||||
SSL_CTX_set_options(ctx, SSL_OP_ALL);
|
||||
|
||||
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
|
||||
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20800000L)
|
||||
/* always disable SSLv2, as per RFC 6176 */
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
||||
|
||||
@@ -639,10 +650,19 @@
|
||||
if (!(protocol & SSL_PROTOCOL_TLSV1_2)) {
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2);
|
||||
}
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ ssl_set_ctx_protocol_option(s, ctx, SSL_OP_NO_TLSv1_3,
|
||||
+ protocol & SSL_PROTOCOL_TLSV1_3, "TLSv1.3");
|
||||
+#endif
|
||||
#endif
|
||||
|
||||
#else /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
/* We first determine the maximum protocol version we should provide */
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ if (SSL_HAVE_PROTOCOL_TLSV1_3 && (protocol & SSL_PROTOCOL_TLSV1_3)) {
|
||||
+ prot = TLS1_3_VERSION;
|
||||
+ } else
|
||||
+#endif
|
||||
if (protocol & SSL_PROTOCOL_TLSV1_2) {
|
||||
prot = TLS1_2_VERSION;
|
||||
} else if (protocol & SSL_PROTOCOL_TLSV1_1) {
|
||||
@@ -664,6 +684,11 @@
|
||||
|
||||
/* Next we scan for the minimal protocol version we should provide,
|
||||
* but we do not allow holes between max and min */
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ if (prot == TLS1_3_VERSION && protocol & SSL_PROTOCOL_TLSV1_2) {
|
||||
+ prot = TLS1_2_VERSION;
|
||||
+ }
|
||||
+#endif
|
||||
if (prot == TLS1_2_VERSION && protocol & SSL_PROTOCOL_TLSV1_1) {
|
||||
prot = TLS1_1_VERSION;
|
||||
}
|
||||
@@ -736,6 +761,13 @@
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
|
||||
+ /* For OpenSSL >=1.1.1, disable auto-retry mode so it's possible
|
||||
+ * to consume handshake records without blocking for app-data.
|
||||
+ * https://github.com/openssl/openssl/issues/7178 */
|
||||
+ SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||
+#endif
|
||||
+
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -888,7 +920,15 @@
|
||||
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
return ssl_die(s);
|
||||
}
|
||||
-
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ if (mctx->auth.tls13_ciphers
|
||||
+ && !SSL_CTX_set_ciphersuites(ctx, mctx->auth.tls13_ciphers)) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO()
|
||||
+ "Unable to configure permitted TLSv1.3 ciphers");
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
|
||||
+ return ssl_die(s);
|
||||
+ }
|
||||
+#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1493,6 +1533,13 @@
|
||||
X509_STORE_CTX *sctx;
|
||||
X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx);
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
|
||||
+ /* For OpenSSL >=1.1.1, turn on client cert support which is
|
||||
+ * otherwise turned off by default (by design).
|
||||
+ * https://github.com/openssl/openssl/issues/6933 */
|
||||
+ SSL_CTX_set_post_handshake_auth(mctx->ssl_ctx, 1);
|
||||
+#endif
|
||||
+
|
||||
SSL_CTX_set_client_cert_cb(mctx->ssl_ctx,
|
||||
ssl_callback_proxy_cert);
|
||||
|
||||
--- httpd-2.4.34/modules/ssl/ssl_engine_kernel.c.r1827912+
|
||||
+++ httpd-2.4.34/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -188,6 +188,12 @@
|
||||
|| strcmp(a1->cipher_suite, a2->cipher_suite))) {
|
||||
return 0;
|
||||
}
|
||||
+ /* both have the same ca cipher suite string */
|
||||
+ if ((a1->tls13_ciphers != a2->tls13_ciphers)
|
||||
+ && (!a1->tls13_ciphers || !a2->tls13_ciphers
|
||||
+ || strcmp(a1->tls13_ciphers, a2->tls13_ciphers))) {
|
||||
+ return 0;
|
||||
+ }
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -424,87 +430,70 @@
|
||||
}
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Access Handler
|
||||
- */
|
||||
-int ssl_hook_Access(request_rec *r)
|
||||
+static int ssl_check_post_client_verify(request_rec *r, SSLSrvConfigRec *sc,
|
||||
+ SSLDirConfigRec *dc, SSLConnRec *sslconn,
|
||||
+ SSL *ssl)
|
||||
{
|
||||
- SSLDirConfigRec *dc = myDirConfig(r);
|
||||
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
- SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
- SSL *ssl = sslconn ? sslconn->ssl : NULL;
|
||||
- server_rec *handshakeserver = sslconn ? sslconn->server : NULL;
|
||||
- SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL;
|
||||
- SSL_CTX *ctx = NULL;
|
||||
- apr_array_header_t *requires;
|
||||
- ssl_require_t *ssl_requires;
|
||||
- int ok, i;
|
||||
- BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
|
||||
X509 *cert;
|
||||
- X509 *peercert;
|
||||
- X509_STORE *cert_store = NULL;
|
||||
- X509_STORE_CTX *cert_store_ctx;
|
||||
- STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
|
||||
- const SSL_CIPHER *cipher = NULL;
|
||||
- int depth, verify_old, verify, n, is_slave = 0;
|
||||
- const char *ncipher_suite;
|
||||
-
|
||||
- /* On a slave connection, we do not expect to have an SSLConnRec, but
|
||||
- * our master connection might have one. */
|
||||
- if (!(sslconn && ssl) && r->connection->master) {
|
||||
- sslconn = myConnConfig(r->connection->master);
|
||||
- ssl = sslconn ? sslconn->ssl : NULL;
|
||||
- handshakeserver = sslconn ? sslconn->server : NULL;
|
||||
- hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL;
|
||||
- is_slave = 1;
|
||||
- }
|
||||
|
||||
- if (ssl) {
|
||||
- /*
|
||||
- * We should have handshaken here (on handshakeserver),
|
||||
- * otherwise we are being redirected (ErrorDocument) from
|
||||
- * a renegotiation failure below. The access is still
|
||||
- * forbidden in the latter case, let ap_die() handle
|
||||
- * this recursive (same) error.
|
||||
- */
|
||||
- if (!SSL_is_init_finished(ssl)) {
|
||||
- return HTTP_FORBIDDEN;
|
||||
+ /*
|
||||
+ * Remember the peer certificate's DN
|
||||
+ */
|
||||
+ if ((cert = SSL_get_peer_certificate(ssl))) {
|
||||
+ if (sslconn->client_cert) {
|
||||
+ X509_free(sslconn->client_cert);
|
||||
}
|
||||
- ctx = SSL_get_SSL_CTX(ssl);
|
||||
+ sslconn->client_cert = cert;
|
||||
+ sslconn->client_dn = NULL;
|
||||
}
|
||||
-
|
||||
+
|
||||
/*
|
||||
- * Support for SSLRequireSSL directive
|
||||
+ * Finally check for acceptable renegotiation results
|
||||
*/
|
||||
- if (dc->bSSLRequired && !ssl) {
|
||||
- if ((sc->enabled == SSL_ENABLED_OPTIONAL) && !is_slave) {
|
||||
- /* This vhost was configured for optional SSL, just tell the
|
||||
- * client that we need to upgrade.
|
||||
- */
|
||||
- apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
|
||||
- apr_table_setn(r->err_headers_out, "Connection", "Upgrade");
|
||||
+ if ((dc->nVerifyClient != SSL_CVERIFY_NONE) ||
|
||||
+ (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) {
|
||||
+ BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
|
||||
+ (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE));
|
||||
+
|
||||
+ if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02262)
|
||||
+ "Re-negotiation handshake failed: "
|
||||
+ "Client verification failed");
|
||||
|
||||
- return HTTP_UPGRADE_REQUIRED;
|
||||
+ return HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02219)
|
||||
- "access to %s failed, reason: %s",
|
||||
- r->filename, "SSL connection required");
|
||||
-
|
||||
- /* remember forbidden access for strict require option */
|
||||
- apr_table_setn(r->notes, "ssl-access-forbidden", "1");
|
||||
+ if (do_verify) {
|
||||
+ if (cert == NULL) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02263)
|
||||
+ "Re-negotiation handshake failed: "
|
||||
+ "Client certificate missing");
|
||||
|
||||
- return HTTP_FORBIDDEN;
|
||||
+ return HTTP_FORBIDDEN;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ return OK;
|
||||
+}
|
||||
|
||||
- /*
|
||||
- * Check to see whether SSL is in use; if it's not, then no
|
||||
- * further access control checks are relevant. (the test for
|
||||
- * sc->enabled is probably strictly unnecessary)
|
||||
- */
|
||||
- if (sc->enabled == SSL_ENABLED_FALSE || !ssl) {
|
||||
- return DECLINED;
|
||||
- }
|
||||
+/*
|
||||
+ * Access Handler, classic flavour, for SSL/TLS up to v1.2
|
||||
+ * where everything can be renegotiated and no one is happy.
|
||||
+ */
|
||||
+static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirConfigRec *dc,
|
||||
+ SSLConnRec *sslconn, SSL *ssl)
|
||||
+{
|
||||
+ server_rec *handshakeserver = sslconn ? sslconn->server : NULL;
|
||||
+ SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL;
|
||||
+ SSL_CTX *ctx = NULL;
|
||||
+ BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
|
||||
+ X509 *peercert;
|
||||
+ X509_STORE *cert_store = NULL;
|
||||
+ X509_STORE_CTX *cert_store_ctx;
|
||||
+ STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
|
||||
+ const SSL_CIPHER *cipher = NULL;
|
||||
+ int depth, verify_old, verify, n, rc;
|
||||
+ const char *ncipher_suite;
|
||||
|
||||
#ifdef HAVE_SRP
|
||||
/*
|
||||
@@ -581,7 +570,7 @@
|
||||
}
|
||||
|
||||
/* configure new state */
|
||||
- if (is_slave) {
|
||||
+ if (r->connection->master) {
|
||||
/* TODO: this categorically fails changed cipher suite settings
|
||||
* on slave connections. We could do better by
|
||||
* - create a new SSL* from our SSL_CTX and set cipher suite there,
|
||||
@@ -659,7 +648,7 @@
|
||||
}
|
||||
|
||||
if (renegotiate) {
|
||||
- if (is_slave) {
|
||||
+ if (r->connection->master) {
|
||||
/* The request causes renegotiation on a slave connection.
|
||||
* This is not allowed since we might have concurrent requests
|
||||
* on this connection.
|
||||
@@ -732,7 +721,7 @@
|
||||
(verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))
|
||||
{
|
||||
renegotiate = TRUE;
|
||||
- if (is_slave) {
|
||||
+ if (r->connection->master) {
|
||||
/* The request causes renegotiation on a slave connection.
|
||||
* This is not allowed since we might have concurrent requests
|
||||
* on this connection.
|
||||
@@ -885,6 +874,7 @@
|
||||
|
||||
if (renegotiate_quick) {
|
||||
STACK_OF(X509) *cert_stack;
|
||||
+ X509 *cert;
|
||||
|
||||
/* perform just a manual re-verification of the peer */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258)
|
||||
@@ -1037,43 +1027,10 @@
|
||||
}
|
||||
|
||||
/*
|
||||
- * Remember the peer certificate's DN
|
||||
- */
|
||||
- if ((cert = SSL_get_peer_certificate(ssl))) {
|
||||
- if (sslconn->client_cert) {
|
||||
- X509_free(sslconn->client_cert);
|
||||
- }
|
||||
- sslconn->client_cert = cert;
|
||||
- sslconn->client_dn = NULL;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
* Finally check for acceptable renegotiation results
|
||||
*/
|
||||
- if ((dc->nVerifyClient != SSL_CVERIFY_NONE) ||
|
||||
- (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) {
|
||||
- BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
|
||||
- (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE));
|
||||
-
|
||||
- if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02262)
|
||||
- "Re-negotiation handshake failed: "
|
||||
- "Client verification failed");
|
||||
-
|
||||
- return HTTP_FORBIDDEN;
|
||||
- }
|
||||
-
|
||||
- if (do_verify) {
|
||||
- if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {
|
||||
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02263)
|
||||
- "Re-negotiation handshake failed: "
|
||||
- "Client certificate missing");
|
||||
-
|
||||
- return HTTP_FORBIDDEN;
|
||||
- }
|
||||
-
|
||||
- X509_free(peercert);
|
||||
- }
|
||||
+ if (OK != (rc = ssl_check_post_client_verify(r, sc, dc, sslconn, ssl))) {
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1096,6 +1053,215 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ return DECLINED;
|
||||
+}
|
||||
+
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+/*
|
||||
+ * Access Handler, modern flavour, for SSL/TLS v1.3 and onward.
|
||||
+ * Only client certificates can be requested, everything else stays.
|
||||
+ */
|
||||
+static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirConfigRec *dc,
|
||||
+ SSLConnRec *sslconn, SSL *ssl)
|
||||
+{
|
||||
+ if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) ||
|
||||
+ (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
|
||||
+ int vmode_inplace, vmode_needed;
|
||||
+ int change_vmode = FALSE;
|
||||
+ int old_state, n, rc;
|
||||
+
|
||||
+ vmode_inplace = SSL_get_verify_mode(ssl);
|
||||
+ vmode_needed = SSL_VERIFY_NONE;
|
||||
+
|
||||
+ if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
|
||||
+ (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) {
|
||||
+ vmode_needed |= SSL_VERIFY_PEER_STRICT;
|
||||
+ }
|
||||
+
|
||||
+ if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) ||
|
||||
+ (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) ||
|
||||
+ (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) ||
|
||||
+ (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
|
||||
+ {
|
||||
+ vmode_needed |= SSL_VERIFY_PEER;
|
||||
+ }
|
||||
+
|
||||
+ if (vmode_needed == SSL_VERIFY_NONE) {
|
||||
+ return DECLINED;
|
||||
+ }
|
||||
+
|
||||
+ vmode_needed |= SSL_VERIFY_CLIENT_ONCE;
|
||||
+ if (vmode_inplace != vmode_needed) {
|
||||
+ /* Need to change, if new setting is more restrictive than existing one */
|
||||
+
|
||||
+ if ((vmode_inplace == SSL_VERIFY_NONE)
|
||||
+ || (!(vmode_inplace & SSL_VERIFY_PEER)
|
||||
+ && (vmode_needed & SSL_VERIFY_PEER))
|
||||
+ || (!(vmode_inplace & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
|
||||
+ && (vmode_needed & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) {
|
||||
+ /* need to change the effective verify mode */
|
||||
+ change_vmode = TRUE;
|
||||
+ }
|
||||
+ else {
|
||||
+ /* FIXME: does this work with TLSv1.3? Is this more than re-inspecting
|
||||
+ * the certificate we should already have? */
|
||||
+ /*
|
||||
+ * override of SSLVerifyDepth
|
||||
+ *
|
||||
+ * The depth checks are handled by us manually inside the
|
||||
+ * verify callback function and not by OpenSSL internally
|
||||
+ * (and our function is aware of both the per-server and
|
||||
+ * per-directory contexts). So we cannot ask OpenSSL about
|
||||
+ * the currently verify depth. Instead we remember it in our
|
||||
+ * SSLConnRec attached to the SSL* of OpenSSL. We've to force
|
||||
+ * the renegotiation if the reconfigured/new verify depth is
|
||||
+ * less than the currently active/remembered verify depth
|
||||
+ * (because this means more restriction on the certificate
|
||||
+ * chain).
|
||||
+ */
|
||||
+ n = (sslconn->verify_depth != UNSET)?
|
||||
+ sslconn->verify_depth : sc->server->auth.verify_depth;
|
||||
+ /* determine the new depth */
|
||||
+ sslconn->verify_depth = (dc->nVerifyDepth != UNSET)
|
||||
+ ? dc->nVerifyDepth
|
||||
+ : sc->server->auth.verify_depth;
|
||||
+ if (sslconn->verify_depth < n) {
|
||||
+ change_vmode = TRUE;
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO()
|
||||
+ "Reduced client verification depth will "
|
||||
+ "force renegotiation");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (change_vmode) {
|
||||
+ char peekbuf[1];
|
||||
+
|
||||
+ if (r->connection->master) {
|
||||
+ /* FIXME: modifying the SSL on a slave connection is no good.
|
||||
+ * We would need to push this back to the master connection
|
||||
+ * somehow.
|
||||
+ */
|
||||
+ apr_table_setn(r->notes, "ssl-renegotiate-forbidden", "verify-client");
|
||||
+ return HTTP_FORBIDDEN;
|
||||
+ }
|
||||
+
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO() "verify client post handshake");
|
||||
+
|
||||
+ SSL_set_verify(ssl, vmode_needed, ssl_callback_SSLVerify);
|
||||
+
|
||||
+ if (SSL_verify_client_post_handshake(ssl) != 1) {
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10158)
|
||||
+ "cannot perform post-handshake authentication");
|
||||
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server);
|
||||
+ apr_table_setn(r->notes, "error-notes",
|
||||
+ "Reason: Cannot perform Post-Handshake Authentication.<br />");
|
||||
+ return HTTP_FORBIDDEN;
|
||||
+ }
|
||||
+
|
||||
+ old_state = sslconn->reneg_state;
|
||||
+ sslconn->reneg_state = RENEG_ALLOW;
|
||||
+ modssl_set_app_data2(ssl, r);
|
||||
+
|
||||
+ SSL_do_handshake(ssl);
|
||||
+ /* Need to trigger renegotiation handshake by reading.
|
||||
+ * Peeking 0 bytes actually works.
|
||||
+ * See: http://marc.info/?t=145493359200002&r=1&w=2
|
||||
+ */
|
||||
+ SSL_peek(ssl, peekbuf, 0);
|
||||
+
|
||||
+ sslconn->reneg_state = old_state;
|
||||
+ modssl_set_app_data2(ssl, NULL);
|
||||
+
|
||||
+ /*
|
||||
+ * Finally check for acceptable renegotiation results
|
||||
+ */
|
||||
+ if (OK != (rc = ssl_check_post_client_verify(r, sc, dc, sslconn, ssl))) {
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return DECLINED;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+int ssl_hook_Access(request_rec *r)
|
||||
+{
|
||||
+ SSLDirConfigRec *dc = myDirConfig(r);
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
+ SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
+ SSL *ssl = sslconn ? sslconn->ssl : NULL;
|
||||
+ apr_array_header_t *requires;
|
||||
+ ssl_require_t *ssl_requires;
|
||||
+ int ok, i, ret;
|
||||
+
|
||||
+ /* On a slave connection, we do not expect to have an SSLConnRec, but
|
||||
+ * our master connection might have one. */
|
||||
+ if (!(sslconn && ssl) && r->connection->master) {
|
||||
+ sslconn = myConnConfig(r->connection->master);
|
||||
+ ssl = sslconn ? sslconn->ssl : NULL;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * We should have handshaken here, otherwise we are being
|
||||
+ * redirected (ErrorDocument) from a renegotiation failure below.
|
||||
+ * The access is still forbidden in the latter case, let ap_die() handle
|
||||
+ * this recursive (same) error.
|
||||
+ */
|
||||
+ if (ssl && !SSL_is_init_finished(ssl)) {
|
||||
+ return HTTP_FORBIDDEN;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Support for SSLRequireSSL directive
|
||||
+ */
|
||||
+ if (dc->bSSLRequired && !ssl) {
|
||||
+ if ((sc->enabled == SSL_ENABLED_OPTIONAL) && !r->connection->master) {
|
||||
+ /* This vhost was configured for optional SSL, just tell the
|
||||
+ * client that we need to upgrade.
|
||||
+ */
|
||||
+ apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
|
||||
+ apr_table_setn(r->err_headers_out, "Connection", "Upgrade");
|
||||
+
|
||||
+ return HTTP_UPGRADE_REQUIRED;
|
||||
+ }
|
||||
+
|
||||
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02219)
|
||||
+ "access to %s failed, reason: %s",
|
||||
+ r->filename, "SSL connection required");
|
||||
+
|
||||
+ /* remember forbidden access for strict require option */
|
||||
+ apr_table_setn(r->notes, "ssl-access-forbidden", "1");
|
||||
+
|
||||
+ return HTTP_FORBIDDEN;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Check to see whether SSL is in use; if it's not, then no
|
||||
+ * further access control checks are relevant. (the test for
|
||||
+ * sc->enabled is probably strictly unnecessary)
|
||||
+ */
|
||||
+ if (sc->enabled == SSL_ENABLED_FALSE || !ssl) {
|
||||
+ return DECLINED;
|
||||
+ }
|
||||
+
|
||||
+#if SSL_HAVE_PROTOCOL_TLSV1_3
|
||||
+ /* TLSv1.3+ is less complicated here. Branch off into a new codeline
|
||||
+ * and avoid messing with the past. */
|
||||
+ if (SSL_version(ssl) >= TLS1_3_VERSION) {
|
||||
+ ret = ssl_hook_Access_modern(r, sc, dc, sslconn, ssl);
|
||||
+ }
|
||||
+ else
|
||||
+#endif
|
||||
+ {
|
||||
+ ret = ssl_hook_Access_classic(r, sc, dc, sslconn, ssl);
|
||||
+ }
|
||||
+
|
||||
+ if (ret != DECLINED) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
/* If we're trying to have the user name set from a client
|
||||
* certificate then we need to set it here. This should be safe as
|
||||
* the user name probably isn't important from an auth checking point
|
||||
@@ -2080,31 +2246,43 @@
|
||||
{
|
||||
conn_rec *c;
|
||||
server_rec *s;
|
||||
- SSLConnRec *scr;
|
||||
|
||||
/* Retrieve the conn_rec and the associated SSLConnRec. */
|
||||
if ((c = (conn_rec *)SSL_get_app_data((SSL *)ssl)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
- if ((scr = myConnConfig(c)) == NULL) {
|
||||
- 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
|
||||
+ {
|
||||
+ SSLConnRec *sslconn;
|
||||
+
|
||||
+ if ((sslconn = myConnConfig(c)) == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- /* If the reneg state is to reject renegotiations, check the SSL
|
||||
- * state machine and move to ABORT if a Client Hello is being
|
||||
- * read. */
|
||||
- if (!scr->is_proxy &&
|
||||
- (where & SSL_CB_HANDSHAKE_START) &&
|
||||
- scr->reneg_state == RENEG_REJECT) {
|
||||
- scr->reneg_state = RENEG_ABORT;
|
||||
+ /* If the reneg state is to reject renegotiations, check the SSL
|
||||
+ * state machine and move to ABORT if a Client Hello is being
|
||||
+ * read. */
|
||||
+ if (!sslconn->is_proxy &&
|
||||
+ (where & SSL_CB_HANDSHAKE_START) &&
|
||||
+ sslconn->reneg_state == RENEG_REJECT) {
|
||||
+ sslconn->reneg_state = RENEG_ABORT;
|
||||
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02042)
|
||||
"rejecting client initiated renegotiation");
|
||||
- }
|
||||
- /* If the first handshake is complete, change state to reject any
|
||||
- * subsequent client-initiated renegotiation. */
|
||||
- else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
|
||||
- scr->reneg_state = RENEG_REJECT;
|
||||
+ }
|
||||
+ /* If the first handshake is complete, change state to reject any
|
||||
+ * subsequent client-initiated renegotiation. */
|
||||
+ else if ((where & SSL_CB_HANDSHAKE_DONE)
|
||||
+ && sslconn->reneg_state == RENEG_INIT) {
|
||||
+ sslconn->reneg_state = RENEG_REJECT;
|
||||
+ }
|
||||
}
|
||||
|
||||
s = mySrvFromConn(c);
|
||||
--- httpd-2.4.34/modules/ssl/ssl_private.h.r1827912+
|
||||
+++ httpd-2.4.34/modules/ssl/ssl_private.h
|
||||
@@ -132,13 +132,14 @@
|
||||
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
|
||||
#define SSL_CTX_set_max_proto_version(ctx, version) \
|
||||
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
|
||||
-#endif
|
||||
-/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most
|
||||
- * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so
|
||||
- * we have to work around this...
|
||||
+#elif LIBRESSL_VERSION_NUMBER < 0x2070000f
|
||||
+/* LibreSSL before 2.7 declares OPENSSL_VERSION_NUMBER == 2.0 but does not
|
||||
+ * include most changes from OpenSSL >= 1.1 (new functions, macros,
|
||||
+ * deprecations, ...), so we have to work around this...
|
||||
*/
|
||||
#define MODSSL_USE_OPENSSL_PRE_1_1_API (1)
|
||||
-#else
|
||||
+#endif /* LIBRESSL_VERSION_NUMBER < 0x2060000f */
|
||||
+#else /* defined(LIBRESSL_VERSION_NUMBER) */
|
||||
#define MODSSL_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
#endif
|
||||
|
||||
@@ -238,7 +239,8 @@
|
||||
void free_bio_methods(void);
|
||||
#endif
|
||||
|
||||
-#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
+#if OPENSSL_VERSION_NUMBER < 0x10002000L || \
|
||||
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000f)
|
||||
#define X509_STORE_CTX_get0_store(x) (x->ctx)
|
||||
#endif
|
||||
|
||||
@@ -372,8 +374,17 @@
|
||||
#ifdef HAVE_TLSV1_X
|
||||
#define SSL_PROTOCOL_TLSV1_1 (1<<3)
|
||||
#define SSL_PROTOCOL_TLSV1_2 (1<<4)
|
||||
+#define SSL_PROTOCOL_TLSV1_3 (1<<5)
|
||||
+
|
||||
+#ifdef SSL_OP_NO_TLSv1_3
|
||||
+#define SSL_HAVE_PROTOCOL_TLSV1_3 (1)
|
||||
+#define SSL_PROTOCOL_ALL (SSL_PROTOCOL_BASIC| \
|
||||
+ SSL_PROTOCOL_TLSV1_1|SSL_PROTOCOL_TLSV1_2|SSL_PROTOCOL_TLSV1_3)
|
||||
+#else
|
||||
+#define SSL_HAVE_PROTOCOL_TLSV1_3 (0)
|
||||
#define SSL_PROTOCOL_ALL (SSL_PROTOCOL_BASIC| \
|
||||
SSL_PROTOCOL_TLSV1_1|SSL_PROTOCOL_TLSV1_2)
|
||||
+#endif
|
||||
#else
|
||||
#define SSL_PROTOCOL_ALL (SSL_PROTOCOL_BASIC)
|
||||
#endif
|
||||
@@ -646,6 +657,11 @@
|
||||
/** for client or downstream server authentication */
|
||||
int verify_depth;
|
||||
ssl_verify_t verify_mode;
|
||||
+
|
||||
+ /** TLSv1.3 has its separate cipher list, separate from the
|
||||
+ settings for older TLS protocol versions. Since which one takes
|
||||
+ effect is a matter of negotiation, we need separate settings */
|
||||
+ const char *tls13_ciphers;
|
||||
} modssl_auth_ctx_t;
|
||||
|
||||
#ifdef HAVE_TLS_SESSION_TICKETS
|
||||
@@ -801,7 +817,7 @@
|
||||
const char *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
|
||||
const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *);
|
||||
-const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
|
||||
+const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *, const char *);
|
||||
const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *);
|
||||
@@ -830,7 +846,7 @@
|
||||
|
||||
const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
|
||||
const char *ssl_cmd_SSLProxyProtocol(cmd_parms *, void *, const char *);
|
||||
-const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *, void *, const char *);
|
||||
+const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *, void *, const char *, const char *);
|
||||
const char *ssl_cmd_SSLProxyVerify(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *, void *, const char *);
|
||||
const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *, void *, const char *);
|
||||
Binary file not shown.
@ -1,250 +0,0 @@
|
||||
# ./pullrev.sh 1337344 1341905 1342065 1341930
|
||||
|
||||
suexec enhancements:
|
||||
|
||||
1) use syslog for logging
|
||||
2) use capabilities not setuid/setgid root binary
|
||||
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1337344
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1341905
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1342065
|
||||
http://svn.apache.org/viewvc?view=revision&revision=1341930
|
||||
|
||||
--- httpd-2.4.4/configure.in.r1337344+
|
||||
+++ httpd-2.4.4/configure.in
|
||||
@@ -734,7 +734,24 @@ APACHE_HELP_STRING(--with-suexec-gidmin,
|
||||
|
||||
AC_ARG_WITH(suexec-logfile,
|
||||
APACHE_HELP_STRING(--with-suexec-logfile,Set the logfile),[
|
||||
- AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file] ) ] )
|
||||
+ if test "x$withval" = "xyes"; then
|
||||
+ AC_DEFINE_UNQUOTED(AP_LOG_EXEC, "$withval", [SuExec log file])
|
||||
+ fi
|
||||
+])
|
||||
+
|
||||
+AC_ARG_WITH(suexec-syslog,
|
||||
+APACHE_HELP_STRING(--with-suexec-syslog,Set the logfile),[
|
||||
+ if test $withval = "yes"; then
|
||||
+ if test "x${with_suexec_logfile}" != "xno"; then
|
||||
+ AC_MSG_NOTICE([hint: use "--without-suexec-logfile --with-suexec-syslog"])
|
||||
+ AC_MSG_ERROR([suexec does not support both logging to file and syslog])
|
||||
+ fi
|
||||
+ AC_CHECK_FUNCS([vsyslog], [], [
|
||||
+ AC_MSG_ERROR([cannot support syslog from suexec without vsyslog()])])
|
||||
+ AC_DEFINE(AP_LOG_SYSLOG, 1, [SuExec log to syslog])
|
||||
+ fi
|
||||
+])
|
||||
+
|
||||
|
||||
AC_ARG_WITH(suexec-safepath,
|
||||
APACHE_HELP_STRING(--with-suexec-safepath,Set the safepath),[
|
||||
@@ -744,6 +761,15 @@ AC_ARG_WITH(suexec-umask,
|
||||
APACHE_HELP_STRING(--with-suexec-umask,umask for suexec'd process),[
|
||||
AC_DEFINE_UNQUOTED(AP_SUEXEC_UMASK, 0$withval, [umask for suexec'd process] ) ] )
|
||||
|
||||
+INSTALL_SUEXEC=setuid
|
||||
+AC_ARG_ENABLE([suexec-capabilities],
|
||||
+APACHE_HELP_STRING(--enable-suexec-capabilities,Use Linux capability bits not setuid root suexec), [
|
||||
+INSTALL_SUEXEC=caps
|
||||
+AC_DEFINE(AP_SUEXEC_CAPABILITIES, 1,
|
||||
+ [Enable if suexec is installed with Linux capabilities, not setuid])
|
||||
+])
|
||||
+APACHE_SUBST(INSTALL_SUEXEC)
|
||||
+
|
||||
dnl APR should go after the other libs, so the right symbols can be picked up
|
||||
if test x${apu_found} != xobsolete; then
|
||||
AP_LIBS="$AP_LIBS `$apu_config --avoid-ldap --link-libtool`"
|
||||
--- httpd-2.4.4/docs/manual/suexec.html.en.r1337344+
|
||||
+++ httpd-2.4.4/docs/manual/suexec.html.en
|
||||
@@ -372,6 +372,21 @@
|
||||
together with the <code>--enable-suexec</code> option to let
|
||||
APACI accept your request for using the suEXEC feature.</dd>
|
||||
|
||||
+ <dt><code>--enable-suexec-capabilities</code></dt>
|
||||
+
|
||||
+ <dd><strong>Linux specific:</strong> Normally,
|
||||
+ the <code>suexec</code> binary is installed "setuid/setgid
|
||||
+ root", which allows it to run with the full privileges of the
|
||||
+ root user. If this option is used, the <code>suexec</code>
|
||||
+ binary will instead be installed with only the setuid/setgid
|
||||
+ "capability" bits set, which is the subset of full root
|
||||
+ priviliges required for suexec operation. Note that
|
||||
+ the <code>suexec</code> binary may not be able to write to a log
|
||||
+ file in this mode; it is recommended that the
|
||||
+ <code>--with-suexec-syslog --without-suexec-logfile</code>
|
||||
+ options are used in conjunction with this mode, so that syslog
|
||||
+ logging is used instead.</dd>
|
||||
+
|
||||
<dt><code>--with-suexec-bin=<em>PATH</em></code></dt>
|
||||
|
||||
<dd>The path to the <code>suexec</code> binary must be hard-coded
|
||||
@@ -433,6 +448,12 @@
|
||||
"<code>suexec_log</code>" and located in your standard logfile
|
||||
directory (<code>--logfiledir</code>).</dd>
|
||||
|
||||
+ <dt><code>--with-suexec-syslog</code></dt>
|
||||
+
|
||||
+ <dd>If defined, suexec will log notices and errors to syslog
|
||||
+ instead of a logfile. This option must be combined
|
||||
+ with <code>--without-suexec-logfile</code>.</dd>
|
||||
+
|
||||
<dt><code>--with-suexec-safepath=<em>PATH</em></code></dt>
|
||||
|
||||
<dd>Define a safe PATH environment to pass to CGI
|
||||
@@ -550,9 +571,12 @@ Group webgroup
|
||||
|
||||
<p>The suEXEC wrapper will write log information
|
||||
to the file defined with the <code>--with-suexec-logfile</code>
|
||||
- option as indicated above. If you feel you have configured and
|
||||
- installed the wrapper properly, have a look at this log and the
|
||||
- error_log for the server to see where you may have gone astray.</p>
|
||||
+ option as indicated above, or to syslog if <code>--with-suexec-syslog</code>
|
||||
+ is used. If you feel you have configured and
|
||||
+ installed the wrapper properly, have a look at the log and the
|
||||
+ error_log for the server to see where you may have gone astray.
|
||||
+ The output of <code>"suexec -V"</code> will show the options
|
||||
+ used to compile suexec, if using a binary distribution.</p>
|
||||
|
||||
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
|
||||
<div class="section">
|
||||
@@ -640,4 +664,4 @@ if (typeof(prettyPrint) !== 'undefined')
|
||||
prettyPrint();
|
||||
}
|
||||
//--><!]]></script>
|
||||
-</body></html>
|
||||
\ No newline at end of file
|
||||
+</body></html>
|
||||
--- httpd-2.4.4/Makefile.in.r1337344+
|
||||
+++ httpd-2.4.4/Makefile.in
|
||||
@@ -238,11 +238,22 @@ install-man:
|
||||
cd $(DESTDIR)$(manualdir) && find . -name ".svn" -type d -print | xargs rm -rf 2>/dev/null || true; \
|
||||
fi
|
||||
|
||||
-install-suexec:
|
||||
+install-suexec: install-suexec-binary install-suexec-$(INSTALL_SUEXEC)
|
||||
+
|
||||
+install-suexec-binary:
|
||||
@if test -f $(builddir)/support/suexec; then \
|
||||
test -d $(DESTDIR)$(sbindir) || $(MKINSTALLDIRS) $(DESTDIR)$(sbindir); \
|
||||
$(INSTALL_PROGRAM) $(top_builddir)/support/suexec $(DESTDIR)$(sbindir); \
|
||||
- chmod 4755 $(DESTDIR)$(sbindir)/suexec; \
|
||||
+ fi
|
||||
+
|
||||
+install-suexec-setuid:
|
||||
+ @if test -f $(builddir)/support/suexec; then \
|
||||
+ chmod 4755 $(DESTDIR)$(sbindir)/suexec; \
|
||||
+ fi
|
||||
+
|
||||
+install-suexec-caps:
|
||||
+ @if test -f $(builddir)/support/suexec; then \
|
||||
+ setcap 'cap_setuid,cap_setgid+pe' $(DESTDIR)$(sbindir)/suexec; \
|
||||
fi
|
||||
|
||||
suexec:
|
||||
--- httpd-2.4.4/modules/arch/unix/mod_unixd.c.r1337344+
|
||||
+++ httpd-2.4.4/modules/arch/unix/mod_unixd.c
|
||||
@@ -284,6 +284,13 @@ unixd_set_suexec(cmd_parms *cmd, void *d
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+#ifdef AP_SUEXEC_CAPABILITIES
|
||||
+/* If suexec is using capabilities, don't test for the setuid bit. */
|
||||
+#define SETUID_TEST(finfo) (1)
|
||||
+#else
|
||||
+#define SETUID_TEST(finfo) (finfo.protection & APR_USETID)
|
||||
+#endif
|
||||
+
|
||||
static int
|
||||
unixd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
apr_pool_t *ptemp)
|
||||
@@ -300,7 +307,7 @@ unixd_pre_config(apr_pool_t *pconf, apr_
|
||||
ap_unixd_config.suexec_enabled = 0;
|
||||
if ((apr_stat(&wrapper, SUEXEC_BIN, APR_FINFO_NORM, ptemp))
|
||||
== APR_SUCCESS) {
|
||||
- if ((wrapper.protection & APR_USETID) && wrapper.user == 0
|
||||
+ if (SETUID_TEST(wrapper) && wrapper.user == 0
|
||||
&& (access(SUEXEC_BIN, R_OK|X_OK) == 0)) {
|
||||
ap_unixd_config.suexec_enabled = 1;
|
||||
ap_unixd_config.suexec_disabled_reason = "";
|
||||
--- httpd-2.4.4/support/suexec.c.r1337344+
|
||||
+++ httpd-2.4.4/support/suexec.c
|
||||
@@ -58,6 +58,10 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
+#ifdef AP_LOG_SYSLOG
|
||||
+#include <syslog.h>
|
||||
+#endif
|
||||
+
|
||||
#if defined(PATH_MAX)
|
||||
#define AP_MAXPATH PATH_MAX
|
||||
#elif defined(MAXPATHLEN)
|
||||
@@ -69,7 +73,20 @@
|
||||
#define AP_ENVBUF 256
|
||||
|
||||
extern char **environ;
|
||||
+
|
||||
+#ifdef AP_LOG_SYSLOG
|
||||
+/* Syslog support. */
|
||||
+#if !defined(AP_LOG_FACILITY) && defined(LOG_AUTHPRIV)
|
||||
+#define AP_LOG_FACILITY LOG_AUTHPRIV
|
||||
+#elif !defined(AP_LOG_FACILITY)
|
||||
+#define AP_LOG_FACILITY LOG_AUTH
|
||||
+#endif
|
||||
+
|
||||
+static int log_open;
|
||||
+#else
|
||||
+/* Non-syslog support. */
|
||||
static FILE *log = NULL;
|
||||
+#endif
|
||||
|
||||
static const char *const safe_env_lst[] =
|
||||
{
|
||||
@@ -137,7 +154,14 @@ static void err_output(int is_error, con
|
||||
|
||||
static void err_output(int is_error, const char *fmt, va_list ap)
|
||||
{
|
||||
-#ifdef AP_LOG_EXEC
|
||||
+#if defined(AP_LOG_SYSLOG)
|
||||
+ if (!log_open) {
|
||||
+ openlog("suexec", LOG_PID, AP_LOG_FACILITY);
|
||||
+ log_open = 1;
|
||||
+ }
|
||||
+
|
||||
+ vsyslog(is_error ? LOG_ERR : LOG_INFO, fmt, ap);
|
||||
+#elif defined(AP_LOG_EXEC)
|
||||
time_t timevar;
|
||||
struct tm *lt;
|
||||
|
||||
@@ -295,7 +319,9 @@ int main(int argc, char *argv[])
|
||||
#ifdef AP_HTTPD_USER
|
||||
fprintf(stderr, " -D AP_HTTPD_USER=\"%s\"\n", AP_HTTPD_USER);
|
||||
#endif
|
||||
-#ifdef AP_LOG_EXEC
|
||||
+#if defined(AP_LOG_SYSLOG)
|
||||
+ fprintf(stderr, " -D AP_LOG_SYSLOG\n");
|
||||
+#elif defined(AP_LOG_EXEC)
|
||||
fprintf(stderr, " -D AP_LOG_EXEC=\"%s\"\n", AP_LOG_EXEC);
|
||||
#endif
|
||||
#ifdef AP_SAFE_PATH
|
||||
@@ -591,6 +617,12 @@ int main(int argc, char *argv[])
|
||||
#endif /* AP_SUEXEC_UMASK */
|
||||
|
||||
/* Be sure to close the log file so the CGI can't mess with it. */
|
||||
+#ifdef AP_LOG_SYSLOG
|
||||
+ if (log_open) {
|
||||
+ closelog();
|
||||
+ log_open = 0;
|
||||
+ }
|
||||
+#else
|
||||
if (log != NULL) {
|
||||
#if APR_HAVE_FCNTL_H
|
||||
/*
|
||||
@@ -612,6 +644,7 @@ int main(int argc, char *argv[])
|
||||
log = NULL;
|
||||
#endif
|
||||
}
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Execute the command, replacing our image with its own.
|
||||
BIN
httpd-2.4.43.tar.bz2
Normal file
BIN
httpd-2.4.43.tar.bz2
Normal file
Binary file not shown.
@ -19,8 +19,8 @@ index ad1287f..efcfcf6 100644
|
||||
+
|
||||
+my $installbuilddir = $libdir . "/httpd/build";
|
||||
+
|
||||
get_config_vars("$installbuilddir/config_vars.mk",\%config_vars);
|
||||
|
||||
get_config_vars($destdir . "$installbuilddir/config_vars.mk",\%config_vars);
|
||||
|
||||
# read the configuration variables once
|
||||
@@ -275,7 +286,7 @@ if ($opt_g) {
|
||||
$data =~ s|%NAME%|$name|sg;
|
||||
|
||||
60
httpd.spec
60
httpd.spec
@ -7,8 +7,8 @@
|
||||
|
||||
Name: httpd
|
||||
Summary: Apache HTTP Server
|
||||
Version: 2.4.34
|
||||
Release: 17
|
||||
Version: 2.4.43
|
||||
Release: 1
|
||||
License: ASL 2.0
|
||||
URL: https://httpd.apache.org/
|
||||
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
|
||||
@ -55,64 +55,16 @@ Patch0002: httpd-2.4.9-apxs.patch
|
||||
Patch0003: httpd-2.4.1-deplibs.patch
|
||||
Patch0006: httpd-2.4.3-apctl-systemd.patch
|
||||
Patch0019: httpd-2.4.25-detect-systemd.patch
|
||||
Patch0021: httpd-2.4.33-mddefault.patch
|
||||
Patch0023: httpd-2.4.33-export.patch
|
||||
Patch0024: httpd-2.4.1-corelimit.patch
|
||||
Patch0025: httpd-2.4.25-selinux.patch
|
||||
Patch0027: httpd-2.4.2-icons.patch
|
||||
Patch0029: httpd-2.4.33-systemd.patch
|
||||
Patch0030: httpd-2.4.4-cachehardmax.patch
|
||||
Patch0034: httpd-2.4.17-socket-activation.patch
|
||||
Patch0036: httpd-2.4.33-r1830819+.patch
|
||||
Patch0037: httpd-2.4.34-r1827912+.patch
|
||||
Patch0038: httpd-2.4.34-sslciphdefault.patch
|
||||
Patch0039: httpd-2.4.34-sslprotdefault.patch
|
||||
Patch0058: httpd-2.4.34-r1738878.patch
|
||||
Patch0059: httpd-2.4.34-r1555631.patch
|
||||
Patch0060: httpd-2.4.34-enable-sslv3.patch
|
||||
|
||||
Patch6000: CVE-2018-11763.patch
|
||||
Patch6001: On-the-2.4.x-branch.patch
|
||||
Patch6002: Merge-r1418761-r1418765-r1510295-r1757147-r1805163-r.patch
|
||||
Patch6003: Merge-r1837130-from-trunk.patch
|
||||
Patch6004: mod_proxy_hcheck-Fix-issues-with-TCP-health-checks.-.patch
|
||||
Patch6005: mod_proxy_hcheck-Fix-issues-with-interval-determinat.patch
|
||||
Patch6006: MPMs-Initialize-all-runtime-asynchronous-objects-on-.patch
|
||||
Patch6007: Merge-r1842540-from-trunk.patch
|
||||
Patch6008: mod_ssl-We-need-to-get-the-SSL_CTX-for-further-proce.patch
|
||||
Patch6009: Merge-r1837250-from-trunk.patch
|
||||
Patch6010: mod_ssl-Fixes-PR-62880-where-certificate-loading-fai.patch
|
||||
Patch6011: mod_ssl-Fixes-PR-62654-where-require-ssl-did-not-wor.patch
|
||||
Patch6012: Merge-r1831773-from-trunk.patch
|
||||
Patch6013: mod_negotiation-LanguagePriority-tags-must-be-treate.patch
|
||||
Patch6014: mod_ssl-ssl_engine_io.c-bio_filter_out_write-bio_fil.patch
|
||||
Patch6015: Merge-of-r1853133-r1853166-from-trunk.patch
|
||||
Patch6016: Merge-r1851093-from-trunk1.patch
|
||||
Patch6017: Merge-r1851093-from-trunk2.patch
|
||||
Patch6018: Merge-r1853190-from-trunk.patch
|
||||
Patch6019: Merge-r1855646-r1855748-from-trunk.patch
|
||||
Patch6020: CVE-2019-0211.patch
|
||||
Patch6021: CVE-2019-0215.patch
|
||||
Patch6022: CVE-2018-17189.patch
|
||||
Patch6023: CVE-2019-0220-1.patch
|
||||
Patch6024: CVE-2019-0220-2.patch
|
||||
Patch6025: CVE-2019-0220-3.patch
|
||||
Patch6026: CVE-2018-17199.patch
|
||||
Patch6027: CVE-2019-10092-1.patch
|
||||
Patch6028: CVE-2019-10092-2.patch
|
||||
Patch6029: CVE-2019-10098.patch
|
||||
Patch6030: CVE-2019-0196.patch
|
||||
Patch6031: CVE-2019-0197.patch
|
||||
Patch6032: CVE-2019-10097.patch
|
||||
Patch6033: CVE-2019-9517_CVE-2019-10081_CVE-2019-10082-1.patch
|
||||
Patch6034: CVE-2019-9517_CVE-2019-10081_CVE-2019-10082-2.patch
|
||||
Patch6035: CVE-2019-9517_CVE-2019-10081_CVE-2019-10082-3.patch
|
||||
Patch6036: CVE-2019-9517_CVE-2019-10081_CVE-2019-10082-4.patch
|
||||
Patch6037: CVE-2019-9517_CVE-2019-10081_CVE-2019-10082-5.patch
|
||||
Patch6038: CVE-2020-1927-1.patch
|
||||
Patch6039: CVE-2020-1927-2.patch
|
||||
Patch6040: CVE-2020-1934.patch
|
||||
|
||||
Patch9000: layout_add_openEuler.patch
|
||||
|
||||
BuildRequires: gcc autoconf pkgconfig findutils xmlto perl-interpreter perl-generators systemd-devel
|
||||
@ -255,7 +207,7 @@ export LYNX_PATH=/usr/bin/links
|
||||
--enable-mods-shared=all --enable-ssl --with-ssl --disable-distcache \
|
||||
--enable-proxy --enable-proxy-fdpass --enable-cache --enable-disk-cache \
|
||||
--enable-ldap --enable-authnz-ldap --enable-cgid --enable-cgi \
|
||||
--enable-authn-anon --enable-authn-alias \
|
||||
--enable-authn-anon --enable-authn-alias --enable-systemd \
|
||||
--disable-imagemap --disable-file-cache --disable-http2 $*
|
||||
|
||||
%make_build
|
||||
@ -550,6 +502,12 @@ exit $rv
|
||||
%{_rpmconfigdir}/macros.d/macros.httpd
|
||||
|
||||
%changelog
|
||||
* Fri Jul 24 2020 zhujunhao <zhujunhao8@huawei.com> - 2.4.43-1
|
||||
- Type:NA
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:Update to 2.4.43
|
||||
|
||||
* Thu Apr 23 2020 openEuler Buildteam <buildteam@openeuler.org> - 2.4.34-17
|
||||
- Type:cves
|
||||
- ID:CVE-2019-9517 CVE-2019-10081 CVE-2019-10082 CVE-2020-1927 CVE-2020-1934
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From f68b1efc6b4fb2c072d95e1ea6c74c98ff85b2b2 Mon Sep 17 00:00:00 2001
|
||||
From: "William A. Rowe Jr" <wrowe@apache.org>
|
||||
Date: Wed, 16 Jan 2019 16:37:41 +0000
|
||||
Subject: [PATCH 329/504] mod_negotiation: LanguagePriority tags must be
|
||||
treated case-insensitive, per
|
||||
https://tools.ietf.org/html/rfc7231#section-3.1.3.1
|
||||
|
||||
PR: 39730
|
||||
Backports: r1850989
|
||||
Submitted by: jailletc36
|
||||
Reviewed by: jailletc36, wrowe, jim
|
||||
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1851468 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
STATUS | 6 ------
|
||||
modules/mappers/mod_negotiation.c | 2 +-
|
||||
3 files changed, 4 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c
|
||||
index 3f04d83ddf..b6dfedc6c0 100644
|
||||
--- a/modules/mappers/mod_negotiation.c
|
||||
+++ b/modules/mappers/mod_negotiation.c
|
||||
@@ -1459,7 +1459,7 @@ static int find_lang_index(apr_array_header_t *accept_langs, char *lang)
|
||||
alang = (const char **) accept_langs->elts;
|
||||
|
||||
for (i = 0; i < accept_langs->nelts; ++i) {
|
||||
- if (!strncmp(lang, *alang, strlen(*alang))) {
|
||||
+ if (!ap_cstr_casecmpn(lang, *alang, strlen(*alang))) {
|
||||
return i;
|
||||
}
|
||||
alang += (accept_langs->elt_size / sizeof(char*));
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 5a17d3abd84c82bbc47e16a552ef6325a88af36c Mon Sep 17 00:00:00 2001
|
||||
From: Graham Leggett <minfrin@apache.org>
|
||||
Date: Tue, 18 Sep 2018 21:24:06 +0000
|
||||
Subject: [PATCH 168/504] mod_proxy_hcheck: Fix issues with TCP health checks.
|
||||
PR 61499 trunk patch: http://svn.apache.org/r1840582 2.4.x patch: svn merge
|
||||
-c 1840582 ^/httpd/httpd/trunk . +1: jim, ylavic, minfrin
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1841263 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
STATUS | 4 ----
|
||||
modules/proxy/mod_proxy_hcheck.c | 1 -
|
||||
3 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c
|
||||
index 0ee6845265..bf557b71e9 100644
|
||||
--- a/modules/proxy/mod_proxy_hcheck.c
|
||||
+++ b/modules/proxy/mod_proxy_hcheck.c
|
||||
@@ -612,7 +612,6 @@ static apr_status_t hc_check_tcp(baton_t *baton)
|
||||
|
||||
status = hc_get_backend("HCTCP", &backend, hc, ctx, baton->ptemp);
|
||||
if (status == OK) {
|
||||
- backend->addr = hc->cp->addr;
|
||||
status = ap_proxy_connect_backend("HCTCP", backend, hc, ctx->s);
|
||||
/* does an unconditional ap_proxy_is_socket_connected() */
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From 27f60f11f6c3d048e42692476d949e35a90b863f Mon Sep 17 00:00:00 2001
|
||||
From: Graham Leggett <minfrin@apache.org>
|
||||
Date: Tue, 18 Sep 2018 21:45:59 +0000
|
||||
Subject: [PATCH 171/504] mod_proxy_hcheck: Fix issues with interval
|
||||
determination. PR 62318 trunk patch: http://svn.apache.org/r1838937 2.4.x
|
||||
patch: svn merge -c 1838937 ^/httpd/httpd/trunk . +1: jim, ylavic, minfrin
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1841266 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
STATUS | 5 -----
|
||||
modules/proxy/mod_proxy_hcheck.c | 2 +-
|
||||
3 files changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c
|
||||
index bf557b71e9..2783a58e78 100644
|
||||
--- a/modules/proxy/mod_proxy_hcheck.c
|
||||
+++ b/modules/proxy/mod_proxy_hcheck.c
|
||||
@@ -830,6 +830,7 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
|
||||
"%sHealth checking %s", (thread ? "Threaded " : ""),
|
||||
worker->s->name);
|
||||
|
||||
+ worker->s->updated = now;
|
||||
if (hc->s->method == TCP) {
|
||||
rv = hc_check_tcp(baton);
|
||||
}
|
||||
@@ -870,7 +871,6 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
|
||||
}
|
||||
}
|
||||
}
|
||||
- worker->s->updated = now;
|
||||
apr_pool_destroy(baton->ptemp);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,175 +0,0 @@
|
||||
From 13a0cba7b804a173499758bb696d67fac371205c Mon Sep 17 00:00:00 2001
|
||||
From: Graham Leggett <minfrin@apache.org>
|
||||
Date: Fri, 23 Nov 2018 15:10:24 +0000
|
||||
Subject: [PATCH 276/504] *) mod_ssl: Fixes PR 62654 where "require ssl" did
|
||||
not work on HTTP/2 connections, and PR 61519 where $HTTPS was incorrect
|
||||
for the "SSLEngine optional" case. +1: jorton, jim, minfrin
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1847284 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
STATUS | 11 -----------
|
||||
modules/ssl/mod_ssl.c | 16 ++--------------
|
||||
modules/ssl/ssl_engine_kernel.c | 33 +++++++++++----------------------
|
||||
modules/ssl/ssl_private.h | 5 +++++
|
||||
modules/ssl/ssl_util.c | 17 +++++++++++++++++
|
||||
6 files changed, 39 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
||||
index 37947e78f7..9fdf9e042e 100644
|
||||
--- a/modules/ssl/mod_ssl.c
|
||||
+++ b/modules/ssl/mod_ssl.c
|
||||
@@ -618,24 +618,12 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
|
||||
|
||||
static const char *ssl_hook_http_scheme(const request_rec *r)
|
||||
{
|
||||
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
-
|
||||
- if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- return "https";
|
||||
+ return modssl_request_is_tls(r, NULL) ? "https" : NULL;
|
||||
}
|
||||
|
||||
static apr_port_t ssl_hook_default_port(const request_rec *r)
|
||||
{
|
||||
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
-
|
||||
- if (sc->enabled == SSL_ENABLED_FALSE || sc->enabled == SSL_ENABLED_OPTIONAL) {
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- return 443;
|
||||
+ return modssl_request_is_tls(r, NULL) ? 443 : 0;
|
||||
}
|
||||
|
||||
static int ssl_hook_pre_connection(conn_rec *c, void *csd)
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index de0ffb09ef..62d5539e82 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -1342,8 +1342,7 @@ int ssl_hook_Access(request_rec *r)
|
||||
*/
|
||||
int ssl_hook_UserCheck(request_rec *r)
|
||||
{
|
||||
- SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
+ SSLConnRec *sslconn;
|
||||
SSLDirConfigRec *dc = myDirConfig(r);
|
||||
char *clientdn;
|
||||
const char *auth_line, *username, *password;
|
||||
@@ -1392,15 +1391,15 @@ int ssl_hook_UserCheck(request_rec *r)
|
||||
|
||||
/*
|
||||
* We decline operation in various situations...
|
||||
+ * - TLS not enabled
|
||||
+ * - client did not present a certificate
|
||||
* - SSLOptions +FakeBasicAuth not configured
|
||||
* - r->user already authenticated
|
||||
- * - ssl not enabled
|
||||
- * - client did not present a certificate
|
||||
*/
|
||||
- if (!((sc->enabled == SSL_ENABLED_TRUE || sc->enabled == SSL_ENABLED_OPTIONAL)
|
||||
- && sslconn && sslconn->ssl && sslconn->client_cert) ||
|
||||
- !(dc->nOptions & SSL_OPT_FAKEBASICAUTH) || r->user)
|
||||
- {
|
||||
+ if (!modssl_request_is_tls(r, &sslconn)
|
||||
+ || !sslconn->client_cert
|
||||
+ || !(dc->nOptions & SSL_OPT_FAKEBASICAUTH)
|
||||
+ || r->user) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
@@ -1500,8 +1499,6 @@ static const char *const ssl_hook_Fixup_vars[] = {
|
||||
|
||||
int ssl_hook_Fixup(request_rec *r)
|
||||
{
|
||||
- SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
SSLDirConfigRec *dc = myDirConfig(r);
|
||||
apr_table_t *env = r->subprocess_env;
|
||||
char *var, *val = "";
|
||||
@@ -1509,19 +1506,14 @@ int ssl_hook_Fixup(request_rec *r)
|
||||
const char *servername;
|
||||
#endif
|
||||
STACK_OF(X509) *peer_certs;
|
||||
+ SSLConnRec *sslconn;
|
||||
SSL *ssl;
|
||||
int i;
|
||||
|
||||
- if (!(sslconn && sslconn->ssl) && r->connection->master) {
|
||||
- sslconn = myConnConfig(r->connection->master);
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Check to see if SSL is on
|
||||
- */
|
||||
- if (!(((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) && sslconn && (ssl = sslconn->ssl))) {
|
||||
+ if (!modssl_request_is_tls(r, &sslconn)) {
|
||||
return DECLINED;
|
||||
}
|
||||
+ ssl = sslconn->ssl;
|
||||
|
||||
/*
|
||||
* Annotate the SSI/CGI environment with standard SSL information
|
||||
@@ -1595,10 +1587,7 @@ static authz_status ssl_authz_require_ssl_check(request_rec *r,
|
||||
const char *require_line,
|
||||
const void *parsed)
|
||||
{
|
||||
- SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
- SSL *ssl = sslconn ? sslconn->ssl : NULL;
|
||||
-
|
||||
- if (ssl)
|
||||
+ if (modssl_request_is_tls(r, NULL))
|
||||
return AUTHZ_GRANTED;
|
||||
else
|
||||
return AUTHZ_DENIED;
|
||||
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
|
||||
index 160640384d..f46814d0ad 100644
|
||||
--- a/modules/ssl/ssl_private.h
|
||||
+++ b/modules/ssl/ssl_private.h
|
||||
@@ -1101,6 +1101,11 @@ void ssl_init_ocsp_certificates(server_rec *s, modssl_ctx_t *mctx);
|
||||
* memory. */
|
||||
DH *modssl_get_dh_params(unsigned keylen);
|
||||
|
||||
+/* Returns non-zero if the request was made over SSL/TLS. If sslconn
|
||||
+ * is non-NULL and the request is using SSL/TLS, sets *sslconn to the
|
||||
+ * corresponding SSLConnRec structure for the connection. */
|
||||
+int modssl_request_is_tls(const request_rec *r, SSLConnRec **sslconn);
|
||||
+
|
||||
int ssl_is_challenge(conn_rec *c, const char *servername,
|
||||
X509 **pcert, EVP_PKEY **pkey);
|
||||
|
||||
diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
|
||||
index c372044bbb..0d23465e87 100644
|
||||
--- a/modules/ssl/ssl_util.c
|
||||
+++ b/modules/ssl/ssl_util.c
|
||||
@@ -100,6 +100,23 @@ BOOL ssl_util_vhost_matches(const char *servername, server_rec *s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+int modssl_request_is_tls(const request_rec *r, SSLConnRec **scout)
|
||||
+{
|
||||
+ SSLConnRec *sslconn = myConnConfig(r->connection);
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
+
|
||||
+ if (!(sslconn && sslconn->ssl) && r->connection->master) {
|
||||
+ sslconn = myConnConfig(r->connection->master);
|
||||
+ }
|
||||
+
|
||||
+ if (sc->enabled == SSL_ENABLED_FALSE || !sslconn || !sslconn->ssl)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (scout) *scout = sslconn;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
|
||||
const char * const *argv)
|
||||
{
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From 6315787ba30fe832ffb6cefaab2a30bf67f5d753 Mon Sep 17 00:00:00 2001
|
||||
From: Graham Leggett <minfrin@apache.org>
|
||||
Date: Fri, 23 Nov 2018 14:57:22 +0000
|
||||
Subject: [PATCH 274/504] mod_ssl: Fixes PR 62880 where certificate loading
|
||||
fails bc SSL ERRs are not cleared beforehand. +1: icing, jim,
|
||||
minfrin
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1847280 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 4 ++++
|
||||
STATUS | 6 ------
|
||||
modules/ssl/ssl_engine_init.c | 2 ++
|
||||
modules/ssl/ssl_util_ocsp.c | 2 ++
|
||||
4 files changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
||||
index b7b2be796c..753ed4b3a9 100644
|
||||
--- a/modules/ssl/ssl_engine_init.c
|
||||
+++ b/modules/ssl/ssl_engine_init.c
|
||||
@@ -1038,8 +1038,10 @@ static int use_certificate_chain(
|
||||
ctx->extra_certs = NULL;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
/* create new extra chain by loading the certs */
|
||||
n = 0;
|
||||
+ ERR_clear_error();
|
||||
while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
|
||||
if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
|
||||
X509_free(x509);
|
||||
diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c
|
||||
index b11a6e924e..b66e15146c 100644
|
||||
--- a/modules/ssl/ssl_util_ocsp.c
|
||||
+++ b/modules/ssl/ssl_util_ocsp.c
|
||||
@@ -363,7 +363,9 @@ static STACK_OF(X509) *modssl_read_ocsp_certificates(const char *file)
|
||||
BIO_free(bio);
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
/* create new extra chain by loading the certs */
|
||||
+ ERR_clear_error();
|
||||
while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
|
||||
if (!other_certs) {
|
||||
other_certs = sk_X509_new_null();
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 5b0b68bdfd5a9ac5def45402723d32c5bd39cd8f Mon Sep 17 00:00:00 2001
|
||||
From: Rainer Jung <rjung@apache.org>
|
||||
Date: Thu, 18 Oct 2018 10:03:52 +0000
|
||||
Subject: [PATCH 237/504] mod_ssl: We need to get the SSL_CTX for further
|
||||
processing down below.
|
||||
|
||||
This fixes a crash during SSL renegotiation with OptRenegotiate set,
|
||||
when client certificates are available from the original handshake
|
||||
but were originally not verified and should get verified now.
|
||||
This is a regression in 2.4.36 (unreleased).
|
||||
|
||||
Backport of r1828793 from trunk.
|
||||
|
||||
Submitted by: rjung
|
||||
Reviewed by: rjung, rpluem, jorton
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1844223 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 5 +++++
|
||||
STATUS | 5 -----
|
||||
modules/ssl/ssl_engine_kernel.c | 2 +-
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
||||
index 6cd0da527f..de0ffb09ef 100644
|
||||
--- a/modules/ssl/ssl_engine_kernel.c
|
||||
+++ b/modules/ssl/ssl_engine_kernel.c
|
||||
@@ -485,7 +485,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
|
||||
{
|
||||
server_rec *handshakeserver = sslconn ? sslconn->server : NULL;
|
||||
SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL;
|
||||
- SSL_CTX *ctx = NULL;
|
||||
+ SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL;
|
||||
BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
|
||||
X509 *peercert;
|
||||
X509_STORE *cert_store = NULL;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
From c0b11e0ba834665b87eaa59ff544a3552d5f46e8 Mon Sep 17 00:00:00 2001
|
||||
From: "William A. Rowe Jr" <wrowe@apache.org>
|
||||
Date: Wed, 16 Jan 2019 17:06:07 +0000
|
||||
Subject: [PATCH 330/504] mod_ssl (ssl_engine_io.c: bio_filter_out_write,
|
||||
bio_filter_in_read) Clear retry flags before aborting on client-initiated
|
||||
reneg.
|
||||
|
||||
PR: 63052
|
||||
Backports: r1850946
|
||||
Submitted by: Joe Orton
|
||||
Reviewed by: wrowe, jorton, rpluem
|
||||
|
||||
|
||||
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1851471 13f79535-47bb-0310-9956-ffa450edef68
|
||||
---
|
||||
CHANGES | 3 +++
|
||||
STATUS | 6 ------
|
||||
modules/ssl/ssl_engine_io.c | 12 ++++--------
|
||||
3 files changed, 7 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
|
||||
index b398363b1c..6da8f10118 100644
|
||||
--- a/modules/ssl/ssl_engine_io.c
|
||||
+++ b/modules/ssl/ssl_engine_io.c
|
||||
@@ -200,18 +200,14 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
|
||||
apr_bucket *e;
|
||||
int need_flush;
|
||||
|
||||
+ BIO_clear_retry_flags(bio);
|
||||
+
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
outctx->rc = APR_ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
- /* when handshaking we'll have a small number of bytes.
|
||||
- * max size SSL will pass us here is about 16k.
|
||||
- * (16413 bytes to be exact)
|
||||
- */
|
||||
- BIO_clear_retry_flags(bio);
|
||||
-
|
||||
/* Use a transient bucket for the output data - any downstream
|
||||
* filter must setaside if necessary. */
|
||||
e = apr_bucket_transient_create(in, inl, outctx->bb->bucket_alloc);
|
||||
@@ -458,14 +454,14 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
+ BIO_clear_retry_flags(bio);
|
||||
+
|
||||
/* Abort early if the client has initiated a renegotiation. */
|
||||
if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
|
||||
inctx->rc = APR_ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
- BIO_clear_retry_flags(bio);
|
||||
-
|
||||
if (!inctx->bb) {
|
||||
inctx->rc = APR_EOF;
|
||||
return -1;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user