summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2018-11-20 16:07:52 +0000
committerrofl0r <retnyg@gmx.net>2018-12-10 19:05:03 +0000
commit7562c073291a4c542e2be82cc5aa332031ee4b29 (patch)
tree8e771a7e5076ca6d9db1ca91e19b518d9ef20edb
parent04f68e21e76047ed8a0747016d7f6f03e070fc59 (diff)
use CONNECT method if request contains upgrade header
this should allow using websockets or other upgraded connections on a standard (non-encrypted) proxified HTTP connection. testcase: $ telnet localhost 8888 GET / HTTP/1.1 Host: echo.websocket.org:80 Upgrade: websocket Connection: Upgrade Origin: http://echo.websocket.org Sec-WebSocket-Key: 5KNqfsPZ9m/BbeRlVpf7MQ== Sec-WebSocket-Version: 13
-rw-r--r--src/reqs.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/reqs.c b/src/reqs.c
index bbdcc74..f356e02 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -87,7 +87,7 @@
* connections. The request line is allocated from the heap, but it must
* be freed in another function.
*/
-static int read_request_line (struct conn_s *connptr)
+static int read_request_line (struct conn_s *connptr, char** lines, size_t* lines_len)
{
ssize_t len;
@@ -101,6 +101,12 @@ retry:
return -1;
}
+ *lines = saferealloc(*lines, *lines_len + len + 1);
+ if(*lines) {
+ strcpy(*lines + *lines_len, connptr->request_line);
+ *lines_len += len;
+ }
+
/*
* Strip the new line and carriage return from the string.
*/
@@ -626,7 +632,7 @@ add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
/*
* Read all the headers from the stream
*/
-static int get_all_headers (int fd, hashmap_t hashofheaders)
+static int get_all_headers (int fd, hashmap_t hashofheaders, char** lines, size_t* lines_len)
{
char *line = NULL;
char *header = NULL;
@@ -646,6 +652,14 @@ static int get_all_headers (int fd, hashmap_t hashofheaders)
return -1;
}
+ if(lines) {
+ *lines = saferealloc(*lines, *lines_len + linelen + 1);
+ if(*lines) {
+ strcpy(*lines + *lines_len, line);
+ *lines_len += linelen;
+ }
+ }
+
/*
* If we received a CR LF or a non-continuation line, then add
* the accumulated header field, if any, to the hashmap, and
@@ -1011,7 +1025,7 @@ retry:
/*
* Get all the headers from the remote server in a big hash
*/
- if (get_all_headers (connptr->server_fd, hashofheaders) < 0) {
+ if (get_all_headers (connptr->server_fd, hashofheaders, NULL, NULL) < 0) {
log_message (LOG_WARNING,
"Could not retrieve all the headers from the remote server.");
hashmap_delete (hashofheaders);
@@ -1543,6 +1557,8 @@ void handle_connection (int fd)
char sock_ipaddr[IP_LENGTH];
char peer_ipaddr[IP_LENGTH];
char peer_string[HOSTNAME_LENGTH];
+ char *lines = NULL;
+ size_t lines_len = 0;
getpeer_information (fd, peer_ipaddr, peer_string);
@@ -1571,7 +1587,7 @@ void handle_connection (int fd)
goto fail;
}
- if (read_request_line (connptr) < 0) {
+ if (read_request_line (connptr, &lines, &lines_len) < 0) {
update_stats (STAT_BADCONN);
indicate_http_error (connptr, 408, "Timeout",
"detail",
@@ -1597,7 +1613,7 @@ void handle_connection (int fd)
/*
* Get all the headers from the client in a big hash.
*/
- if (get_all_headers (connptr->client_fd, hashofheaders) < 0) {
+ if (get_all_headers (connptr->client_fd, hashofheaders, &lines, &lines_len) < 0) {
log_message (LOG_WARNING,
"Could not retrieve all the headers from the client");
indicate_http_error (connptr, 400, "Bad Request",
@@ -1683,6 +1699,11 @@ void handle_connection (int fd)
"file descriptor %d.", request->host,
connptr->server_fd);
+ if(hashmap_search(hashofheaders, "upgrade") > 0) {
+ connptr->connect_method = TRUE;
+ safe_write (connptr->server_fd, lines, lines_len);
+ }
+
if (!connptr->connect_method)
establish_http_connection (connptr, request);
}
@@ -1740,6 +1761,7 @@ fail:
}
done:
+ safefree(lines);
free_request_struct (request);
hashmap_delete (hashofheaders);
destroy_conn (connptr);