From 48c38a4533cc942ecd66ebaa56570b14fe963ca3 Mon Sep 17 00:00:00 2001 From: Madhusudan Mathihalli Date: Sat, 28 Feb 2004 00:45:26 +0000 Subject: [PATCH] Send the 'Close Alert' message to the peer upon closing a SSL session. This required creating a new EOC (End-Of-Connection) bucket type to notify mod_ssl that the connection is about to be closed. Reviewed by: Joe Orton, Justin Erenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102793 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ include/http_connection.h | 28 ++++++++++++++++++++++++++++ modules/ssl/ssl_engine_io.c | 20 +++++++++++++++++++- server/connection.c | 7 +++++++ server/core.c | 3 +++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 493215591c..6eee255c56 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) mod_ssl: Send the Close Alert message to the peer before closing + the SSL session. [Madhusudan Mathihalli, Joe Orton] + *) mod_setenvif: Remove "support" for Remote_User variable which never worked at all. PR 25725. [André Malo] diff --git a/include/http_connection.h b/include/http_connection.h index 1550fe385e..75d614f372 100644 --- a/include/http_connection.h +++ b/include/http_connection.h @@ -103,6 +103,34 @@ AP_DECLARE_HOOK(int,pre_connection,(conn_rec *c, void *csd)) */ AP_DECLARE_HOOK(int,process_connection,(conn_rec *c)) +/* End Of Connection (EOC) bucket */ + +AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eoc; + +/** + * Determine if a bucket is an End Of Connection (EOC) bucket + * @param e The bucket to inspect + * @return true or false + */ +#define AP_BUCKET_IS_EOC(e) (e->type == &ap_bucket_type_eoc) + +/** + * Make the bucket passed in an End Of Connection (EOC) bucket + * @param b The bucket to make into an EOC bucket + * @return The new bucket, or NULL if allocation failed + * @deffunc apr_bucket *ap_bucket_eoc_make(apr_bucket *b) + */ +AP_DECLARE(apr_bucket *) ap_bucket_eoc_make(apr_bucket *b); + +/** + * Create a bucket referring to an End Of Connection (EOC). This indicates + * that the connection will be closed. + * @param list The freelist from which this bucket should be allocated + * @return The new bucket, or NULL if allocation failed + * @deffunc apr_bucket *ap_bucket_eoc_create(apr_bucket_alloc_t *list) + */ +AP_DECLARE(apr_bucket *) ap_bucket_eoc_create(apr_bucket_alloc_t *list); + #ifdef __cplusplus } #endif diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index 5787c86c31..19f763fb3b 100644 --- a/modules/ssl/ssl_engine_io.c +++ b/modules/ssl/ssl_engine_io.c @@ -100,6 +100,7 @@ typedef struct { BIO *pbioWrite; ap_filter_t *pInputFilter; ap_filter_t *pOutputFilter; + int nobuffer; /* non-zero to prevent buffering */ } ssl_filter_ctx_t; typedef struct { @@ -193,7 +194,8 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl) */ BIO_clear_retry_flags(bio); - if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer))) { + if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer)) && + !outctx->filter_ctx->nobuffer) { /* the first two SSL_writes (of 1024 and 261 bytes) * need to be in the same packet (vec[0].iov_base) */ @@ -1396,6 +1398,22 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, apr_bucket_delete(bucket); } } + else if (AP_BUCKET_IS_EOC(bucket)) { + /* The special "EOC" bucket means a shutdown is needed; + * - turn off buffering in bio_filter_out_write + * - issue the SSL_shutdown + */ + filter_ctx->nobuffer = 1; + status = ssl_filter_io_shutdown(filter_ctx, f->c, 0); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_INFO, status, NULL, + "SSL filter error shutting down I/O"); + } + if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { + return status; + } + break; + } else { /* filter output */ const char *data; diff --git a/server/connection.c b/server/connection.c index 0f9ac746cc..07e3341878 100644 --- a/server/connection.c +++ b/server/connection.c @@ -71,8 +71,15 @@ AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) 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); + + /* End Of Connection bucket */ + b = apr_bucket_eoc_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + ap_pass_brigade(c->output_filters, bb); } diff --git a/server/core.c b/server/core.c index 2bd91f1355..467b5b06ac 100644 --- a/server/core.c +++ b/server/core.c @@ -3854,6 +3854,9 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) if (APR_BUCKET_IS_EOS(e)) { break; } + if (AP_BUCKET_IS_EOC(e)) { + apr_bucket_delete(e); + } if (APR_BUCKET_IS_FLUSH(e)) { if (e != APR_BRIGADE_LAST(b)) { more = apr_brigade_split(b, APR_BUCKET_NEXT(e)); -- 2.50.1