[core] use openssl to read,discard request body
use openssl to read,discard request body after response has been sent on a TLS connection, at least until SSL close notify has been sent x-ref: "HTTPS POST upload hangs when i reach maximum supported request size" https://redmine.lighttpd.net/boards/2/topics/8491personal/stbuehler/ci-build
parent
fca9e5a0b1
commit
1542e44bb7
|
@ -150,7 +150,7 @@ static int connection_close(server *srv, connection *con) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void connection_read_for_eos(server *srv, connection *con) {
|
||||
static void connection_read_for_eos_plain(server *srv, connection *con) {
|
||||
/* we have to do the linger_on_close stuff regardless
|
||||
* of con->keep_alive; even non-keepalive sockets may
|
||||
* still have unread data, and closing before reading
|
||||
|
@ -173,6 +173,18 @@ static void connection_read_for_eos(server *srv, connection *con) {
|
|||
con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
|
||||
}
|
||||
|
||||
static void connection_read_for_eos_ssl(server *srv, connection *con) {
|
||||
if (con->network_read(srv, con, con->read_queue, MAX_READ_LIMIT) < 0)
|
||||
con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
|
||||
chunkqueue_reset(con->read_queue);
|
||||
}
|
||||
|
||||
static void connection_read_for_eos(server *srv, connection *con) {
|
||||
!con->is_ssl_sock
|
||||
? connection_read_for_eos_plain(srv, con)
|
||||
: connection_read_for_eos_ssl(srv, con);
|
||||
}
|
||||
|
||||
static void connection_handle_close_state(server *srv, connection *con) {
|
||||
connection_read_for_eos(srv, con);
|
||||
|
||||
|
@ -188,7 +200,8 @@ static void connection_handle_shutdown(server *srv, connection *con) {
|
|||
connection_reset(srv, con);
|
||||
|
||||
/* close the connection */
|
||||
if (con->fd >= 0 && 0 == shutdown(con->fd, SHUT_WR)) {
|
||||
if (con->fd >= 0
|
||||
&& (con->is_ssl_sock || 0 == shutdown(con->fd, SHUT_WR))) {
|
||||
con->close_timeout_ts = srv->cur_ts;
|
||||
connection_set_state(srv, con, CON_STATE_CLOSE);
|
||||
|
||||
|
|
|
@ -88,7 +88,8 @@ static char *local_send_buffer;
|
|||
typedef struct {
|
||||
SSL *ssl;
|
||||
connection *con;
|
||||
int renegotiations; /* count of SSL_CB_HANDSHAKE_START */
|
||||
short renegotiations; /* count of SSL_CB_HANDSHAKE_START */
|
||||
short close_notify;
|
||||
unsigned short request_env_patched;
|
||||
unsigned short alpn;
|
||||
plugin_config conf;
|
||||
|
@ -1508,6 +1509,10 @@ load_next_chunk (server *srv, chunkqueue *cq, off_t max_bytes,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
mod_openssl_close_notify(server *srv, handler_ctx *hctx);
|
||||
|
||||
|
||||
static int
|
||||
connection_write_cq_ssl (server *srv, connection *con,
|
||||
chunkqueue *cq, off_t max_bytes)
|
||||
|
@ -1515,6 +1520,8 @@ connection_write_cq_ssl (server *srv, connection *con,
|
|||
handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id];
|
||||
SSL *ssl = hctx->ssl;
|
||||
|
||||
if (0 != hctx->close_notify) return mod_openssl_close_notify(srv, hctx);
|
||||
|
||||
chunkqueue_remove_finished_chunks(cq);
|
||||
|
||||
while (max_bytes > 0 && NULL != cq->first) {
|
||||
|
@ -1622,6 +1629,8 @@ connection_read_cq_ssl (server *srv, connection *con,
|
|||
force_assert(cq == con->read_queue);
|
||||
UNUSED(max_bytes);
|
||||
|
||||
if (0 != hctx->close_notify) return mod_openssl_close_notify(srv, hctx);
|
||||
|
||||
ERR_clear_error();
|
||||
do {
|
||||
len = SSL_pending(hctx->ssl);
|
||||
|
@ -1798,7 +1807,16 @@ CONNECTION_FUNC(mod_openssl_handle_con_accept)
|
|||
|
||||
|
||||
static void
|
||||
mod_openssl_close_notify(server *srv, handler_ctx *hctx);
|
||||
mod_openssl_detach(handler_ctx *hctx)
|
||||
{
|
||||
/* step aside from futher SSL processing
|
||||
* (used after handle_connection_shut_wr hook) */
|
||||
/* future: might restore prior network_read and network_write fn ptrs */
|
||||
hctx->con->is_ssl_sock = 0;
|
||||
/* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */
|
||||
if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR);
|
||||
hctx->close_notify = 1;
|
||||
}
|
||||
|
||||
|
||||
CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)
|
||||
|
@ -1807,34 +1825,36 @@ CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)
|
|||
handler_ctx *hctx = con->plugin_ctx[p->id];
|
||||
if (NULL == hctx) return HANDLER_GO_ON;
|
||||
|
||||
hctx->close_notify = -2;
|
||||
if (SSL_is_init_finished(hctx->ssl)) {
|
||||
mod_openssl_close_notify(srv, hctx);
|
||||
}
|
||||
else {
|
||||
mod_openssl_detach(hctx);
|
||||
}
|
||||
|
||||
return HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static int
|
||||
mod_openssl_close_notify(server *srv, handler_ctx *hctx)
|
||||
{
|
||||
int ret, ssl_r;
|
||||
unsigned long err;
|
||||
|
||||
if (1 == hctx->close_notify) return -2;
|
||||
|
||||
ERR_clear_error();
|
||||
switch ((ret = SSL_shutdown(hctx->ssl))) {
|
||||
case 1:
|
||||
/* ok */
|
||||
break;
|
||||
mod_openssl_detach(hctx);
|
||||
return -2;
|
||||
case 0:
|
||||
/* wait for fd-event
|
||||
*
|
||||
* FIXME: wait for fdevent and call SSL_shutdown again
|
||||
*
|
||||
*/
|
||||
|
||||
/* Drain SSL read buffers in case pending records need processing.
|
||||
* Limit to reading 16k to avoid denial of service when the CPU
|
||||
* Limit to reading next record to avoid denial of service when CPU
|
||||
* processing TLS is slower than arrival speed of TLS data packets.
|
||||
* (unless hctx->conf.ssl_read_ahead is set)
|
||||
*
|
||||
* references:
|
||||
*
|
||||
|
@ -1852,25 +1872,40 @@ mod_openssl_close_notify(server *srv, handler_ctx *hctx)
|
|||
* Additional discussion in "Auto retry in shutdown"
|
||||
* https://github.com/openssl/openssl/pull/6340
|
||||
*/
|
||||
err = 0;
|
||||
do {
|
||||
char buf[4096];
|
||||
ret = SSL_read(hctx->ssl, buf, (int)sizeof(buf));
|
||||
} while (ret > 0 && (err += (unsigned long)ret) < 16384);
|
||||
ssl_r = SSL_pending(hctx->ssl);
|
||||
if (ssl_r) {
|
||||
do {
|
||||
char buf[4096];
|
||||
ret = SSL_read(hctx->ssl, buf, (int)sizeof(buf));
|
||||
} while (ret > 0 && (hctx->conf.ssl_read_ahead||(ssl_r-=ret)));
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
if (-1 != (ret = SSL_shutdown(hctx->ssl))) break;
|
||||
switch ((ret = SSL_shutdown(hctx->ssl))) {
|
||||
case 1:
|
||||
mod_openssl_detach(hctx);
|
||||
return -2;
|
||||
case 0:
|
||||
hctx->close_notify = -1;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
default:
|
||||
|
||||
if (!SSL_is_init_finished(hctx->ssl)) {
|
||||
mod_openssl_detach(hctx);
|
||||
return -2;
|
||||
}
|
||||
|
||||
switch ((ssl_r = SSL_get_error(hctx->ssl, ret))) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
/*con->is_writable=-1;*//*(no effect; shutdown() called below)*/
|
||||
case SSL_ERROR_WANT_READ:
|
||||
break;
|
||||
hctx->close_notify = -1;
|
||||
return 0; /* try again later */
|
||||
case SSL_ERROR_SYSCALL:
|
||||
/* perhaps we have error waiting in our error-queue */
|
||||
if (0 != (err = ERR_get_error())) {
|
||||
|
@ -1905,6 +1940,8 @@ mod_openssl_close_notify(server *srv, handler_ctx *hctx)
|
|||
}
|
||||
}
|
||||
ERR_clear_error();
|
||||
hctx->close_notify = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue