[asterisk-commits] dlee: branch 12 r404565 - /branches/12/main/http.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Dec 24 10:41:38 CST 2013
Author: dlee
Date: Tue Dec 24 10:41:36 2013
New Revision: 404565
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=404565
Log:
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/
Modified:
branches/12/main/http.c
Modified: branches/12/main/http.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/http.c?view=diff&rev=404565&r1=404564&r2=404565
==============================================================================
--- branches/12/main/http.c (original)
+++ branches/12/main/http.c Tue Dec 24 10:41:36 2013
@@ -609,6 +609,27 @@
#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.
*
* This function only returns the "type/subtype" and any trailing parameter is
@@ -620,32 +641,51 @@
*/
static char *get_content_type(struct ast_variable *headers)
{
- struct ast_variable *v;
-
- 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);
- }
- }
-
- return NULL;
-}
-
+ const char *content_type = get_header(headers, "Content-Type");
+ const char *param;
+ size_t size;
+
+ if (!content_type) {
+ 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;
-
- for (v = headers; v; v = v->next) {
- if (!strcasecmp(v->name, "Content-Length")) {
- return atoi(v->value);
- }
- }
-
- /* Missing content length; assume zero */
- return 0;
+ const char *content_length = get_header(headers, "Content-Length");
+
+ if (!content_length) {
+ /* 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 @@
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;
@@ -1138,6 +1179,22 @@
tail->next = ast_variable_new(name, value, __FILE__);
tail = tail->next;
}
+ }
+
+ 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) {
More information about the asterisk-commits
mailing list