mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(esp_http_server): reject Transfer-Encoding requests with 501
This commit is contained in:
@@ -689,8 +689,10 @@ typedef enum {
|
|||||||
* guaranteed as the HTTP request may be partially received/parsed.
|
* guaranteed as the HTTP request may be partially received/parsed.
|
||||||
* - The function must return ESP_OK if underlying socket needs to
|
* - The function must return ESP_OK if underlying socket needs to
|
||||||
* be kept open. Any other value will ensure that the socket is
|
* be kept open. Any other value will ensure that the socket is
|
||||||
* closed. The return value is ignored when error is of type
|
* closed. The return value is ignored, and the socket is closed
|
||||||
* `HTTPD_500_INTERNAL_SERVER_ERROR` and the socket closed anyway.
|
* anyway, when the error is `HTTPD_500_INTERNAL_SERVER_ERROR` or
|
||||||
|
* `HTTPD_501_METHOD_NOT_IMPLEMENTED` (for 501 the request is only
|
||||||
|
* partially parsed, so the session cannot continue safely).
|
||||||
*
|
*
|
||||||
* @param[in] req HTTP request for which the error needs to be handled
|
* @param[in] req HTTP request for which the error needs to be handled
|
||||||
* @param[in] error Error type
|
* @param[in] error Error type
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ typedef struct {
|
|||||||
size_t raw_datalen; /*!< Full length of the raw data in scratch buffer */
|
size_t raw_datalen; /*!< Full length of the raw data in scratch buffer */
|
||||||
} parser_data_t;
|
} parser_data_t;
|
||||||
|
|
||||||
|
static const char *httpd_find_hdr_value(struct httpd_req_aux *ra, const char *field);
|
||||||
|
|
||||||
static esp_err_t verify_url (http_parser *parser)
|
static esp_err_t verify_url (http_parser *parser)
|
||||||
{
|
{
|
||||||
parser_data_t *parser_data = (parser_data_t *) parser->data;
|
parser_data_t *parser_data = (parser_data_t *) parser->data;
|
||||||
@@ -372,6 +374,21 @@ static esp_err_t cb_headers_complete(http_parser *parser)
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This server implements no transfer codings, so reject any request that
|
||||||
|
* carries a Transfer-Encoding header with 501 (RFC 9112 section 6.1).
|
||||||
|
* Without this check a chunked body is treated as an empty body and its
|
||||||
|
* chunk framing is parsed as a separate pipelined request, which is a
|
||||||
|
* request-smuggling primitive when the server sits behind a proxy. The
|
||||||
|
* header-presence check also covers codings that http_parser does not
|
||||||
|
* flag as chunked (e.g. "gzip, chunked"). */
|
||||||
|
if ((parser->flags & F_CHUNKED) ||
|
||||||
|
httpd_find_hdr_value(ra, "Transfer-Encoding") != NULL) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("Transfer-Encoding is not supported"));
|
||||||
|
parser_data->error = HTTPD_501_METHOD_NOT_IMPLEMENTED;
|
||||||
|
parser_data->status = PARSING_FAILED;
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* In absence of body/chunked encoding, http_parser sets content_len to ULLONG_MAX */
|
/* In absence of body/chunked encoding, http_parser sets content_len to ULLONG_MAX */
|
||||||
if (parser->content_length != ULLONG_MAX) {
|
if (parser->content_length != ULLONG_MAX) {
|
||||||
/* Content-Length was specified. Reject any value above UINT32_MAX: it is
|
/* Content-Length was specified. Reject any value above UINT32_MAX: it is
|
||||||
|
|||||||
@@ -603,9 +603,16 @@ esp_err_t httpd_req_handle_err(httpd_req_t *req, httpd_err_code_t error)
|
|||||||
if (hd->err_handler_fns[error]) {
|
if (hd->err_handler_fns[error]) {
|
||||||
ret = hd->err_handler_fns[error](req, error);
|
ret = hd->err_handler_fns[error](req, error);
|
||||||
|
|
||||||
/* If error code is 500, force return failure
|
/* Force failure irrespective of the handler's return value for
|
||||||
* irrespective of the handler's return value */
|
* errors after which the session cannot continue safely: 500
|
||||||
ret = (error == HTTPD_500_INTERNAL_SERVER_ERROR ? ESP_FAIL : ret);
|
* (internal state is broken) and 501 (parsing aborted mid-request,
|
||||||
|
* so the position of the next request in the byte stream is
|
||||||
|
* unknown and keep-alive would let leftover bytes be parsed and
|
||||||
|
* answered as a further request). */
|
||||||
|
if (error == HTTPD_500_INTERNAL_SERVER_ERROR ||
|
||||||
|
error == HTTPD_501_METHOD_NOT_IMPLEMENTED) {
|
||||||
|
ret = ESP_FAIL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If no handler is registered for this error default
|
/* If no handler is registered for this error default
|
||||||
* behavior is to send the HTTP error response and
|
* behavior is to send the HTTP error response and
|
||||||
|
|||||||
Reference in New Issue
Block a user