From e22d89c9d6247f7c95ad6b8ab3768671c8f3d75e Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Mon, 12 Jan 2015 13:31:16 +0000 Subject: [PATCH] Merge r1601184, r1601274, r1601185 from trunk: mod_ssl: Ensure that the SSL close notify alert is flushed to the client. PR54998. Submitted By: Tim Kosse , ylavic Committed By: ylavic mod_ssl: SSL_smart_shutdown(): follow up to r1601184. Use SSL_get_wbio() to comply with OPENSSL_NO_SSL_INTERN. Stop SSL shutdown loop when flush fails. mpm_event[opt]: Send the SSL close notify alert when the KeepAliveTimeout expires. PR54998. Submitted by: ylavic Reviewed/backported by: jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1651077 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 ++++++ include/ap_mmn.h | 3 ++- include/http_connection.h | 9 +++++++++ modules/ssl/ssl_util_ssl.c | 15 ++++++++++++++- server/connection.c | 20 +++++++++++++++----- server/mpm/event/event.c | 1 + 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 6856108527..e6d7d4f639 100644 --- a/CHANGES +++ b/CHANGES @@ -237,6 +237,12 @@ Changes with Apache 2.4.10 *) mod_proxy_fcgi: Support iobuffersize parameter. [Jeff Trawick] + *) event: Send the SSL close notify alert when the KeepAliveTimeout + expires. PR54998. [Yann Ylavic] + + *) mod_ssl: Ensure that the SSL close notify alert is flushed to the client. + PR54998. [Tim Kosse , Yann Ylavic] + *) mod_auth_form: Add a debug message when the fields on a form are not recognised. [Graham Leggett] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 83d979467b..7a278b9c22 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -433,6 +433,7 @@ to util_ldap_connection_t * 20120211.36 (2.4.10-dev) Add ap_copy_scoreboard_worker() * 20120211.37 (2.4.11-dev) Add r->trailers_{in,out} + * 20120211.38 (2.4.10-dev) Added ap_shutdown_conn(). */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -440,7 +441,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 37 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 38 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_connection.h b/include/http_connection.h index 11f8dd1b60..58389a4fb4 100644 --- a/include/http_connection.h +++ b/include/http_connection.h @@ -43,9 +43,18 @@ extern "C" { */ AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, void *csd); +/** + * Shutdown the connection for writing. + * @param c The connection to shutdown + * @param flush Whether or not to flush pending data before + * @return APR_SUCCESS or the underlying error + */ +AP_CORE_DECLARE(apr_status_t) ap_shutdown_conn(conn_rec *c, int flush); + /** * Flushes all remain data in the client send buffer * @param c The connection to flush + * @remark calls ap_shutdown_conn(c, 1) */ AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c); diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index 0bf377682c..b6183e8b55 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -125,6 +125,7 @@ int SSL_smart_shutdown(SSL *ssl) { int i; int rc; + int flush; /* * Repeat the calls, because SSL_shutdown internally dispatches through a @@ -134,8 +135,20 @@ int SSL_smart_shutdown(SSL *ssl) * connection and OpenSSL cannot recognize it. */ rc = 0; + flush = !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN); for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) { - if ((rc = SSL_shutdown(ssl))) + rc = SSL_shutdown(ssl); + if (rc >= 0 && flush && (SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) { + /* Once the close notity is sent through the output filters, + * ensure it is flushed through the socket. + */ + if (BIO_flush(SSL_get_wbio(ssl)) <= 0) { + rc = -1; + break; + } + flush = 0; + } + if (rc != 0) break; } return rc; diff --git a/server/connection.c b/server/connection.c index fadf08d35b..52be96e631 100644 --- a/server/connection.c +++ b/server/connection.c @@ -64,22 +64,32 @@ AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),O #define MAX_SECS_TO_LINGER 30 #endif -AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) +AP_CORE_DECLARE(apr_status_t) ap_shutdown_conn(conn_rec *c, int flush) { + apr_status_t rv; apr_bucket_brigade *bb; apr_bucket *b; bb = apr_brigade_create(c->pool, c->bucket_alloc); - /* FLUSH bucket */ - b = apr_bucket_flush_create(c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, b); + if (flush) { + /* FLUSH bucket */ + b = apr_bucket_flush_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + } /* End Of Connection bucket */ b = ap_bucket_eoc_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); - ap_pass_brigade(c->output_filters, bb); + rv = ap_pass_brigade(c->output_filters, bb); + apr_brigade_destroy(bb); + return rv; +} + +AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) +{ + (void)ap_shutdown_conn(c, 1); } /* we now proceed to read from the client until we get EOF, or until diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index bad336627e..9e41c695ce 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -870,6 +870,7 @@ static int start_lingering_close_nonblocking(event_conn_state_t *cs) apr_socket_t *csd = cs->pfd.desc.s; if (c->aborted + || ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { apr_socket_close(csd); ap_push_pool(worker_queue_info, cs->p); -- 2.50.1