[core] act as transparent proxy after con Upgrade

personal/stbuehler/mod-csrf
Glenn Strauss 2017-05-06 01:23:37 -04:00
parent 28851b2cdf
commit e685ef70f1
6 changed files with 51 additions and 9 deletions

View File

@ -131,6 +131,7 @@ typedef union {
#define HTTP_TRANSFER_ENCODING BV(5)
#define HTTP_CONTENT_LOCATION BV(6)
#define HTTP_SET_COOKIE BV(7)
#define HTTP_UPGRADE BV(8)
typedef struct {
/** HEADER */

View File

@ -264,6 +264,19 @@ static handler_t connection_handle_read_post_chunked(server *srv, connection *co
return HANDLER_GO_ON;
}
static handler_t connection_handle_read_body_unknown(server *srv, connection *con, chunkqueue *cq, chunkqueue *dst_cq) {
/* con->conf.max_request_size is in kBytes */
const off_t max_request_size = (off_t)con->conf.max_request_size << 10;
chunkqueue_append_chunkqueue(dst_cq, cq);
if (0 != max_request_size && dst_cq->bytes_in > max_request_size) {
log_error_write(srv, __FILE__, __LINE__, "sos",
"request-size too long:", dst_cq->bytes_in, "-> 413");
/* 413 Payload Too Large */
return connection_handle_read_post_error(srv, con, 413);
}
return HANDLER_GO_ON;
}
static off_t connection_write_throttle(server *srv, connection *con, off_t max_bytes) {
UNUSED(srv);
if (con->conf.global_kbytes_per_second) {
@ -423,8 +436,11 @@ handler_t connection_handle_read_post_state(server *srv, connection *con) {
}
}
if (-1 == con->request.content_length) { /*(Transfer-Encoding: chunked)*/
handler_t rc = connection_handle_read_post_chunked(srv, con, cq, dst_cq);
if (con->request.content_length < 0) {
/*(-1: Transfer-Encoding: chunked, -2: unspecified length)*/
handler_t rc = (-1 == con->request.content_length)
? connection_handle_read_post_chunked(srv, con, cq, dst_cq)
: connection_handle_read_body_unknown(srv, con, cq, dst_cq);
if (HANDLER_GO_ON != rc) return rc;
}
else if (con->request.content_length <= 64*1024) {

View File

@ -420,9 +420,10 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
* to get keep-alive we either need:
* - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or
* - Transfer-Encoding: chunked (HTTP/1.1)
* - Upgrade: ... (lighttpd then acts as transparent proxy)
*/
if (!(con->parsed_response & (HTTP_CONTENT_LENGTH|HTTP_TRANSFER_ENCODING))) {
if (!(con->parsed_response & (HTTP_CONTENT_LENGTH|HTTP_TRANSFER_ENCODING|HTTP_UPGRADE))) {
if (con->request.http_version == HTTP_VERSION_1_1) {
off_t qlen = chunkqueue_length(con->write_queue);
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;

View File

@ -906,6 +906,21 @@ void http_response_backend_done (server *srv, connection *con) {
}
void http_response_upgrade_read_body_unknown(server *srv, connection *con) {
/* act as transparent proxy */
UNUSED(srv);
if (!(con->conf.stream_request_body & FDEVENT_STREAM_REQUEST))
con->conf.stream_request_body |=
(FDEVENT_STREAM_REQUEST_BUFMIN | FDEVENT_STREAM_REQUEST);
if (!(con->conf.stream_response_body & FDEVENT_STREAM_RESPONSE))
con->conf.stream_response_body |=
(FDEVENT_STREAM_RESPONSE_BUFMIN | FDEVENT_STREAM_RESPONSE);
con->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN;
con->request.content_length = -2;
con->keep_alive = 0;
}
static handler_t http_response_process_local_redir(server *srv, connection *con, size_t blen) {
/* [RFC3875] The Common Gateway Interface (CGI) Version 1.1
* [RFC3875] 6.2.2 Local Redirect Response
@ -1071,6 +1086,13 @@ static int http_response_process_headers(server *srv, connection *con, http_resp
continue; /* do not send Status to client */
}
break;
case 7:
if (0 == strncasecmp(key, "Upgrade", key_len)) {
/*(technically, should also verify Connection: upgrade)*/
/*(flag only for mod_proxy (for now))*/
if (opts->backend == BACKEND_PROXY) con->parsed_response |= HTTP_UPGRADE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;

View File

@ -1,6 +1,7 @@
#include "first.h"
#include "response.h"
#include "fdevent.h"
#include "keyvalue.h"
#include "log.h"
#include "stat_cache.h"
@ -46,12 +47,12 @@ int http_response_write_header(server *srv, connection *con) {
con->keep_alive_idle = con->conf.max_keep_alive_idle;
}
if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
if (con->keep_alive) {
response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
} else {
response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
}
if ((con->parsed_response & HTTP_UPGRADE) && con->request.http_version == HTTP_VERSION_1_1) {
response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("upgrade"));
} else if (0 == con->keep_alive) {
response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
} else if (con->request.http_version == HTTP_VERSION_1_0) {/*(&& con->keep_alive != 0)*/
response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
}
/* add all headers */

View File

@ -50,6 +50,7 @@ int http_response_handle_cachable(server *srv, connection *con, buffer * mtime);
void http_response_send_file (server *srv, connection *con, buffer *path);
void http_response_backend_done (server *srv, connection *con);
void http_response_backend_error (server *srv, connection *con);
void http_response_upgrade_read_body_unknown(server *srv, connection *con);
buffer * strftime_cache_get(server *srv, time_t last_mod);
#endif