summaryrefslogtreecommitdiff
path: root/main/http.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-03-10 17:21:01 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-03-10 17:21:01 +0000
commit7c854d65afd3a969bdbd9b3a521cff1fad5809c2 (patch)
tree228ee704edec9612ce0d36cb255d52ac248209cf /main/http.c
parentef69b5176daa82ba7edc09216fe0594e008098e0 (diff)
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 ........ Merged revisions 410383 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410395 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/http.c')
-rw-r--r--main/http.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/main/http.c b/main/http.c
index e867de13a..0e45b60db 100644
--- a/main/http.c
+++ b/main/http.c
@@ -197,9 +197,7 @@ uint32_t ast_http_manid_from_vars(struct ast_variable *headers)
break;
}
}
- if (cookies) {
- ast_variables_destroy(cookies);
- }
+ ast_variables_destroy(cookies);
return mngid;
}
@@ -1083,12 +1081,13 @@ static int ssl_close(void *cookie)
}*/
#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 @@ static struct ast_variable *parse_cookies(char *cookies)
/* 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 @@ struct ast_http_auth *ast_http_get_auth(struct ast_variable *headers)
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 @@ static void *httpd_helper_thread(void *data)
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 @@ static void *httpd_helper_thread(void *data)
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,6 +1302,11 @@ static void *httpd_helper_thread(void *data)
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;
@@ -1306,6 +1314,17 @@ static void *httpd_helper_thread(void *data)
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;
+ }
}
transfer_encoding = get_transfer_encoding(headers);
@@ -1325,20 +1344,13 @@ static void *httpd_helper_thread(void *data)
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);