diff options
-rw-r--r-- | main/http.c | 21 | ||||
-rw-r--r-- | main/manager.c | 14 | ||||
-rw-r--r-- | res/res_ari.c | 41 |
3 files changed, 67 insertions, 9 deletions
diff --git a/main/http.c b/main/http.c index e687d037c..a9c8a3564 100644 --- a/main/http.c +++ b/main/http.c @@ -616,9 +616,13 @@ struct ast_variable *ast_http_get_post_vars( { int content_length = 0; struct ast_variable *v, *post_vars=NULL, *prev = NULL; - char *buf, *var, *val; + char *var, *val; + RAII_VAR(char *, buf, NULL, ast_free_ptr); int res; + /* Use errno to distinguish errors from no params */ + errno = 0; + for (v = headers; v; v = v->next) { if (!strcasecmp(v->name, "Content-Type")) { if (strcasecmp(v->value, "application/x-www-form-urlencoded")) { @@ -640,22 +644,25 @@ struct ast_variable *ast_http_get_post_vars( } if (content_length > MAX_POST_CONTENT - 1) { - ast_log(LOG_WARNING, "Excessively long HTTP content. %d is greater than our max of %d\n", - content_length, MAX_POST_CONTENT); - ast_http_send(ser, AST_HTTP_POST, 413, "Request Entity Too Large", NULL, NULL, 0, 0); + ast_log(LOG_WARNING, + "Excessively long HTTP content. (%d > %d)\n", + content_length, MAX_POST_CONTENT); + errno = EFBIG; return NULL; } buf = ast_malloc(content_length + 1); if (!buf) { + /* malloc sets errno to ENOMEM */ return NULL; } res = fread(buf, 1, content_length, ser->f); if (res < content_length) { /* Error, distinguishable by ferror() or feof(), but neither - * is good. */ - goto done; + * is good. Treat either one as I/O error */ + errno = EIO; + return NULL; } buf[content_length] = '\0'; @@ -677,8 +684,6 @@ struct ast_variable *ast_http_get_post_vars( } } -done: - ast_free(buf); return post_vars; } diff --git a/main/manager.c b/main/manager.c index a531feb80..01cc75474 100644 --- a/main/manager.c +++ b/main/manager.c @@ -6723,6 +6723,20 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser, params = ast_http_get_post_vars(ser, headers); } + if (!params) { + switch (errno) { + case EFBIG: + ast_http_send(ser, AST_HTTP_POST, 413, "Request Entity Too Large", NULL, NULL, 0, 0); + break; + case ENOMEM: + ast_http_send(ser, AST_HTTP_POST, 500, "Internal Server Error", NULL, NULL, 0, 0); + break; + case EIO: + ast_http_send(ser, AST_HTTP_POST, 400, "Bad Request", NULL, NULL, 0, 0); + break; + } + } + for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { hdrlen = strlen(v->name) + strlen(v->value) + 3; m.headers[m.hdrcount] = ast_malloc(hdrlen); diff --git a/res/res_ari.c b/res/res_ari.c index d666d8d57..4ceb3847e 100644 --- a/res/res_ari.c +++ b/res/res_ari.c @@ -844,6 +844,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup); struct ast_ari_response response = {}; int ret = 0; + RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy); if (!response_headers || !response_body) { return -1; @@ -861,8 +862,46 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, process_cors_request(headers, &response); + /* Process form data from a POST. It could be mixed with query + * parameters, which seems a bit odd. But it's allowed, so that's okay + * with us. + */ + post_vars = ast_http_get_post_vars(ser, headers); + if (get_params == NULL) { + switch (errno) { + case EFBIG: + ast_ari_response_error(&response, 413, + "Request Entity Too Large", + "Request body too large"); + break; + case ENOMEM: + ast_ari_response_error(&response, 500, + "Internal Server Error", + "Error processing request"); + break; + case EIO: + ast_ari_response_error(&response, 400, + "Bad Request", "Error parsing request body"); + break; + } + get_params = post_vars; + } else if (get_params && post_vars) { + /* Has both post_vars and get_params */ + struct ast_variable *last_var = post_vars; + while (last_var->next) { + last_var = last_var->next; + } + /* The duped get_params will get freed when post_vars gets + * ast_variables_destroyed. + */ + last_var->next = ast_variables_dup(get_params); + get_params = post_vars; + } + user = authenticate_user(get_params, headers); - if (!user) { + if (response.response_code > 0) { + /* POST parameter processing error. Do nothing. */ + } else if (!user) { /* Per RFC 2617, section 1.2: The 401 (Unauthorized) response * message is used by an origin server to challenge the * authorization of a user agent. This response MUST include a |