summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnacio Casal Quinteiro <icq@gnome.org>2016-12-07 17:15:13 +0100
committerIgnacio Casal Quinteiro <icq@gnome.org>2016-12-07 18:36:47 +0100
commitb119ec7ee152ae38de67cde7956f18b331025c28 (patch)
tree356525cd7bcb2e62c8a70e2d137ced645a538d35
parent975e6f5426568187e907926c905bcb554019ae9f (diff)
downloadlibsoup-wip/validate-close-code.tar.gz
websocket-connection: validate received peer closing codewip/validate-close-code
We cannot trust the received closing code sent by the peer and we should validate it before trying to call the close method. This fixes an assertion on the tests 7.9.* of autobahn: See https://github.com/crossbario/autobahn-testsuite
-rw-r--r--libsoup/soup-websocket-connection.c94
1 files changed, 81 insertions, 13 deletions
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index ed82a27c..8f58961e 100644
--- a/libsoup/soup-websocket-connection.c
+++ b/libsoup/soup-websocket-connection.c
@@ -535,6 +535,59 @@ too_big_error_and_close (SoupWebsocketConnection *self,
}
static void
+close_connection (SoupWebsocketConnection *self,
+ gushort code,
+ const char *data)
+{
+ SoupWebsocketQueueFlags flags;
+ SoupWebsocketConnectionPrivate *pv;
+
+ pv = self->pv;
+
+ if (pv->close_sent) {
+ g_debug ("close code already sent");
+ return;
+ }
+
+ /* Validate the closing code received by the peer */
+ switch (code) {
+ case SOUP_WEBSOCKET_CLOSE_NORMAL:
+ case SOUP_WEBSOCKET_CLOSE_GOING_AWAY:
+ case SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR:
+ case SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA:
+ case SOUP_WEBSOCKET_CLOSE_BAD_DATA:
+ case SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION:
+ case SOUP_WEBSOCKET_CLOSE_TOO_BIG:
+ break;
+ case SOUP_WEBSOCKET_CLOSE_NO_EXTENSION:
+ if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) {
+ g_debug ("Wrong closing code %d received for a server connection",
+ code);
+ break;
+ }
+ case SOUP_WEBSOCKET_CLOSE_SERVER_ERROR:
+ if (pv->connection_type != SOUP_WEBSOCKET_CONNECTION_SERVER) {
+ g_debug ("Wrong closing code %d received for a non server connection",
+ code);
+ break;
+ }
+ default:
+ g_debug ("Wrong closing code %d received", code);
+ }
+
+ g_signal_emit (self, signals[CLOSING], 0);
+
+ if (pv->close_received)
+ g_debug ("responding to close request");
+
+ flags = 0;
+ if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER && pv->close_received)
+ flags |= SOUP_WEBSOCKET_QUEUE_LAST;
+ send_close (self, flags, code, data);
+ close_io_after_timeout (self);
+}
+
+static void
receive_close (SoupWebsocketConnection *self,
const guint8 *data,
gsize len)
@@ -565,8 +618,33 @@ receive_close (SoupWebsocketConnection *self,
if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER)
close_io_stream (self);
} else {
- /* Send back the response */
- soup_websocket_connection_close (self, pv->peer_close_code, NULL);
+ /* Validate the closing code received by the peer */
+ switch (pv->peer_close_code) {
+ case SOUP_WEBSOCKET_CLOSE_NO_EXTENSION:
+ if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) {
+ g_debug ("Wrong closing code %d received for a server connection",
+ pv->peer_close_code);
+ break;
+ }
+ case SOUP_WEBSOCKET_CLOSE_SERVER_ERROR:
+ if (pv->connection_type != SOUP_WEBSOCKET_CONNECTION_SERVER) {
+ g_debug ("Wrong closing code %d received for a non server connection",
+ pv->peer_close_code);
+ break;
+ }
+ case SOUP_WEBSOCKET_CLOSE_NORMAL:
+ case SOUP_WEBSOCKET_CLOSE_GOING_AWAY:
+ case SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR:
+ case SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA:
+ case SOUP_WEBSOCKET_CLOSE_BAD_DATA:
+ case SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION:
+ case SOUP_WEBSOCKET_CLOSE_TOO_BIG:
+ /* Send back the response */
+ soup_websocket_connection_close (self, pv->peer_close_code, NULL);
+ break;
+ default:
+ g_debug ("Wrong closing code %d received", pv->peer_close_code);
+ }
}
}
@@ -1632,7 +1710,6 @@ soup_websocket_connection_close (SoupWebsocketConnection *self,
gushort code,
const char *data)
{
- SoupWebsocketQueueFlags flags;
SoupWebsocketConnectionPrivate *pv;
g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self));
@@ -1647,16 +1724,7 @@ soup_websocket_connection_close (SoupWebsocketConnection *self,
else
g_return_if_fail (code != SOUP_WEBSOCKET_CLOSE_SERVER_ERROR);
- g_signal_emit (self, signals[CLOSING], 0);
-
- if (pv->close_received)
- g_debug ("responding to close request");
-
- flags = 0;
- if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER && pv->close_received)
- flags |= SOUP_WEBSOCKET_QUEUE_LAST;
- send_close (self, flags, code, data);
- close_io_after_timeout (self);
+ close_connection (self, code, data);
}
/**