summaryrefslogtreecommitdiff
path: root/server/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/protocol.c')
-rw-r--r--server/protocol.c41
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)