A variety of potential protocol/rpc fixes.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4119 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2023-01-14 00:55:51 +00:00
parent 6ed057089b
commit f6ae15c4dc
2 changed files with 81 additions and 37 deletions

106
src/ssb.c
View File

@ -61,7 +61,7 @@ typedef enum {
enum {
k_connections_changed_callbacks_max = 8,
k_tf_ssb_rpc_message_body_length_max = 65536,
k_tf_ssb_rpc_message_body_length_max = 64 * 1024,
};
typedef struct _tf_ssb_broadcast_t tf_ssb_broadcast_t;
@ -446,6 +446,13 @@ static void _tf_ssb_connection_box_stream_send(tf_ssb_connection_t* connection,
return;
}
if (size > 65535)
{
_tf_ssb_connection_close(connection, "sending message that is too big");
tf_free(message_enc);
return;
}
uint8_t header[18];
*(uint16_t*)header = htons((uint16_t)size);
memcpy(header + sizeof(uint16_t), message_enc + 34 - 16, 16);
@ -630,7 +637,8 @@ void tf_ssb_connection_rpc_send_error_method_not_allowed(tf_ssb_connection_t* co
const char* k_unsupported = "{\"message\": \"method: is not in list of allowed methods\", \"name\": \"Error\", \"stack\": \"none\"}";
tf_ssb_connection_rpc_send(
connection,
k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error | (flags & k_ssb_rpc_flag_stream),
k_ssb_rpc_flag_json |
((flags & k_ssb_rpc_flag_stream) ? (k_ssb_rpc_flag_stream | k_ssb_rpc_flag_end_error) : 0),
request_number,
(const uint8_t*)k_unsupported,
strlen(k_unsupported),
@ -698,6 +706,12 @@ void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_
JSValue idval = JS_JSONStringify(context, message, JS_NULL, JS_NewInt32(context, 2));
size_t len = 0;
const char* messagestr = JS_ToCStringLen(context, &len, idval);
if (!messagestr)
{
memset(out_id, 0, out_id_size);
JS_FreeValue(context, idval);
return;
}
char* latin1 = tf_strdup(messagestr);
uint8_t* write_pos = (uint8_t*)latin1;
@ -736,10 +750,23 @@ void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_
static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size)
{
JSValue signature = JS_GetPropertyStr(context, val, "signature");
if (JS_IsUndefined(signature))
{
memset(out_signature, 0, out_signature_size);
return false;
}
const char* str = JS_ToCString(context, signature);
if (!str)
{
JS_FreeValue(context, signature);
memset(out_signature, 0, out_signature_size);
return false;
}
bool verified = false;
tf_ssb_calculate_message_id(context, val, out_id, out_id_size);
JSValue signature = JS_GetPropertyStr(context, val, "signature");
const char* str = JS_ToCString(context, signature);
JSAtom sigatom = JS_NewAtom(context, "signature");
JS_DeleteProperty(context, val, sigatom, 0);
JS_FreeAtom(context, sigatom);
@ -1359,40 +1386,47 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
static void _tf_ssb_connection_rpc_recv_push(tf_ssb_connection_t* connection, const uint8_t* data, size_t size)
{
if (connection->rpc_recv_size + size > sizeof(connection->rpc_recv_buffer))
size_t size_left = size;
size_t size_processed = 0;
while (size_left > 0)
{
_tf_ssb_connection_close(connection, "recv buffer overflow");
return;
}
memcpy(connection->rpc_recv_buffer + connection->rpc_recv_size, data, size);
connection->rpc_recv_size += size;
while (connection->rpc_recv_size >= 9)
{
uint8_t flags = *connection->rpc_recv_buffer;
uint32_t body_len;
int32_t request_number;
memcpy(&body_len, connection->rpc_recv_buffer + 1, sizeof(body_len));
body_len = htonl(body_len);
memcpy(&request_number, connection->rpc_recv_buffer + 1 + sizeof(body_len), sizeof(request_number));
request_number = htonl(request_number);
size_t rpc_size = 9 + body_len;
if (connection->rpc_recv_size >= rpc_size)
size_t copy_size = (connection->rpc_recv_size + size_left > sizeof(connection->rpc_recv_buffer)) ? sizeof(connection->rpc_recv_buffer) - connection->rpc_recv_size : size_left;
if (copy_size == 0)
{
uint8_t* end = &connection->rpc_recv_buffer[9 + body_len];
uint8_t tmp = *end;
*end = '\0';
_tf_ssb_connection_rpc_recv(connection, flags, request_number, connection->rpc_recv_buffer + 9, body_len);
*end = tmp;
memmove(connection->rpc_recv_buffer, connection->rpc_recv_buffer + rpc_size, connection->rpc_recv_size - rpc_size);
connection->rpc_recv_size -= rpc_size;
_tf_ssb_connection_close(connection, "recv buffer overflow");
return;
}
else
memcpy(connection->rpc_recv_buffer + connection->rpc_recv_size, data + size_processed, copy_size);
connection->rpc_recv_size += copy_size;
size_processed += copy_size;
size_left -= copy_size;
while (connection->rpc_recv_size >= 9)
{
/* Wait for more body. */
break;
uint8_t flags = *connection->rpc_recv_buffer;
uint32_t body_len;
int32_t request_number;
memcpy(&body_len, connection->rpc_recv_buffer + 1, sizeof(body_len));
body_len = htonl(body_len);
memcpy(&request_number, connection->rpc_recv_buffer + 1 + sizeof(body_len), sizeof(request_number));
request_number = htonl(request_number);
size_t rpc_size = 9 + body_len;
if (connection->rpc_recv_size >= rpc_size)
{
uint8_t* end = &connection->rpc_recv_buffer[9 + body_len];
uint8_t tmp = *end;
*end = '\0';
_tf_ssb_connection_rpc_recv(connection, flags, request_number, connection->rpc_recv_buffer + 9, body_len);
*end = tmp;
memmove(connection->rpc_recv_buffer, connection->rpc_recv_buffer + rpc_size, connection->rpc_recv_size - rpc_size);
connection->rpc_recv_size -= rpc_size;
}
else
{
/* Wait for more body. */
break;
}
}
}
}
@ -3078,8 +3112,8 @@ tf_ssb_blob_wants_t* tf_ssb_connection_get_blob_wants_state(tf_ssb_connection_t*
bool tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value)
{
JSContext* context = tf_ssb_get_context(ssb);
char signature[crypto_sign_BYTES + 128];
char id[crypto_hash_sha256_BYTES * 2 + 1];
char signature[crypto_sign_BYTES + 128] = { 0 };
char id[crypto_hash_sha256_BYTES * 2 + 1] = { 0 };
bool sequence_before_author = false;
if (tf_ssb_verify_and_strip_signature(context, value, id, sizeof(id), signature, sizeof(signature), &sequence_before_author))
{

View File

@ -367,6 +367,11 @@ static void _tf_ssb_rpc_room_meta(tf_ssb_connection_t* connection, uint8_t flags
JS_FreeValue(context, response);
}
static void _tf_ssb_rpc_room_attendants_callback(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{
printf("room attendants callback??\n");
}
static void _tf_ssb_rpc_room_attendants(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
@ -416,6 +421,7 @@ static void _tf_ssb_rpc_room_attendants(tf_ssb_connection_t* connection, uint8_t
JS_FreeValue(context, state);
tf_ssb_connection_set_attendant(connection, true, request_number);
tf_ssb_connection_add_request(connection, -request_number, _tf_ssb_rpc_room_attendants_callback, NULL, NULL, NULL);
}
typedef struct _blobs_get_t
@ -966,6 +972,10 @@ static void _tf_ssb_rpc_send_ebt_replicate(tf_ssb_connection_t* connection)
static void _tf_ssb_rpc_ebt_replicate_server(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{
if (flags & k_ssb_rpc_flag_end_error)
{
return;
}
_tf_ssb_rpc_ebt_replicate(connection, flags, request_number, args, message, size, user_data);
tf_ssb_connection_add_request(connection, -request_number, _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL);
}
@ -1053,7 +1063,7 @@ void tf_ssb_rpc_register(tf_ssb_t* ssb)
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "blobs", "createWants", NULL }, _tf_ssb_rpc_blobs_createWants, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "tunnel", "connect", NULL }, _tf_ssb_rpc_tunnel_connect, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "tunnel", "isRoom", NULL }, _tf_ssb_rpc_room_meta, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "meta", NULL }, _tf_ssb_rpc_room_meta, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "metadata", NULL }, _tf_ssb_rpc_room_meta, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "attendants", NULL }, _tf_ssb_rpc_room_attendants, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "createHistoryStream", NULL }, _tf_ssb_rpc_createHistoryStream, NULL, NULL);
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "ebt", "replicate", NULL }, _tf_ssb_rpc_ebt_replicate_server, NULL, NULL);