[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.