summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src/toxcore/group_pack.c
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-02-15 12:18:35 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-02-15 12:18:35 +0300
commit31e72718ee54867accf0b739a24adc86f8b7ab54 (patch)
treef964c10c5d97d9fe4fd2bd8187c250faedcb0fd7 /protocols/Tox/libtox/src/toxcore/group_pack.c
parent282e9c18d9d3b726cce3d2ef0babc88029661cb8 (diff)
libtox update
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore/group_pack.c')
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_pack.c141
1 files changed, 106 insertions, 35 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.c b/protocols/Tox/libtox/src/toxcore/group_pack.c
index ecdd965610..e3af82c67a 100644
--- a/protocols/Tox/libtox/src/toxcore/group_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/group_pack.c
@@ -9,20 +9,72 @@
#include "group_pack.h"
-#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "attributes.h"
#include "bin_pack.h"
#include "bin_unpack.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "crypto_core_pack.h"
+#include "group_common.h"
+#include "group_moderation.h"
+#include "logger.h"
+#include "network.h"
#include "util.h"
+bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out)
+{
+ switch (value) {
+ case GI_PUBLIC: {
+ *out = GI_PUBLIC;
+ return true;
+ }
+
+ case GI_PRIVATE: {
+ *out = GI_PRIVATE;
+ return true;
+ }
+
+ default: {
+ *out = GI_PUBLIC;
+ return false;
+ }
+ }
+}
+
+bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out)
+{
+ switch (value) {
+ case GV_ALL: {
+ *out = GV_ALL;
+ return true;
+ }
+
+ case GV_MODS: {
+ *out = GV_MODS;
+ return true;
+ }
+
+ case GV_FOUNDER: {
+ *out = GV_FOUNDER;
+ return true;
+ }
+
+ default: {
+ *out = GV_ALL;
+ return false;
+ }
+ }
+}
+
non_null()
static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 8)) {
+ if (!bin_unpack_array_fixed(bu, 8, nullptr)) {
LOGGER_ERROR(chat->log, "Group state values array malformed");
return false;
}
@@ -44,8 +96,8 @@ static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
}
chat->connection_state = manually_disconnected ? CS_DISCONNECTED : CS_CONNECTING;
- chat->shared_state.privacy_state = (Group_Privacy_State)privacy_state;
- chat->shared_state.voice_state = (Group_Voice_State)voice_state;
+ group_privacy_state_from_int(privacy_state, &chat->shared_state.privacy_state);
+ group_voice_state_from_int(voice_state, &chat->shared_state.voice_state);
// we always load saved groups as private in case the group became private while we were offline.
// this will have no detrimental effect if the group is public, as the correct privacy
@@ -58,15 +110,23 @@ static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_state_bin(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 5)) {
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
LOGGER_ERROR(chat->log, "Group state binary array malformed");
return false;
}
- if (!(bin_unpack_bin_fixed(bu, chat->shared_state_sig, SIGNATURE_SIZE)
- && bin_unpack_bin_fixed(bu, chat->shared_state.founder_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->shared_state.group_name, chat->shared_state.group_name_len)
- && bin_unpack_bin_fixed(bu, chat->shared_state.password, chat->shared_state.password_length)
+ if (!bin_unpack_bin_fixed(bu, chat->shared_state_sig, SIGNATURE_SIZE)) {
+ LOGGER_ERROR(chat->log, "Failed to unpack shared state signature");
+ return false;
+ }
+
+ if (!unpack_extended_public_key(&chat->shared_state.founder_public_key, bu)) {
+ LOGGER_ERROR(chat->log, "Failed to unpack founder public key");
+ return false;
+ }
+
+ if (!(bin_unpack_bin_max(bu, chat->shared_state.group_name, &chat->shared_state.group_name_len, sizeof(chat->shared_state.group_name))
+ && bin_unpack_bin_max(bu, chat->shared_state.password, &chat->shared_state.password_length, sizeof(chat->shared_state.password))
&& bin_unpack_bin_fixed(bu, chat->shared_state.mod_list_hash, MOD_MODERATION_HASH_SIZE))) {
LOGGER_ERROR(chat->log, "Failed to unpack state binary data");
return false;
@@ -78,7 +138,7 @@ static bool load_unpack_state_bin(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 6)) {
+ if (!bin_unpack_array_fixed(bu, 6, nullptr)) {
LOGGER_ERROR(chat->log, "Group topic array malformed");
return false;
}
@@ -86,7 +146,7 @@ static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
if (!(bin_unpack_u32(bu, &chat->topic_info.version)
&& bin_unpack_u16(bu, &chat->topic_info.length)
&& bin_unpack_u16(bu, &chat->topic_info.checksum)
- && bin_unpack_bin_fixed(bu, chat->topic_info.topic, chat->topic_info.length)
+ && bin_unpack_bin_max(bu, chat->topic_info.topic, &chat->topic_info.length, sizeof(chat->topic_info.topic))
&& bin_unpack_bin_fixed(bu, chat->topic_info.public_sig_key, SIG_PUBLIC_KEY_SIZE)
&& bin_unpack_bin_fixed(bu, chat->topic_sig, SIGNATURE_SIZE))) {
LOGGER_ERROR(chat->log, "Failed to unpack topic info");
@@ -99,8 +159,9 @@ static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 2)) {
- LOGGER_ERROR(chat->log, "Group mod list array malformed");
+ uint32_t actual_size = 0;
+ if (!bin_unpack_array_fixed(bu, 2, &actual_size)) {
+ LOGGER_ERROR(chat->log, "Group mod list array malformed: %d != 2", actual_size);
return false;
}
@@ -116,7 +177,7 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
if (chat->moderation.num_mods > MOD_MAX_NUM_MODERATORS) {
LOGGER_ERROR(chat->log, "moderation count %u exceeds maximum %u", chat->moderation.num_mods, MOD_MAX_NUM_MODERATORS);
- return false;
+ chat->moderation.num_mods = MOD_MAX_NUM_MODERATORS;
}
uint8_t *packed_mod_list = (uint8_t *)malloc(chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE);
@@ -148,15 +209,15 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_keys(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
LOGGER_ERROR(chat->log, "Group keys array malformed");
return false;
}
- if (!(bin_unpack_bin_fixed(bu, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->chat_secret_key, EXT_SECRET_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->self_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->self_secret_key, EXT_SECRET_KEY_SIZE))) {
+ if (!(unpack_extended_public_key(&chat->chat_public_key, bu)
+ && unpack_extended_secret_key(&chat->chat_secret_key, bu)
+ && unpack_extended_public_key(&chat->self_public_key, bu)
+ && unpack_extended_secret_key(&chat->self_secret_key, bu))) {
LOGGER_ERROR(chat->log, "Failed to unpack keys");
return false;
}
@@ -167,7 +228,7 @@ static bool load_unpack_keys(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
LOGGER_ERROR(chat->log, "Group self info array malformed");
return false;
}
@@ -184,7 +245,10 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
return false;
}
- assert(self_nick_len <= MAX_GC_NICK_SIZE);
+ if (self_nick_len > MAX_GC_NICK_SIZE) {
+ LOGGER_ERROR(chat->log, "self_nick too big (%u bytes), truncating to %d", self_nick_len, MAX_GC_NICK_SIZE);
+ self_nick_len = MAX_GC_NICK_SIZE;
+ }
if (!bin_unpack_bin_fixed(bu, self_nick, self_nick_len)) {
LOGGER_ERROR(chat->log, "Failed to unpack self nick bytes");
@@ -192,16 +256,19 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
}
// we have to add ourself before setting self info
- if (peer_add(chat, nullptr, chat->self_public_key) != 0) {
+ if (peer_add(chat, nullptr, chat->self_public_key.enc) != 0) {
LOGGER_ERROR(chat->log, "Failed to add self to peer list");
return false;
}
- assert(chat->numpeers > 0);
+ if (chat->numpeers == 0) {
+ LOGGER_ERROR(chat->log, "Failed to unpack self: numpeers should be > 0");
+ return false;
+ }
GC_Peer *self = &chat->group[0];
- memcpy(self->gconn.addr.public_key, chat->self_public_key, EXT_PUBLIC_KEY_SIZE);
+ self->gconn.addr.public_key = chat->self_public_key;
memcpy(self->nick, self_nick, self_nick_len);
self->nick_length = self_nick_len;
self->role = (Group_Role)self_role;
@@ -214,7 +281,7 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
LOGGER_ERROR(chat->log, "Group saved peers array malformed");
return false;
}
@@ -256,8 +323,9 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
bool gc_load_unpack_group(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 7)) {
- LOGGER_ERROR(chat->log, "Group info array malformed");
+ uint32_t actual_size;
+ if (!bin_unpack_array_fixed(bu, 7, &actual_size)) {
+ LOGGER_ERROR(chat->log, "Group info array malformed: %d != 7", actual_size);
return false;
}
@@ -290,7 +358,7 @@ static void save_pack_state_bin(const GC_Chat *chat, Bin_Pack *bp)
bin_pack_array(bp, 5);
bin_pack_bin(bp, chat->shared_state_sig, SIGNATURE_SIZE); // 1
- bin_pack_bin(bp, chat->shared_state.founder_public_key, EXT_PUBLIC_KEY_SIZE); // 2
+ pack_extended_public_key(&chat->shared_state.founder_public_key, bp); // 2
bin_pack_bin(bp, chat->shared_state.group_name, chat->shared_state.group_name_len); // 3
bin_pack_bin(bp, chat->shared_state.password, chat->shared_state.password_length); // 4
bin_pack_bin(bp, chat->shared_state.mod_list_hash, MOD_MODERATION_HASH_SIZE); // 5
@@ -348,10 +416,10 @@ static void save_pack_keys(const GC_Chat *chat, Bin_Pack *bp)
{
bin_pack_array(bp, 4);
- bin_pack_bin(bp, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE); // 1
- bin_pack_bin(bp, chat->chat_secret_key, EXT_SECRET_KEY_SIZE); // 2
- bin_pack_bin(bp, chat->self_public_key, EXT_PUBLIC_KEY_SIZE); // 3
- bin_pack_bin(bp, chat->self_secret_key, EXT_SECRET_KEY_SIZE); // 4
+ pack_extended_public_key(&chat->chat_public_key, bp); // 1
+ pack_extended_secret_key(&chat->chat_secret_key, bp); // 2
+ pack_extended_public_key(&chat->self_public_key, bp); // 3
+ pack_extended_secret_key(&chat->self_secret_key, bp); // 4
}
non_null()
@@ -359,13 +427,16 @@ static void save_pack_self_info(const GC_Chat *chat, Bin_Pack *bp)
{
bin_pack_array(bp, 4);
- const GC_Peer *self = &chat->group[0];
+ GC_Peer *self = &chat->group[0];
- assert(self->nick_length <= MAX_GC_NICK_SIZE);
+ if (self->nick_length > MAX_GC_NICK_SIZE) {
+ LOGGER_ERROR(chat->log, "self_nick is too big (%u). Truncating to %d", self->nick_length, MAX_GC_NICK_SIZE);
+ self->nick_length = MAX_GC_NICK_SIZE;
+ }
bin_pack_u16(bp, self->nick_length); // 1
bin_pack_u08(bp, (uint8_t)self->role); // 2
- bin_pack_u08(bp, (uint8_t)self->status); // 3
+ bin_pack_u08(bp, self->status); // 3
bin_pack_bin(bp, self->nick, self->nick_length); // 4
}