mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-18 15:49:56 +00:00
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@410381 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
49
main/http.c
49
main/http.c
@@ -186,9 +186,7 @@ uint32_t ast_http_manid_from_vars(struct ast_variable *headers)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cookies) {
|
ast_variables_destroy(cookies);
|
||||||
ast_variables_destroy(cookies);
|
|
||||||
}
|
|
||||||
return mngid;
|
return mngid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,12 +803,13 @@ static int ssl_close(void *cookie)
|
|||||||
}*/
|
}*/
|
||||||
#endif /* DO_SSL */
|
#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;
|
char *cur;
|
||||||
struct ast_variable *vars = NULL, *var;
|
struct ast_variable *vars = NULL, *var;
|
||||||
|
|
||||||
while ((cur = strsep(&cookies, ";"))) {
|
while ((cur = strsep(&parse, ";"))) {
|
||||||
char *name, *val;
|
char *name, *val;
|
||||||
|
|
||||||
name = val = cur;
|
name = val = cur;
|
||||||
@@ -840,21 +839,19 @@ static struct ast_variable *parse_cookies(char *cookies)
|
|||||||
/* get cookie from Request headers */
|
/* get cookie from Request headers */
|
||||||
struct ast_variable *ast_http_get_cookies(struct ast_variable *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) {
|
for (v = headers; v; v = v->next) {
|
||||||
if (!strcasecmp(v->name, "Cookie")) {
|
if (!strcasecmp(v->name, "Cookie")) {
|
||||||
char *tmp = ast_strdupa(v->value);
|
ast_variables_destroy(cookies);
|
||||||
if (cookies) {
|
cookies = parse_cookies(v->value);
|
||||||
ast_variables_destroy(cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
cookies = parse_cookies(tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cookies;
|
return cookies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! 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)
|
static void *httpd_helper_thread(void *data)
|
||||||
{
|
{
|
||||||
@@ -865,6 +862,7 @@ static void *httpd_helper_thread(void *data)
|
|||||||
struct ast_variable *tail = headers;
|
struct ast_variable *tail = headers;
|
||||||
char *uri, *method;
|
char *uri, *method;
|
||||||
enum ast_http_method http_method = AST_HTTP_UNKNOWN;
|
enum ast_http_method http_method = AST_HTTP_UNKNOWN;
|
||||||
|
int remaining_headers;
|
||||||
|
|
||||||
if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
|
if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
|
||||||
goto done;
|
goto done;
|
||||||
@@ -899,9 +897,13 @@ static void *httpd_helper_thread(void *data)
|
|||||||
if (*c) {
|
if (*c) {
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ast_http_error(ser, 400, "Bad Request", "Invalid Request");
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process "Request Headers" lines */
|
/* process "Request Headers" lines */
|
||||||
|
remaining_headers = MAX_HTTP_REQUEST_HEADERS;
|
||||||
while (fgets(header_line, sizeof(header_line), ser->f)) {
|
while (fgets(header_line, sizeof(header_line), ser->f)) {
|
||||||
char *name, *value;
|
char *name, *value;
|
||||||
|
|
||||||
@@ -924,6 +926,11 @@ static void *httpd_helper_thread(void *data)
|
|||||||
|
|
||||||
ast_trim_blanks(name);
|
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) {
|
if (!headers) {
|
||||||
headers = ast_variable_new(name, value, __FILE__);
|
headers = ast_variable_new(name, value, __FILE__);
|
||||||
tail = headers;
|
tail = headers;
|
||||||
@@ -931,11 +938,17 @@ static void *httpd_helper_thread(void *data)
|
|||||||
tail->next = ast_variable_new(name, value, __FILE__);
|
tail->next = ast_variable_new(name, value, __FILE__);
|
||||||
tail = tail->next;
|
tail = tail->next;
|
||||||
}
|
}
|
||||||
}
|
if (!tail) {
|
||||||
|
/*
|
||||||
|
* Variable allocation failure.
|
||||||
|
* Try to make some room.
|
||||||
|
*/
|
||||||
|
ast_variables_destroy(headers);
|
||||||
|
headers = NULL;
|
||||||
|
|
||||||
if (!*uri) {
|
ast_http_error(ser, 500, "Server Error", "Out of memory");
|
||||||
ast_http_error(ser, 400, "Bad Request", "Invalid Request");
|
goto done;
|
||||||
goto done;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_uri(ser, uri, http_method, headers);
|
handle_uri(ser, uri, http_method, headers);
|
||||||
@@ -944,9 +957,7 @@ done:
|
|||||||
ast_atomic_fetchadd_int(&session_count, -1);
|
ast_atomic_fetchadd_int(&session_count, -1);
|
||||||
|
|
||||||
/* clean up all the header information */
|
/* clean up all the header information */
|
||||||
if (headers) {
|
ast_variables_destroy(headers);
|
||||||
ast_variables_destroy(headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ser->f) {
|
if (ser->f) {
|
||||||
fclose(ser->f);
|
fclose(ser->f);
|
||||||
|
|||||||
Reference in New Issue
Block a user