Skip to content

Commit 92a4484

Browse files
committed
WIP more validation
1 parent 44267fe commit 92a4484

File tree

1 file changed

+109
-2
lines changed

1 file changed

+109
-2
lines changed

source/websocket_bootstrap.c

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <aws/cal/hash.h>
77
#include <aws/common/encoding.h>
88
#include <aws/common/logging.h>
9+
#include <aws/common/string.h>
910
#include <aws/http/connection.h>
1011
#include <aws/http/private/http_impl.h>
1112
#include <aws/http/private/strutil.h>
@@ -73,6 +74,9 @@ struct aws_websocket_client_bootstrap {
7374
* this is what we expect the response's "Sec-WebSocket-Accept" to be */
7475
struct aws_byte_buf expected_sec_websocket_accept;
7576

77+
/* Values from the request's "Sec-WebSocket-Protocol" values (or NULL if none) */
78+
struct aws_string *expected_sec_websocket_protocol;
79+
7680
/* Handshake response data */
7781
int response_status;
7882
struct aws_http_headers *response_headers;
@@ -152,6 +156,16 @@ int aws_websocket_client_connect(const struct aws_websocket_client_connection_op
152156
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
153157
}
154158

159+
/* Extensions are not currently supported */
160+
struct aws_string *sec_websocket_extensions =
161+
aws_http_headers_get_comma_separated(request_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Extensions"));
162+
if (sec_websocket_extensions != NULL) {
163+
aws_string_destroy(sec_websocket_extensions);
164+
AWS_LOGF_ERROR(
165+
AWS_LS_HTTP_WEBSOCKET_SETUP, "id=static: 'Sec-WebSocket-Extensions' are not currently supported");
166+
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
167+
}
168+
155169
/* Create bootstrap */
156170
struct aws_websocket_client_bootstrap *ws_bootstrap =
157171
aws_mem_calloc(options->allocator, 1, sizeof(struct aws_websocket_client_bootstrap));
@@ -175,6 +189,9 @@ int aws_websocket_client_connect(const struct aws_websocket_client_connection_op
175189
goto error;
176190
}
177191

192+
ws_bootstrap->expected_sec_websocket_protocol = aws_http_headers_get_comma_separated(
193+
options->handshake_request, aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol"));
194+
178195
/* Initiate HTTP connection */
179196
struct aws_http_client_connection_options http_options = AWS_HTTP_CLIENT_CONNECTION_OPTIONS_INIT;
180197
http_options.allocator = ws_bootstrap->alloc;
@@ -241,6 +258,7 @@ static void s_ws_bootstrap_destroy(struct aws_websocket_client_bootstrap *ws_boo
241258
aws_http_message_release(ws_bootstrap->handshake_request);
242259
aws_http_headers_release(ws_bootstrap->response_headers);
243260
aws_byte_buf_clean_up(&ws_bootstrap->expected_sec_websocket_accept);
261+
aws_string_destroy(ws_bootstrap->expected_sec_websocket_protocol);
244262
aws_byte_buf_clean_up(&ws_bootstrap->response_body);
245263

246264
aws_mem_release(ws_bootstrap->alloc, ws_bootstrap);
@@ -582,6 +600,38 @@ static int s_ws_bootstrap_validate_header(
582600
return AWS_OP_SUCCESS;
583601
}
584602

603+
static int s_ws_bootstrap_validate_sec_websocket_protocol(const struct aws_websocket_client_bootstrap *ws_bootstrap) {
604+
605+
/* First handle the easy case:
606+
* If client requested no protocols, then the response should not pick any */
607+
if (ws_bootstrap->expected_sec_websocket_protocol == NULL) {
608+
if (aws_http_headers_has(
609+
ws_bootstrap->response_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol"))) {
610+
611+
AWS_LOGF_ERROR(
612+
AWS_LS_HTTP_WEBSOCKET_SETUP,
613+
"id=%p: Response has 'Sec-WebSocket-Protocol' header, no protocol was requested",
614+
(void *)ws_bootstrap);
615+
return aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
616+
} else {
617+
return AWS_OP_SUCCESS;
618+
}
619+
}
620+
621+
/* Check that server has picked one of the requested protocols */
622+
struct aws_byte_cursor response_protocol;
623+
if (aws_http_headers_get_single(
624+
ws_bootstrap->response_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol"), &response_protocol)) {
625+
AWS_LOGF_ERROR(
626+
AWS_LS_HTTP_WEBSOCKET_SETUP,
627+
"id=%p: Response lacks required 'Sec-WebSocket-Protocol' header",
628+
(void *)ws_bootstrap);
629+
return aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
630+
}
631+
632+
YOU ARE HERE
633+
}
634+
585635
/* OK, we've got all the headers for the 101 Switching Protocols response.
586636
* Validate the handshake response, install the websocket handler into the channel,
587637
* and invoke the on_connection_setup callback. */
@@ -627,9 +677,66 @@ static int s_ws_bootstrap_validate_response_and_install_websocket_handler(
627677
goto error;
628678
}
629679

630-
/* TODO: validate Sec-WebSocket-Extensions */
680+
/* (step 5 is about validating Sec-WebSocket-Extensions, but we don't support extensions) */
681+
struct aws_string *sec_websocket_extensions = aws_http_headers_get_comma_separated(
682+
ws_bootstrap->response_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Extensions"));
683+
if (sec_websocket_extensions != NULL) {
684+
aws_string_destroy(sec_websocket_extensions);
685+
AWS_LOGF_ERROR(
686+
AWS_LS_HTTP_WEBSOCKET_SETUP,
687+
"id=%p: Response has 'Sec-WebSocket-Extensions' header, but client does not support extensions.",
688+
(void *)ws_bootstrap);
689+
aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
690+
goto error;
691+
}
692+
693+
/* 6. If the response includes a |Sec-WebSocket-Protocol| header field
694+
* and this header field indicates the use of a subprotocol that was
695+
* not present in the client's handshake (the server has indicated a
696+
* subprotocol not requested by the client), the client MUST _Fail
697+
* the WebSocket Connection_. */
698+
if (ws_bootstrap->sec_websocket_protocol_values) {
699+
struct aws_byte_cursor response_protocol;
700+
if (aws_http_headers_get_single(
701+
ws_bootstrap->response_headers,
702+
aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol"),
703+
&response_protocol)) {
704+
705+
AWS_LOGF_ERROR(
706+
AWS_LS_HTTP_WEBSOCKET_SETUP,
707+
"id=%p: Response lacks required'Sec-WebSocket-Protocol' header",
708+
(void *)ws_bootstrap);
709+
aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
710+
goto error;
711+
}
712+
713+
} else {
714+
if (aws_http_headers_has(ws_bootstrap->response_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol")) {
715+
AWS_LOGF_ERROR(
716+
AWS_LS_HTTP_WEBSOCKET_SETUP,
717+
"id=%p: Response has 'Sec-WebSocket-Protocol' header, no protocol was requested",
718+
(void *)ws_bootstrap);
719+
aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
720+
goto error;
721+
}
722+
}
723+
struct aws_byte_cursor response_protocol;
724+
if (aws_http_headers_get_single(
725+
ws_bootstrap->response_headers, aws_byte_cursor_from_c_str("Sec-WebSocket-Protocol"), &response_protocol) ==
726+
AWS_OP_SUCCESS) {
631727

632-
/* TODO: validate Sec-WebSocket-Protocol */
728+
if (ws_bootstrap->sec_websocket_protocol_values == NULL) {
729+
AWS_LOGF_ERROR(
730+
AWS_LS_HTTP_WEBSOCKET_SETUP,
731+
"id=%p: Response has 'Sec-WebSocket-Protocol' header, no protocol was requested",
732+
(void *)ws_bootstrap);
733+
aws_raise_error(AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE);
734+
goto error;
735+
}
736+
}
737+
if (s_ws_bootstrap_validate_sec_websocket_protocol(ws_bootstrap)) {
738+
goto error;
739+
}
633740

634741
/* Insert websocket handler into channel */
635742
struct aws_channel *channel = s_system_vtable->aws_http_connection_get_channel(http_connection);

0 commit comments

Comments
 (0)