mod_proxy_uwsgi: Stricter backend HTTP response parsing/validation

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1907980 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yann Ylavic
2023-03-02 15:10:30 +00:00
parent be5fb2ef25
commit 0df5879df8
2 changed files with 37 additions and 14 deletions

View File

@ -0,0 +1,2 @@
*) mod_proxy_uwsgi: Stricter backend HTTP response parsing/validation.
[Yann Ylavic]

View File

@ -313,18 +313,16 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
len = ap_getline(buffer, sizeof(buffer), rp, 1);
if (len <= 0) {
/* oops */
/* invalid or empty */
return HTTP_INTERNAL_SERVER_ERROR;
}
backend->worker->s->read += len;
if (len >= sizeof(buffer) - 1) {
/* oops */
if ((apr_size_t)len >= sizeof(buffer)) {
/* too long */
return HTTP_INTERNAL_SERVER_ERROR;
}
/* Position of http status code */
if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
status_start = 9;
@ -333,8 +331,8 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
status_start = 7;
}
else {
/* oops */
return HTTP_INTERNAL_SERVER_ERROR;
/* not HTTP */
return HTTP_BAD_GATEWAY;
}
status_end = status_start + 3;
@ -354,21 +352,44 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
}
r->status_line = apr_pstrdup(r->pool, &buffer[status_start]);
/* start parsing headers */
/* parse headers */
while ((len = ap_getline(buffer, sizeof(buffer), rp, 1)) > 0) {
if ((apr_size_t)len >= sizeof(buffer)) {
/* too long */
len = -1;
break;
}
value = strchr(buffer, ':');
/* invalid header skip */
if (!value)
continue;
*value = '\0';
++value;
if (!value) {
/* invalid header */
len = -1;
break;
}
*value++ = '\0';
if (*ap_scan_http_token(buffer)) {
/* invalid name */
len = -1;
break;
}
while (apr_isspace(*value))
++value;
for (end = &value[strlen(value) - 1];
end > value && apr_isspace(*end); --end)
*end = '\0';
if (*ap_scan_http_field_content(value)) {
/* invalid value */
len = -1;
break;
}
apr_table_add(r->headers_out, buffer, value);
}
if (len < 0) {
/* Reset headers, but not to NULL because things below the chain expect
* this to be non NULL e.g. the ap_content_length_filter.
*/
r->headers_out = apr_table_make(r->pool, 1);
return HTTP_BAD_GATEWAY;
}
if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
ap_set_content_type(r, apr_pstrdup(r->pool, buf));