gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] branch master updated: fix #5411


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: fix #5411
Date: Fri, 05 Oct 2018 19:23:28 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new 0db81a92 fix #5411
0db81a92 is described below

commit 0db81a9248b12abc74f153ebd642441d0f9c3e58
Author: Christian Grothoff <address@hidden>
AuthorDate: Fri Oct 5 19:23:26 2018 +0200

    fix #5411
---
 ChangeLog                   | 10 ++++++
 doc/libmicrohttpd.texi      | 15 +++++++--
 src/microhttpd/connection.c | 79 ++++++++++++++++++++++++++-------------------
 src/microhttpd/response.c   | 21 ++++++++++++
 4 files changed, 90 insertions(+), 35 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 068780e3..eb273daf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Fri Oct  5 18:44:45 CEST 2018
+       MHD_add_response_header() now prevents applications from
+       setting a "Transfer-Encoding" header to values other than
+       "identity" or "chunked" as other transfer encodings are
+       not supported by MHD. (Note that usually MHD will pick the
+       transfer encoding correctly automatically, but applications
+       can use the header to force a particular behavior.)
+       Fixing #5411 (never set Content-length if Transfer-Encoding
+       is given). -CG
+
 Sat Jul 14 11:42:15 CEST 2018
        Add MHD_OPTION_GNUTLS_PSK_CRED_HANDLER to allow use of PSK with
        TLS connections. -CG/TM
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index d2886a25..b61c94ff 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -874,9 +874,9 @@ or higher.
 @cindex TLS
 @cindex PSK
 Use pre-shared key for TLS credentials.
-Pass a pointer to callback of type 
+Pass a pointer to callback of type
 @code{MHD_PskServerCredentialsCallback} and a closure.
-The function will be called to 
+The function will be called to
 retrieve the shared key for a given username.
 
 @item MHD_OPTION_DIGEST_AUTH_RANDOM
@@ -2050,6 +2050,17 @@ duplicated into memory blocks embedded in @var{response}.
 Notice that the strings must not hold newlines, carriage returns or tab
 chars.
 
+MHD_add_response_header() prevents applications from setting a
+``Transfer-Encoding'' header to values other than ``identity'' or
+``chunked'' as other transfer encodings are not supported by MHD. Note
+that usually MHD will pick the transfer encoding correctly
+automatically, but applications can use the header to force a
+particular behavior.
+
+MHD_add_response_header() also prevents applications from setting a
+``Content-Length'' header. MHD will automatically set a correct
+``Content-Length'' header if it is possible and allowed.
+
 Return @code{MHD_NO} on error (i.e. invalid header or content format or
 memory allocation error).
 @end deftypefun
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 1778c59b..60dc5eb4 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1404,6 +1404,7 @@ try_grow_read_buffer (struct MHD_Connection *connection)
 static int
 build_header_response (struct MHD_Connection *connection)
 {
+  struct MHD_Response *response = connection->response;
   size_t size;
   size_t off;
   struct MHD_HTTP_Header *pos;
@@ -1420,11 +1421,11 @@ build_header_response (struct MHD_Connection 
*connection)
   bool response_has_close;
   bool response_has_keepalive;
   const char *have_encoding;
-  const char *have_content_length;
   int must_add_close;
   int must_add_chunked_encoding;
   int must_add_keep_alive;
   int must_add_content_length;
+  int may_add_content_length;
 
   mhd_assert (NULL != connection->version);
   if (0 == connection->version[0])
@@ -1458,7 +1459,7 @@ build_header_response (struct MHD_Connection *connection)
       size = off + 2;           /* +2 for extra "\r\n" at the end */
       kind = MHD_HEADER_KIND;
       if ( (0 == (connection->daemon->options & 
MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
-          (NULL == MHD_get_response_header (connection->response,
+          (NULL == MHD_get_response_header (response,
                                             MHD_HTTP_HEADER_DATE)) )
         get_date_string (date,
                         sizeof (date));
@@ -1486,30 +1487,35 @@ build_header_response (struct MHD_Connection 
*connection)
   switch (connection->state)
     {
     case MHD_CONNECTION_FOOTERS_RECEIVED:
-      response_has_close = MHD_check_response_header_s_token_ci 
(connection->response,
+      response_has_close = MHD_check_response_header_s_token_ci (response,
                                                                  
MHD_HTTP_HEADER_CONNECTION,
                                                                  "close");
-      response_has_keepalive = MHD_check_response_header_s_token_ci 
(connection->response,
+      response_has_keepalive = MHD_check_response_header_s_token_ci (response,
                                                                      
MHD_HTTP_HEADER_CONNECTION,
                                                                      
"Keep-Alive");
       client_requested_close = MHD_lookup_header_s_token_ci (connection,
-                                                            
MHD_HTTP_HEADER_CONNECTION,
-                                                            "close");
+                                                             
MHD_HTTP_HEADER_CONNECTION,
+                                                             "close");
 
-      if (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
+      if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
         connection->keepalive = MHD_CONN_MUST_CLOSE;
 #ifdef UPGRADE_SUPPORT
-      else if (NULL != connection->response->upgrade_handler)
+      else if (NULL != response->upgrade_handler)
         /* If this connection will not be "upgraded", it must be closed. */
         connection->keepalive = MHD_CONN_MUST_CLOSE;
 #endif /* UPGRADE_SUPPORT */
 
       /* now analyze chunked encoding situation */
       connection->have_chunked_upload = false;
-
-      if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
+      have_encoding = MHD_get_response_header (response,
+                                               
MHD_HTTP_HEADER_TRANSFER_ENCODING);
+      if (NULL == have_encoding)
+        may_add_content_length = MHD_YES;
+      else
+        may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids 
header */
+      if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
 #ifdef UPGRADE_SUPPORT
-           (NULL == connection->response->upgrade_handler) &&
+           (NULL == response->upgrade_handler) &&
 #endif /* UPGRADE_SUPPORT */
            (! response_has_close) &&
            (! client_requested_close) )
@@ -1523,22 +1529,23 @@ build_header_response (struct MHD_Connection 
*connection)
                (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
                                          connection->version) ) )
             {
-              have_encoding = MHD_get_response_header (connection->response,
-                                                       
MHD_HTTP_HEADER_TRANSFER_ENCODING);
               if (NULL == have_encoding)
                 {
                   must_add_chunked_encoding = MHD_YES;
                   connection->have_chunked_upload = true;
                 }
-              else if (MHD_str_equal_caseless_ (have_encoding,
-                                                "identity"))
-                {
-                  /* application forced identity encoding, can't do 'chunked' 
*/
-                  must_add_close = MHD_YES;
-                }
               else
                 {
-                  connection->have_chunked_upload = true;
+                  if (MHD_str_equal_caseless_ (have_encoding,
+                                               "identity"))
+                    {
+                      /* application forced identity encoding, can't do 
'chunked' */
+                      must_add_close = MHD_YES;
+                    }
+                  else
+                    {
+                      connection->have_chunked_upload = true;
+                    }
                 }
             }
           else
@@ -1556,23 +1563,29 @@ build_header_response (struct MHD_Connection 
*connection)
              (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
            (! response_has_close) &&
 #ifdef UPGRADE_SUPPORT
-           (NULL == connection->response->upgrade_handler) &&
+           (NULL == response->upgrade_handler) &&
 #endif /* UPGRADE_SUPPORT */
-           (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) 
) )
+           (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
         must_add_close = MHD_YES;
 
-      /* check if we should add a 'content length' header */
-      have_content_length = MHD_get_response_header (connection->response,
-                                                     
MHD_HTTP_HEADER_CONTENT_LENGTH);
-
-      /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
+      /* check if we must add 'close' header because we cannot add 
content-length
+         because it is forbidden AND we don't have a 'chunked' encoding */
+      if ( (! may_add_content_length) &&
+           (! connection->have_chunked_upload) &&
+           (! response_has_close) )
+        must_add_close = MHD_YES;
+      /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
          codes SHOULD NOT have a Content-Length according to spec;
          also chunked encoding / unknown length or CONNECT... */
-      if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
+      if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
            (MHD_HTTP_NO_CONTENT != rc) &&
            (MHD_HTTP_NOT_MODIFIED != rc) &&
            (MHD_HTTP_OK <= rc) &&
-           (NULL == have_content_length) &&
+           (NULL == /* this should always succeed due to check in
+                       MHD_add_response_header() */
+            MHD_get_response_header (response,
+                                     MHD_HTTP_HEADER_CONTENT_LENGTH)) &&
+           (may_add_content_length) &&
            ( (NULL == connection->method) ||
              (! MHD_str_equal_caseless_ (connection->method,
                                          MHD_HTTP_METHOD_CONNECT)) ) )
@@ -1596,7 +1609,7 @@ build_header_response (struct MHD_Connection *connection)
             = MHD_snprintf_ (content_length_buf,
                             sizeof (content_length_buf),
                             MHD_HTTP_HEADER_CONTENT_LENGTH ": " 
MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
-                            (MHD_UNSIGNED_LONG_LONG) 
connection->response->total_size);
+                            (MHD_UNSIGNED_LONG_LONG) response->total_size);
           must_add_content_length = MHD_YES;
         }
 
@@ -1606,7 +1619,7 @@ build_header_response (struct MHD_Connection *connection)
            (MHD_NO == must_add_close) &&
            (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
 #ifdef UPGRADE_SUPPORT
-           (NULL == connection->response->upgrade_handler) &&
+           (NULL == response->upgrade_handler) &&
 #endif /* UPGRADE_SUPPORT */
            (MHD_YES == keepalive_possible (connection)) )
         must_add_keep_alive = MHD_YES;
@@ -1638,7 +1651,7 @@ build_header_response (struct MHD_Connection *connection)
   mhd_assert (! (must_add_close && must_add_keep_alive) );
   mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
 
-  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
+  for (pos = response->first_header; NULL != pos; pos = pos->next)
     {
       /* TODO: add proper support for excluding "Keep-Alive" token. */
       if ( (pos->kind == kind) &&
@@ -1700,7 +1713,7 @@ build_header_response (struct MHD_Connection *connection)
              content_length_len);
       off += content_length_len;
     }
-  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
+  for (pos = response->first_header; NULL != pos; pos = pos->next)
     {
       /* TODO: add proper support for excluding "Keep-Alive" token. */
       if ( (pos->kind == kind) &&
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 9de4843d..d7835c20 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -119,6 +119,27 @@ MHD_add_response_header (struct MHD_Response *response,
                          const char *header,
                          const char *content)
 {
+  if ( (MHD_str_equal_caseless_ (header,
+                                 MHD_HTTP_HEADER_TRANSFER_ENCODING)) &&
+       (! MHD_str_equal_caseless_ (content,
+                                   "identity")) &&
+       (! MHD_str_equal_caseless_ (content,
+                                   "chunked")) )
+    {
+      /* Setting transfer encodings other than "identity" or
+         "chunked" is not allowed.  Note that MHD will set the
+         correct transfer encoding if required automatically. */
+      /* NOTE: for compressed bodies, use the "Content-encoding" header */
+      return MHD_NO;
+    }
+  if (MHD_str_equal_caseless_ (header,
+                               MHD_HTTP_HEADER_CONTENT_LENGTH))
+    {
+      /* MHD will set Content-length if allowed and possible,
+         reject attempt by application */
+      return MHD_NO;
+    }
+
   return add_response_entry (response,
                             MHD_HEADER_KIND,
                             header,

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]