[asterisk-commits] rmudgett: branch 12 r410383 - in /branches/12: ./ main/http.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 10 12:16:42 CDT 2014


Author: rmudgett
Date: Mon Mar 10 12:16:38 2014
New Revision: 410383

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410383
Log:
AST-2014-001: Stack overflow in HTTP processing of Cookie headers.

Sending a HTTP request that is handled by Asterisk with a large number of
Cookie headers could overflow the stack.

Another vulnerability along similar lines is any HTTP request with a
ridiculous number of headers in the request could exhaust system memory.

(closes issue ASTERISK-23340)
Reported by: Lucas Molas, researcher at Programa STIC, Fundacion; and Dr. Manuel Sadosky, Buenos Aires, Argentina
........

Merged revisions 410380 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 410381 from http://svn.asterisk.org/svn/asterisk/branches/11

Modified:
    branches/12/   (props changed)
    branches/12/main/http.c

Propchange: branches/12/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Modified: branches/12/main/http.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/http.c?view=diff&rev=410383&r1=410382&r2=410383
==============================================================================
--- branches/12/main/http.c (original)
+++ branches/12/main/http.c Mon Mar 10 12:16:38 2014
@@ -197,9 +197,7 @@
 			break;
 		}
 	}
-	if (cookies) {
-		ast_variables_destroy(cookies);
-	}
+	ast_variables_destroy(cookies);
 	return mngid;
 }
 
@@ -1083,12 +1081,13 @@
 }*/
 #endif	/* DO_SSL */
 
-static struct ast_variable *parse_cookies(char *cookies)
-{
+static struct ast_variable *parse_cookies(const char *cookies)
+{
+	char *parse = ast_strdupa(cookies);
 	char *cur;
 	struct ast_variable *vars = NULL, *var;
 
-	while ((cur = strsep(&cookies, ";"))) {
+	while ((cur = strsep(&parse, ";"))) {
 		char *name, *val;
 
 		name = val = cur;
@@ -1118,16 +1117,12 @@
 /* get cookie from Request headers */
 struct ast_variable *ast_http_get_cookies(struct ast_variable *headers)
 {
-	struct ast_variable *v, *cookies=NULL;
+	struct ast_variable *v, *cookies = NULL;
 
 	for (v = headers; v; v = v->next) {
 		if (!strcasecmp(v->name, "Cookie")) {
-			char *tmp = ast_strdupa(v->value);
-			if (cookies) {
-				ast_variables_destroy(cookies);
-			}
-
-			cookies = parse_cookies(tmp);
+			ast_variables_destroy(cookies);
+			cookies = parse_cookies(v->value);
 		}
 	}
 	return cookies;
@@ -1226,6 +1221,9 @@
 	return NULL;
 }
 
+/*! Limit the number of request headers in case the sender is being ridiculous. */
+#define MAX_HTTP_REQUEST_HEADERS	100
+
 static void *httpd_helper_thread(void *data)
 {
 	char buf[4096];
@@ -1236,6 +1234,7 @@
 	char *uri, *method;
 	enum ast_http_method http_method = AST_HTTP_UNKNOWN;
 	const char *transfer_encoding;
+	int remaining_headers;
 
 	if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
 		goto done;
@@ -1274,9 +1273,13 @@
 		if (*c) {
 			*c = '\0';
 		}
+	} else {
+		ast_http_error(ser, 400, "Bad Request", "Invalid Request");
+		goto done;
 	}
 
 	/* process "Request Headers" lines */
+	remaining_headers = MAX_HTTP_REQUEST_HEADERS;
 	while (fgets(header_line, sizeof(header_line), ser->f)) {
 		char *name, *value;
 
@@ -1299,12 +1302,28 @@
 
 		ast_trim_blanks(name);
 
+		if (!remaining_headers--) {
+			/* Too many headers. */
+			ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
+			goto done;
+		}
 		if (!headers) {
 			headers = ast_variable_new(name, value, __FILE__);
 			tail = headers;
 		} else {
 			tail->next = ast_variable_new(name, value, __FILE__);
 			tail = tail->next;
+		}
+		if (!tail) {
+			/*
+			 * Variable allocation failure.
+			 * Try to make some room.
+			 */
+			ast_variables_destroy(headers);
+			headers = NULL;
+
+			ast_http_error(ser, 500, "Server Error", "Out of memory");
+			goto done;
 		}
 	}
 
@@ -1325,20 +1344,13 @@
 		goto done;
 	}
 
-	if (!*uri) {
-		ast_http_error(ser, 400, "Bad Request", "Invalid Request");
-		goto done;
-	}
-
 	handle_uri(ser, uri, http_method, headers);
 
 done:
 	ast_atomic_fetchadd_int(&session_count, -1);
 
 	/* clean up all the header information */
-	if (headers) {
-		ast_variables_destroy(headers);
-	}
+	ast_variables_destroy(headers);
 
 	if (ser->f) {
 		fclose(ser->f);




More information about the asterisk-commits mailing list