gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] 01/05: Added detection of HTTP version during early pars


From: gnunet
Subject: [libmicrohttpd] 01/05: Added detection of HTTP version during early parsing
Date: Wed, 26 May 2021 20:24:32 +0200

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

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit de6922ca8204fe08d8105591bf094c0a359da8c3
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Fri May 21 18:59:49 2021 +0300

    Added detection of HTTP version during early parsing
    
    Requests with unsupported HTTP versions are rejected as specified
    by RFC 7230.
---
 src/microhttpd/connection.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
 src/microhttpd/internal.h   | 58 ++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 08b76eb6..8876f692 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -114,6 +114,26 @@
 #define INTERNAL_ERROR ""
 #endif
 
+/**
+ * Response text used when the request HTTP version is too old.
+ */
+#ifdef HAVE_MESSAGES
+#define REQ_HTTP_VER_IS_TOO_OLD \
+  "<html><head><title>Requested HTTP version is not 
supported</title></head><body>Requested HTTP version is too old and not 
supported.</body></html>"
+#else
+#define REQ_HTTP_VER_IS_TOO_OLD ""
+#endif
+
+/**
+ * Response text used when the request HTTP version is too old.
+ */
+#ifdef HAVE_MESSAGES
+#define REQ_HTTP_VER_IS_NOT_SUPPORTED \
+  "<html><head><title>Requested HTTP version is not 
supported</title></head><body>Requested HTTP version is not 
supported.</body></html>"
+#else
+#define REQ_HTTP_VER_IS_NOT_SUPPORTED ""
+#endif
+
 
 /**
  * sendfile() chuck size
@@ -2087,6 +2107,69 @@ parse_cookie_header (struct MHD_Connection *connection)
 }
 
 
+/**
+ * Detect HTTP version
+ *
+ * @param connection the connection
+ * @param http_string the pointer to HTTP version string
+ * @param len the length of @a http_string in bytes
+ * @return #MHD_YES if HTTP version is correct and supported,
+ *         #MHD_NO if HTTP version is not correct or unsupported.
+ */
+static enum MHD_Result
+parse_http_version (struct MHD_Connection *connection,
+                    const char*http_string,
+                    size_t len)
+{
+  const char *const h = http_string; /**< short alias */
+  mhd_assert (NULL != http_string);
+
+  /* String must starts with 'HTTP/d.d', case-sensetive match.
+   * See https://datatracker.ietf.org/doc/html/rfc7230#section-2.6 */
+  if ((len != 8) ||
+      (h[0] != 'H') || (h[1] != 'T') || (h[2] != 'T') || (h[3] != 'P') ||
+      (h[4] != '/')
+      || (h[6] != '.') ||
+      ((h[5] < '0') || (h[5] > '9')) ||
+      ((h[7] < '0') || (h[7] > '9')))
+  {
+    connection->http_ver = MHD_HTTP_VER_INVALID;
+    transmit_error_response (connection,
+                             MHD_HTTP_BAD_REQUEST,
+                             REQUEST_MALFORMED);
+    return MHD_NO;
+  }
+  if (1 == h[5] - '0')
+  {
+    /* HTTP/1.x */
+    if (1 == h[7] - '0')
+      connection->http_ver = MHD_HTTP_VER_1_1;
+    else if (0 == h[7] - '0')
+      connection->http_ver = MHD_HTTP_VER_1_0;
+    else
+      connection->http_ver = MHD_HTTP_VER_1_2__1_9;
+
+    return MHD_YES;
+  }
+
+  if (0 == h[5] - '0')
+  {
+    /* Too old major version */
+    connection->http_ver = MHD_HTTP_VER_TOO_OLD;
+    transmit_error_response (connection,
+                             MHD_HTTP_HTTP_VERSION_NOT_SUPPORTED,
+                             REQ_HTTP_VER_IS_TOO_OLD);
+    return MHD_NO;
+  }
+
+  connection->http_ver = MHD_HTTP_VER_FUTURE;
+  transmit_error_response (connection,
+                           MHD_HTTP_HTTP_VERSION_NOT_SUPPORTED,
+                           REQ_HTTP_VER_IS_NOT_SUPPORTED);
+  return MHD_NO;
+}
+
+
 /**
  * Parse the first line of the HTTP HEADER.
  *
@@ -2126,6 +2209,8 @@ parse_initial_message_line (struct MHD_Connection 
*connection,
     uri = NULL;
     connection->version = "";
     args = NULL;
+    if (MHD_NO == parse_http_version (connection, connection->version, 0))
+      return MHD_NO;
   }
   else
   {
@@ -2146,11 +2231,17 @@ parse_initial_message_line (struct MHD_Connection 
*connection,
       /* http_version points to character before HTTP version string */
       http_version[0] = '\0';
       connection->version = http_version + 1;
+      if (MHD_NO == parse_http_version (connection, connection->version,
+                                        line_len
+                                        - (connection->version - line)))
+        return MHD_NO;
       uri_len = http_version - uri;
     }
     else
     {
       connection->version = "";
+      if (MHD_NO == parse_http_version (connection, connection->version, 0))
+        return MHD_NO;
       uri_len = line_len - (uri - line);
     }
     /* check for spaces in URI if we are "strict" */
@@ -3756,6 +3847,7 @@ MHD_connection_handle_idle (struct MHD_Connection 
*connection)
         /* can try to keep-alive */
 
         connection->version = NULL;
+        connection->http_ver = MHD_HTTP_VER_UNKNOWN;
         connection->state = MHD_CONNECTION_INIT;
         connection->last = NULL;
         connection->colon = NULL;
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 346001c3..e684aa88 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -732,6 +732,59 @@ enum MHD_ConnKeepAlive
   MHD_CONN_USE_KEEPALIVE = 1
 };
 
+enum MHD_HTTP_version
+{
+  /**
+   * Not a HTTP protocol or HTTP version is invalid.
+   */
+  MHD_HTTP_VER_INVALID = -1,
+
+  /**
+   * HTTP version is not yet received from the client.
+   */
+  MHD_HTTP_VER_UNKNOWN = 0,
+
+  /**
+   * HTTP version before 1.0, unsupported.
+   */
+  MHD_HTTP_VER_TOO_OLD = 1,
+
+  /**
+   * HTTP version 1.0
+   */
+  MHD_HTTP_VER_1_0 = 2,
+
+  /**
+   * HTTP version 1.1
+   */
+  MHD_HTTP_VER_1_1 = 3,
+
+  /**
+   * HTTP version 1.2-1.9, must be used as 1.1
+   */
+  MHD_HTTP_VER_1_2__1_9 = 4,
+
+  /**
+   * HTTP future version. Unsupported.
+   * Reserved, not really detected.
+   */
+  MHD_HTTP_VER_FUTURE = 100
+};
+
+/**
+ * Returns boolean 'true' if HTTP version is supported by MHD
+ */
+#define MHD_IS_HTTP_VER_SUPPORTED(ver) (MHD_HTTP_VER_1_0 <= (ver) && \
+    MHD_HTTP_VER_1_2__1_9 >= (ver))
+
+/**
+ * Protocol should be used as HTTP/1.1 protocol.
+ *
+ * See the last paragraph of
+ * https://datatracker.ietf.org/doc/html/rfc7230#section-2.6
+ */
+#define MHD_IS_HTTP_VER_1_1_COMPAT(ver) (MHD_HTTP_VER_1_1 == (ver) || \
+    MHD_HTTP_VER_1_2__1_9 == (ver))
 
 /**
  * State kept for each HTTP request.
@@ -839,6 +892,11 @@ struct MHD_Connection
    */
   char *version;
 
+  /**
+   * HTTP protocol version as enum.
+   */
+  enum MHD_HTTP_version http_ver;
+
   /**
    * Close connection after sending response?
    * Functions may change value from "Unknown" or "KeepAlive" to "Must close",

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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