From 6dba1f89cc94df1f58e3abc545c0452524158e10 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Mon, 8 Mar 2004 17:40:38 +0000 Subject: [PATCH] Fix mod_ssl to issue SSL close_notify alerts before the connection is closed by adding an EOC bucket type: * include/http_connection.h: Declare eoc bucket interface. * server/eoc_bucket.c: New file. * server/Makefile.in, libhttpd.dsp: Build eoc_bucket.c. * server/core.c (core_output_filter): Delete EOC bucket. * server/connection.c (ap_flush_conn): Send an EOC bucket. * modules/ssl/ssl_engine_io.c (ssl_io_filter_output): Shutdown the SSL connection for an EOC bucket. (bio_filter_out_write): Conditionally disable buffering. PR: 27428 Submitted by: Madhusudan Mathihalli Reviewed by: Madhusudan Mathihalli, Justin Erenkrantz, Joe Orton (sneaking in fixes for libhttpd.dsp and NWGNUMakefile) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@102885 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ NWGNUmakefile | 1 + STATUS | 14 +------------- include/http_connection.h | 28 ++++++++++++++++++++++++++++ libhttpd.dsp | 4 ++++ modules/ssl/ssl_engine_io.c | 20 +++++++++++++++++++- server/Makefile.in | 3 ++- server/connection.c | 7 +++++++ server/core.c | 5 ++++- 9 files changed, 69 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 4edb18d0173..a037d9e41f3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 2.0.49 + *) mod_ssl: Send the Close Alert message to the peer before closing + the SSL session. PR 27428. [Madhusudan Mathihalli, Joe Orton] + *) SECURITY: CAN-2004-0113 (cve.mitre.org) mod_ssl: Fix a memory leak in plain-HTTP-on-SSL-port handling. PR 27106. [Joe Orton] diff --git a/NWGNUmakefile b/NWGNUmakefile index e1859496d72..4ae883a4f11 100644 --- a/NWGNUmakefile +++ b/NWGNUmakefile @@ -194,6 +194,7 @@ FILES_nlm_objs = \ $(OBJDIR)/config.o \ $(OBJDIR)/connection.o \ $(OBJDIR)/core.o \ + $(OBJDIR)/eoc_bucket.o \ $(OBJDIR)/error_bucket.o \ $(OBJDIR)/http_core.o \ $(OBJDIR)/http_protocol.o \ diff --git a/STATUS b/STATUS index 5d5ecefd3b1..cd93acffa87 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ APACHE 2.0 STATUS: -*-text-*- -Last modified at [$Date: 2004/03/08 16:40:42 $] +Last modified at [$Date: 2004/03/08 17:40:34 $] Release: @@ -81,18 +81,6 @@ PATCHES TO BACKPORT FROM 2.1 http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/mpm/winnt/child.c?r1=1.29&r2=1.30 +1: stoddard, trawick, ake - * mod_ssl: Send the Close Alert message to the peer before closing - the SSL session. - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/include/http_connection.h?r1=1.59&r2=1.60 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/ssl/ssl_engine_io.c?r1=1.118&r2=1.119 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/Makefile.in?r1=1.91&r2=1.92 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/connection.c?r1=1.114&r2=1.116 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/core.c?r1=1.261&r2=1.263 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/eoc_bucket.c (new file) - PR: 27428 - +1: madhum, jerenkrantz, jorton - (jorton: needs libhttpd.dsp change for Win32 too) - * mod_setenvif: remove support for remote_user variable which never worked at all. PR 25725 (2.0 + 1.3) modules/metadata/mod_setenvif.c: r1.50 diff --git a/include/http_connection.h b/include/http_connection.h index 1550fe385e9..75d614f3725 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/libhttpd.dsp b/libhttpd.dsp index 7a22427512d..057e3974033 100644 --- a/libhttpd.dsp +++ b/libhttpd.dsp @@ -401,6 +401,10 @@ SOURCE=.\os\win32\modules.c # PROP Default_Filter "" # Begin Source File +SOURCE=.\server\eoc_bucket.c +# End Source File +# Begin Source File + SOURCE=.\server\error_bucket.c # End Source File # Begin Source File diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index d48f581f9fc..93e85460dd0 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) */ @@ -1309,6 +1311,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/Makefile.in b/server/Makefile.in index a20b4206cb8..b5598847946 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -14,7 +14,8 @@ LTLIBRARY_SOURCES = \ rfc1413.c connection.c listen.c \ mpm_common.c util_charset.c util_debug.c util_xml.c \ util_filter.c exports.c buildmark.c \ - scoreboard.c error_bucket.c protocol.c core.c request.c provider.c + scoreboard.c error_bucket.c protocol.c core.c request.c provider.c \ + eoc_bucket.c TARGETS = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE) export_vars.h httpd.exp diff --git a/server/connection.c b/server/connection.c index e46cbbb27f7..29cbae26b99 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 = ap_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 5ca95130b85..2fda1fb37d1 100644 --- a/server/core.c +++ b/server/core.c @@ -3857,7 +3857,10 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) if (APR_BUCKET_IS_EOS(e)) { break; } - if (APR_BUCKET_IS_FLUSH(e)) { + if (AP_BUCKET_IS_EOC(e)) { + apr_bucket_delete(e); + } + else if (APR_BUCKET_IS_FLUSH(e)) { if (e != APR_BRIGADE_LAST(b)) { more = apr_brigade_split(b, APR_BUCKET_NEXT(e)); } -- 2.47.2