diff --git a/src/ssb.c b/src/ssb.c index 287e60ac..27af7d29 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -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)) { diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index f4e9f347..6491655c 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -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);