Skip to content
Snippets Groups Projects
Commit a952abb9 authored by David M. Lee's avatar David M. Lee
Browse files

http: Properly reject requests with Transfer-Encoding set

Asterisk does not support any of the transfer encodings specified in
HTTP/1.1, other than the default "identity" encoding.

According to RFC 2616:

   A server which receives an entity-body with a transfer-coding it does
   not understand SHOULD return 501 (Unimplemented), and close the
   connection. A server MUST NOT send transfer-codings to an HTTP/1.0
   client.

This patch adds the 501 Unimplemented response, instead of the hard work
of actually implementing other recordings.

This behavior is especially problematic for Node.js clients, which use
chunked encoding by default.

(closes issue ASTERISK-22486)
Review: https://reviewboard.asterisk.org/r/3092/
........

Merged revisions 404565 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404567 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent c3d5c41d
No related branches found
No related tags found
No related merge requests found
......@@ -608,6 +608,27 @@ void ast_http_uri_unlink_all_with_key(const char *key)
#define MAX_POST_CONTENT 1025
/*!
* \brief Retrieves the header with the given field name.
*
* \param headers Headers to search.
* \param field_name Name of the header to find.
* \return Associated header value.
* \return \c NULL if header is not present.
*/
static const char *get_header(struct ast_variable *headers,
const char *field_name)
{
struct ast_variable *v;
for (v = headers; v; v = v->next) {
if (!strcasecmp(v->name, field_name)) {
return v->value;
}
}
return NULL;
}
/*!
* \brief Retrieves the content type specified in the "Content-Type" header.
*
......@@ -620,32 +641,51 @@ void ast_http_uri_unlink_all_with_key(const char *key)
*/
static char *get_content_type(struct ast_variable *headers)
{
struct ast_variable *v;
const char *content_type = get_header(headers, "Content-Type");
const char *param;
size_t size;
for (v = headers; v; v = v->next) {
if (strcasecmp(v->name, "Content-Type") == 0) {
const char *param = strchr(v->value, ';');
size_t size = (param ? param - v->value :
strlen(v->value)) + 1;
return ast_strndup(v->value, size);
}
if (!content_type) {
return NULL;
}
return NULL;
param = strchr(content_type, ';');
size = param ? param - content_type : strlen(content_type);
return ast_strndup(content_type, size);
}
/*!
* \brief Returns the value of the Content-Length header.
*
* \param headers HTTP headers.
* \return Value of the Content-Length header.
* \return 0 if header is not present, or is invalid.
*/
static int get_content_length(struct ast_variable *headers)
{
struct ast_variable *v;
const char *content_length = get_header(headers, "Content-Length");
for (v = headers; v; v = v->next) {
if (!strcasecmp(v->name, "Content-Length")) {
return atoi(v->value);
}
if (!content_length) {
/* Missing content length; assume zero */
return 0;
}
/* Missing content length; assume zero */
return 0;
/* atoi() will return 0 for invalid inputs, which is good enough for
* the HTTP parsing. */
return atoi(content_length);
}
/*!
* \brief Returns the value of the Transfer-Encoding header.
*
* \param headers HTTP headers.
* \return Value of the Transfer-Encoding header.
* \return 0 if header is not present, or is invalid.
*/
static const char *get_transfer_encoding(struct ast_variable *headers)
{
return get_header(headers, "Transfer-Encoding");
}
struct ast_json *ast_http_get_json(
......@@ -1068,6 +1108,7 @@ static void *httpd_helper_thread(void *data)
struct ast_variable *tail = headers;
char *uri, *method;
enum ast_http_method http_method = AST_HTTP_UNKNOWN;
const char *transfer_encoding;
if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
goto done;
......@@ -1140,6 +1181,22 @@ static void *httpd_helper_thread(void *data)
}
}
transfer_encoding = get_transfer_encoding(headers);
/* Transfer encoding defaults to identity */
if (!transfer_encoding) {
transfer_encoding = "identity";
}
/*
* RFC 2616, section 3.6, we should respond with a 501 for any transfer-
* codings we don't understand.
*/
if (strcasecmp(transfer_encoding, "identity") != 0) {
/* Transfer encodings not supported */
ast_http_error(ser, 501, "Unimplemented", "Unsupported Transfer-Encoding.");
goto done;
}
if (!*uri) {
ast_http_error(ser, 400, "Bad Request", "Invalid Request");
goto done;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment