[asterisk-commits] dlee: trunk r404567 - in /trunk: ./ main/http.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Dec 24 10:50:50 CST 2013


Author: dlee
Date: Tue Dec 24 10:50:48 2013
New Revision: 404567

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=404567
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/
........

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

Modified:
    trunk/   (props changed)
    trunk/main/http.c

Propchange: trunk/
------------------------------------------------------------------------------
--- branch-12-merged (original)
+++ branch-12-merged Tue Dec 24 10:50:48 2013
@@ -1,1 +1,1 @@
-/branches/12:1-398558,398560-398577,398579-399305,399307-401390,401392-403290,403292-403778,403781-404509,404531,404553
+/branches/12:1-398558,398560-398577,398579-399305,399307-401390,401392-403290,403292-403778,403781-404565

Modified: trunk/main/http.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/http.c?view=diff&rev=404567&r1=404566&r2=404567
==============================================================================
--- trunk/main/http.c (original)
+++ trunk/main/http.c Tue Dec 24 10:50:48 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