]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Fix mod_ssl to issue SSL close_notify alerts before the connection is
authorJoe Orton <jorton@apache.org>
Mon, 8 Mar 2004 17:40:38 +0000 (17:40 +0000)
committerJoe Orton <jorton@apache.org>
Mon, 8 Mar 2004 17:40:38 +0000 (17:40 +0000)
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
NWGNUmakefile
STATUS
include/http_connection.h
libhttpd.dsp
modules/ssl/ssl_engine_io.c
server/Makefile.in
server/connection.c
server/core.c

diff --git a/CHANGES b/CHANGES
index 4edb18d01735d679e1dd3f176dfcba66927bc911..a037d9e41f3665b70ebe08d927265905a7231cc2 100644 (file)
--- 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]
index e1859496d72a606c6232bad1e071928b7348bc15..4ae883a4f11c3cdeb44ab7b8cc25cee302f6cec9 100644 (file)
@@ -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 5d5ecefd3b1e035c26a772f1bf456ea2982f69e3..cd93acffa87c0e78426eaac5ecc146827bbb1e39 100644 (file)
--- 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
index 1550fe385e9b1e08f2c62c168bb392d2b4d0c19a..75d614f37255b791ce42b38a76cb1bec32fde4d6 100644 (file)
@@ -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
index 7a22427512d03f757df32e6268145050942cc030..057e3974033c9f954fc97119fad27de6b83e1df5 100644 (file)
@@ -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
index d48f581f9fc2245c0608b985edc1ddfb1f0df21c..93e85460dd0ac3f402b90f99104a1ac1e3fd6b95 100644 (file)
@@ -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;
index a20b4206cb8bfb6bffacddedb612d6c28c0f705c..b5598847946ddba54e2593e7d9fb759e87017b44 100644 (file)
@@ -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
 
index e46cbbb27f7536e69ba88810d0bbc1507a774f49..29cbae26b992193903ff332db07c58b476d2015d 100644 (file)
@@ -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);
 }
 
index 5ca95130b8563526d5fc05c41660cadf1ee5753a..2fda1fb37d1e9b97bf199fa7772791782257e7ef 100644 (file)
@@ -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));
                 }