diff --git a/src/xmpp/message.c b/src/xmpp/message.c index a7b2b058..6dddf116 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -1132,12 +1132,17 @@ _handle_groupchat(xmpp_stanza_t* const stanza) message->timestamp = NULL; } - // we want to display the oldest delay - message->timestamp = stanza_get_oldest_delay(stanza); - - // now this has nothing to do with MUC history - // it's just setting the time to the received time so upon displaying we can use this time - // for example in win_println_incoming_muc_msg() + // XEP-0203 §4: trust only from the room or our server, not a client-forged stamp + message->timestamp = stanza_get_oldest_delay_from(stanza, from_jid->barejid); + if (!message->timestamp && from_jid->domainpart) { + message->timestamp = stanza_get_oldest_delay_from(stanza, from_jid->domainpart); + } + if (!message->timestamp) { + const char* my_domain = connection_get_domain(); + if (my_domain) { + message->timestamp = stanza_get_oldest_delay_from(stanza, my_domain); + } + } if (!message->timestamp) { message->timestamp = g_date_time_new_now_local(); } @@ -1268,7 +1273,15 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza) _receive_omemo(stanza, message); #endif - message->timestamp = stanza_get_delay(stanza); + // XEP-0203 §4: trust only from a server domain, not a client-forged stamp + const char* my_domain = connection_get_domain(); + message->timestamp = stanza_get_delay_from(stanza, my_domain); + if (!message->timestamp && message->from_jid->domainpart) { + message->timestamp = stanza_get_delay_from(stanza, message->from_jid->domainpart); + } + if (!message->timestamp) { + message->timestamp = g_date_time_new_now_local(); + } message->body = xmpp_message_get_body(stanza); if (!message->plain && !message->body) { @@ -1419,8 +1432,12 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c // timestamp provided outside like in a by MAM message->timestamp = timestamp; } else { - // timestamp in the message stanza or use time of receival (now) - message->timestamp = stanza_get_delay(stanza); + // XEP-0203 §4: trust only from a server domain, not a client-forged stamp + const char* my_domain = connection_get_domain(); + message->timestamp = stanza_get_delay_from(stanza, my_domain); + if (!message->timestamp && jid->domainpart) { + message->timestamp = stanza_get_delay_from(stanza, jid->domainpart); + } if (!message->timestamp) { message->timestamp = g_date_time_new_now_local(); } diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 4fde3ce0..513322b8 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -1163,7 +1163,7 @@ _stanza_get_delay_timestamp_xep0091(xmpp_stanza_t* const x_stanza) } GDateTime* -stanza_get_delay_from(xmpp_stanza_t* const stanza, gchar* from) +stanza_get_delay_from(xmpp_stanza_t* const stanza, const char* const from) { xmpp_stanza_t* delay = NULL; @@ -1195,6 +1195,12 @@ stanza_get_delay_from(xmpp_stanza_t* const stanza, gchar* from) GDateTime* stanza_get_oldest_delay(xmpp_stanza_t* const stanza) +{ + return stanza_get_oldest_delay_from(stanza, NULL); +} + +GDateTime* +stanza_get_oldest_delay_from(xmpp_stanza_t* const stanza, const char* const from) { xmpp_stanza_t* child; const char* child_name; @@ -1205,27 +1211,37 @@ stanza_get_oldest_delay(xmpp_stanza_t* const stanza) child_name = xmpp_stanza_get_name(child); if (child_name && g_strcmp0(child_name, STANZA_NAME_DELAY) == 0) { + if (from) { + const char* child_from = xmpp_stanza_get_attribute(child, STANZA_ATTR_FROM); + if (!child_from || g_strcmp0(child_from, from) != 0) + continue; + } GDateTime* tmp = _stanza_get_delay_timestamp_xep0203(child); if (oldest == NULL) { oldest = tmp; - } else if (g_date_time_compare(oldest, tmp) == 1) { + } else if (tmp && g_date_time_compare(oldest, tmp) == 1) { g_date_time_unref(oldest); oldest = tmp; - } else { + } else if (tmp) { g_date_time_unref(tmp); } } if (child_name && g_strcmp0(child_name, STANZA_NAME_X) == 0) { + if (from) { + const char* child_from = xmpp_stanza_get_attribute(child, STANZA_ATTR_FROM); + if (!child_from || g_strcmp0(child_from, from) != 0) + continue; + } GDateTime* tmp = _stanza_get_delay_timestamp_xep0091(child); if (oldest == NULL) { oldest = tmp; - } else if (g_date_time_compare(oldest, tmp) == 1) { + } else if (tmp && g_date_time_compare(oldest, tmp) == 1) { g_date_time_unref(oldest); oldest = tmp; - } else { + } else if (tmp) { g_date_time_unref(tmp); } } diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index e50b5c78..f34828db 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -305,8 +305,9 @@ xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t* ctx, const char* const gboolean stanza_contains_chat_state(xmpp_stanza_t* stanza); GDateTime* stanza_get_delay(xmpp_stanza_t* const stanza); -GDateTime* stanza_get_delay_from(xmpp_stanza_t* const stanza, gchar* from); +GDateTime* stanza_get_delay_from(xmpp_stanza_t* const stanza, const char* const from); GDateTime* stanza_get_oldest_delay(xmpp_stanza_t* const stanza); +GDateTime* stanza_get_oldest_delay_from(xmpp_stanza_t* const stanza, const char* const from); gboolean stanza_is_muc_presence(xmpp_stanza_t* const stanza); gboolean stanza_is_muc_self_presence(xmpp_stanza_t* const stanza,