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
This commit is contained in:
rofl0r 2018-11-20 16:07:52 +00:00
parent 235b1c10a7
commit 6057ffca80

View File

@ -90,7 +90,7 @@
* connections. The request line is allocated from the heap, but it must * connections. The request line is allocated from the heap, but it must
* be freed in another function. * 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; ssize_t len;
@ -104,6 +104,12 @@ retry:
return -1; 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. * Strip the new line and carriage return from the string.
*/ */
@ -672,7 +678,7 @@ add_header_to_connection (orderedmap hashofheaders, char *header, size_t len)
/* /*
* Read all the headers from the stream * Read all the headers from the stream
*/ */
static int get_all_headers (int fd, orderedmap hashofheaders) static int get_all_headers (int fd, orderedmap hashofheaders, char** lines, size_t* lines_len)
{ {
char *line = NULL; char *line = NULL;
char *header = NULL; char *header = NULL;
@ -692,6 +698,14 @@ static int get_all_headers (int fd, orderedmap hashofheaders)
return -1; 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 * If we received a CR LF or a non-continuation line, then add
* the accumulated header field, if any, to the hashmap, and * the accumulated header field, if any, to the hashmap, and
@ -1062,7 +1076,7 @@ retry:
/* /*
* Get all the headers from the remote server in a big hash * 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, log_message (LOG_WARNING,
"Could not retrieve all the headers from the remote server."); "Could not retrieve all the headers from the remote server.");
orderedmap_destroy (hashofheaders); orderedmap_destroy (hashofheaders);
@ -1577,6 +1591,8 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
char sock_ipaddr[IP_LENGTH]; char sock_ipaddr[IP_LENGTH];
char peer_ipaddr[IP_LENGTH]; char peer_ipaddr[IP_LENGTH];
char *lines = NULL;
size_t lines_len = 0;
getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr)); getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr));
@ -1620,7 +1636,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
HC_FAIL(); HC_FAIL();
} }
if (read_request_line (connptr) < 0) { if (read_request_line (connptr, &lines, &lines_len) < 0) {
update_stats (STAT_BADCONN); update_stats (STAT_BADCONN);
indicate_http_error (connptr, 408, "Timeout", indicate_http_error (connptr, 408, "Timeout",
"detail", "detail",
@ -1646,7 +1662,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
/* /*
* Get all the headers from the client in a big hash. * 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, log_message (LOG_WARNING,
"Could not retrieve all the headers from the client"); "Could not retrieve all the headers from the client");
indicate_http_error (connptr, 400, "Bad Request", indicate_http_error (connptr, 400, "Bad Request",
@ -1739,6 +1755,11 @@ e401:
"file descriptor %d.", request->host, "file descriptor %d.", request->host,
connptr->server_fd); connptr->server_fd);
if(orderedmap_find (hashofheaders, "upgrade")) {
connptr->connect_method = TRUE;
safe_write (connptr->server_fd, lines, lines_len);
}
if (!connptr->connect_method) if (!connptr->connect_method)
establish_http_connection (connptr, request); establish_http_connection (connptr, request);
} }
@ -1783,6 +1804,7 @@ e401:
connptr->client_fd, connptr->server_fd); connptr->client_fd, connptr->server_fd);
done: done:
safefree(lines);
free_request_struct (request); free_request_struct (request);
orderedmap_destroy (hashofheaders); orderedmap_destroy (hashofheaders);
conn_destroy_contents (connptr); conn_destroy_contents (connptr);