1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-10 11:43:13 +02:00

relay/api: fix decoding of large websocket frames in remote client (closes #2107)

This commit is contained in:
Sébastien Helleu
2024-04-09 13:32:34 +02:00
parent dbf9068909
commit 5046a9b596
3 changed files with 62 additions and 13 deletions
@@ -466,8 +466,8 @@ relay_remote_network_recv_buffer (struct t_relay_remote *remote,
const char *buffer, int buffer_size)
{
struct t_relay_websocket_frame *frames;
char *partial_ws_frame;
int rc, i, num_frames, partial_ws_frame_size;
int rc, i, buffer2_size, num_frames;
char *buffer2;
/* if authenticating is in progress, check if it was successful */
if (remote->status == RELAY_STATUS_AUTHENTICATING)
@@ -476,26 +476,51 @@ relay_remote_network_recv_buffer (struct t_relay_remote *remote,
}
else if (remote->status == RELAY_STATUS_CONNECTED)
{
partial_ws_frame = NULL;
partial_ws_frame_size = 0;
buffer2 = NULL;
buffer2_size = 0;
if (remote->partial_ws_frame)
{
buffer2_size = buffer_size + remote->partial_ws_frame_size;
buffer2 = malloc (buffer2_size);
if (!buffer2)
{
weechat_printf (
NULL,
_("%sremote[%s]: not enough memory"),
weechat_prefix ("error"),
remote->name);
return;
}
memcpy (buffer2, remote->partial_ws_frame,
remote->partial_ws_frame_size);
memcpy (buffer2 + remote->partial_ws_frame_size,
buffer, buffer_size);
}
frames = NULL;
num_frames = 0;
rc = relay_websocket_decode_frame (
(const unsigned char *)buffer,
buffer_size,
(buffer2) ? (unsigned char *)buffer2 : (const unsigned char *)buffer,
(buffer2) ? (unsigned long long)buffer2_size : (unsigned long long)buffer_size,
0, /* expect_masked_frame */
remote->ws_deflate,
&frames,
&num_frames,
&partial_ws_frame,
&partial_ws_frame_size);
&remote->partial_ws_frame,
&remote->partial_ws_frame_size);
if (buffer2)
free (buffer2);
if (!rc)
{
/* fatal error when decoding frame: close connection */
for (i = 0; i < num_frames; i++)
if (frames)
{
if (frames[i].payload)
free (frames[i].payload);
for (i = 0; i < num_frames; i++)
{
if (frames[i].payload)
free (frames[i].payload);
}
free (frames);
}
free (frames);
weechat_printf (
NULL,
_("%sremote[%s]: error decoding websocket frame"),
+23 -1
View File
@@ -327,6 +327,8 @@ relay_remote_alloc (const char *name)
new_remote->gnutls_sess = NULL;
new_remote->ws_deflate = relay_websocket_deflate_alloc ();
new_remote->synced = 0;
new_remote->partial_ws_frame = NULL;
new_remote->partial_ws_frame_size = 0;
new_remote->prev_remote = NULL;
new_remote->next_remote = NULL;
@@ -487,7 +489,8 @@ relay_remote_new_with_infolist (struct t_infolist *infolist)
{
struct t_relay_remote *new_remote;
Bytef *ptr_dict;
int dict_size;
int dict_size, ws_frame_size;
void *ptr_ws_frame;
new_remote = malloc (sizeof (*new_remote));
if (!new_remote)
@@ -550,6 +553,16 @@ relay_remote_new_with_infolist (struct t_infolist *infolist)
}
}
new_remote->synced = weechat_infolist_integer (infolist, "synced");
ptr_ws_frame = weechat_infolist_buffer (infolist, "partial_ws_frame", &ws_frame_size);
if (ptr_ws_frame && (ws_frame_size > 0))
{
new_remote->partial_ws_frame = malloc (ws_frame_size);
if (new_remote->partial_ws_frame)
{
memcpy (new_remote->partial_ws_frame, ptr_ws_frame, ws_frame_size);
new_remote->partial_ws_frame_size = ws_frame_size;
}
}
new_remote->prev_remote = NULL;
new_remote->next_remote = relay_remotes;
if (relay_remotes)
@@ -766,6 +779,8 @@ relay_remote_free (struct t_relay_remote *remote)
if (remote->hook_fd)
weechat_unhook (remote->hook_fd);
relay_websocket_deflate_free (remote->ws_deflate);
if (remote->partial_ws_frame)
free (remote->partial_ws_frame);
free (remote);
@@ -835,6 +850,8 @@ relay_remote_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "sock", -1))
return 0;
if (!weechat_infolist_new_var_buffer (ptr_item, "partial_ws_frame", NULL, 0))
return 0;
}
else
{
@@ -842,6 +859,8 @@ relay_remote_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "sock", remote->sock))
return 0;
if (!weechat_infolist_new_var_buffer (ptr_item, "partial_ws_frame", remote->partial_ws_frame, remote->partial_ws_frame_size))
return 0;
}
if (remote->ws_deflate->strm_deflate || remote->ws_deflate->strm_inflate)
{
@@ -916,6 +935,9 @@ relay_remote_print_log ()
weechat_log_printf (" gnutls_sess . . . . . . : 0x%lx", ptr_remote->gnutls_sess);
relay_websocket_deflate_print_log (ptr_remote->ws_deflate, "");
weechat_log_printf (" synced. . . . . . . . . : %d", ptr_remote->synced);
weechat_log_printf (" partial_ws_frame. . . . . : %p (%d bytes)",
ptr_remote->partial_ws_frame,
ptr_remote->partial_ws_frame_size);
weechat_log_printf (" prev_remote . . . . . . : 0x%lx", ptr_remote->prev_remote);
weechat_log_printf (" next_remote . . . . . . : 0x%lx", ptr_remote->next_remote);
}
+2
View File
@@ -56,6 +56,8 @@ struct t_relay_remote
gnutls_session_t gnutls_sess; /* gnutls session (only if TLS used) */
struct t_relay_websocket_deflate *ws_deflate; /* websocket deflate data */
int synced; /* 1 if synced with remote */
char *partial_ws_frame; /* part. binary websocket frame recv */
int partial_ws_frame_size; /* size of partial websocket frame */
struct t_relay_remote *prev_remote;/* link to previous remote */
struct t_relay_remote *next_remote;/* link to next remote */
};