diff options
Diffstat (limited to 'server/protocol.c')
-rw-r--r-- | server/protocol.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/server/protocol.c b/server/protocol.c index a0b32464..bf915a0a 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -997,6 +997,8 @@ request_rec *ap_read_request(conn_rec *conn) } if (!r->assbackwards) { + const char *tenc; + ap_get_mime_headers_core(r, tmp_bb); if (r->status != HTTP_OK) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00567) @@ -1008,12 +1010,34 @@ request_rec *ap_read_request(conn_rec *conn) goto traceout; } - if (apr_table_get(r->headers_in, "Transfer-Encoding") - && apr_table_get(r->headers_in, "Content-Length")) { - /* 2616 section 4.4, point 3: "if both Transfer-Encoding - * and Content-Length are received, the latter MUST be - * ignored"; so unset it here to prevent any confusion - * later. */ + tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); + if (tenc) { + /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23 + * Section 3.3.3.3: "If a Transfer-Encoding header field is + * present in a request and the chunked transfer coding is not + * the final encoding ...; the server MUST respond with the 400 + * (Bad Request) status code and then close the connection". + */ + if (!(strcasecmp(tenc, "chunked") == 0 /* fast path */ + || ap_find_last_token(r->pool, tenc, "chunked"))) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02539) + "client sent unknown Transfer-Encoding " + "(%s): %s", tenc, r->uri); + r->status = HTTP_BAD_REQUEST; + conn->keepalive = AP_CONN_CLOSE; + ap_send_error_response(r, 0); + ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); + ap_run_log_transaction(r); + apr_brigade_destroy(tmp_bb); + goto traceout; + } + + /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23 + * Section 3.3.3.3: "If a message is received with both a + * Transfer-Encoding and a Content-Length header field, the + * Transfer-Encoding overrides the Content-Length. ... A sender + * MUST remove the received Content-Length field". + */ apr_table_unset(r->headers_in, "Content-Length"); } } @@ -1557,7 +1581,8 @@ struct ap_vrprintf_data { char *buff; }; -static apr_status_t r_flush(apr_vformatter_buff_t *buff) +/* Flush callback for apr_vformatter; returns -1 on error. */ +static int r_flush(apr_vformatter_buff_t *buff) { /* callback function passed to ap_vformatter to be called when * vformatter needs to write into buff and buff.curpos > buff.endpos */ @@ -1578,7 +1603,7 @@ static apr_status_t r_flush(apr_vformatter_buff_t *buff) vd->vbuff.curpos = vd->buff; vd->vbuff.endpos = vd->buff + AP_IOBUFSIZE; - return APR_SUCCESS; + return 0; } AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va) |