diff --git a/src/XMPP/Stanza.c b/src/XMPP/Stanza.c index d728b64..570ef48 100644 --- a/src/XMPP/Stanza.c +++ b/src/XMPP/Stanza.c @@ -515,7 +515,7 @@ XMPPSendDisco(XMPPComponent *jabber, char *from, char *to) pthread_mutex_unlock(&jabber->write_lock); XMLFreeElement(iq); - ret = ParseeAwaitStanza(identifier, 250); + ret = ParseeAwaitStanza(identifier, 5000); Free(identifier); return ret; } diff --git a/src/XMPPCommands/Nofly.c b/src/XMPPCommands/Nofly.c index bdbe6e4..86a7bb1 100644 --- a/src/XMPPCommands/Nofly.c +++ b/src/XMPPCommands/Nofly.c @@ -43,12 +43,19 @@ NoflyCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *o XMLAddAttr(x, "type", "result"); { DbRef *ref = DbLock(data->db, 1, "global_bans"); - HashMap *bans = DbJson(ref); + HashMap *bans; char *banned, *reason; JsonValue *ban_val; reported = XMLCreateTag("reported"); XMLAddChild(x, reported); + + if (!ref) + { + ref = DbCreate(data->db, 1, "global_bans"); + } + bans = DbJson(ref); + /* Report */ Report("ban", "Banned glob"); Report("reason", "Reason for the nofly"); diff --git a/src/XMPPThread/Bridged.c b/src/XMPPThread/Bridged.c index 32afd23..3685c64 100644 --- a/src/XMPPThread/Bridged.c +++ b/src/XMPPThread/Bridged.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -116,6 +117,7 @@ ParseeVerifyAllStanza(ParseeData *args, XMLElement *stanza) return ret; } +/* TODO: Cache this information. */ bool ServerHasXEP421(ParseeData *data, char *from) { @@ -153,32 +155,84 @@ ServerHasXEP421(ParseeData *data, char *from) Free(server); return ret; } + +/* Scrambles an Occupant ID so that Matrix can use it for MXIDs. + * Occupant IDs are to be treated as opaque, therefore, we hash them + * into a SHA-256 value + * > "The recipient MUST consider the occupant identifier to be an opaque + * > string.". */ +static char * +ScrambleOID(ParseeData *data, char *opaque_oid) +{ + unsigned char *raw; + char *sha, *mxid; + const ParseeConfig *c = data->config; + if (!opaque_oid) + { + return NULL; + } + + /* Turns this into a 128-byte long, Matrix-safe value. */ + raw = Sha256(opaque_oid); + sha = ShaToHex(raw); + Free(raw); + + /* TODO: Either mark this specially, or drop Parsee JID flags + * altogether before any 1.0.0 */ + mxid = StrConcat( + 6, + "@", c->namespace_base, "_l_", sha, ":", + c->homeserver_host + ); + Free(sha); + return mxid; +} + +/* TODO: Shove that function everywhere one can see fit. */ char * -ParseeGetBridgedUser(ParseeData *data, XMLElement *stanza) +ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force) { char *user, *xmpp_from, *type; - char *decode_from; + char *decode_from, *occ_id = NULL; + bool is_chat, has_anon = false, is_anon = false; if (!data || !stanza) { return NULL; } - xmpp_from = HashMapGet(stanza->attrs, "from"); + xmpp_from = force ? force : HashMapGet(stanza->attrs, "from"); type = HashMapGet(stanza->attrs, "type"); decode_from = ParseeLookupJID(xmpp_from); - /* TODO: On semi-anonymous MUCs, it might be preferable to use a - * form of the occupant ID as the base, as it is more unique, and - * less prone to trigger the character limit on Matrix. - * I'll need to detect these first.... - * - * See: https://xmpp.org/extensions/xep-0421.html */ - user = ParseeEncodeJID( - data->config, - decode_from, - StrEquals(type, "chat") - ); + is_chat = StrEquals(type, "chat"); + if (!is_chat) + { + has_anon = ServerHasXEP421(data, xmpp_from); + is_anon = has_anon && StrEquals(xmpp_from, decode_from); + } + + if (is_anon) + { + XMLElement *occupant; + occupant = XMLookForTKV( + stanza, "occupant-id", + "xmlns", "urn:xmpp:occupant-id:0" + ); + occ_id = occupant ? HashMapGet(occupant->attrs, "id") : NULL; + } + + if (!occ_id) + { + user = ParseeEncodeJID( + data->config, + decode_from, + type ? is_chat : false + ); + Free(decode_from); + return user; + } + Free(decode_from); - return user; + return ScrambleOID(data, occ_id); } diff --git a/src/XMPPThread/ReListener.c b/src/XMPPThread/ReListener.c index e6df0f3..562d3a2 100644 --- a/src/XMPPThread/ReListener.c +++ b/src/XMPPThread/ReListener.c @@ -229,15 +229,6 @@ ParseeXMPPThread(void *argp) XMLElement * ParseeAwaitStanza(char *identifier, int64_t timeout) { - XMPPAwait *awa; - XMLElement *stanza; - struct timespec ts; - - if (!identifier) - { - return NULL; - } - /* XXX: You may be wondering _why_ I am using stdlib's malloc, instead of * Cytoplasm's Malloc wrapper(which are essentially the same thing, plus * some memchecking as of now), or the stack, as done previously. @@ -246,15 +237,26 @@ ParseeAwaitStanza(char *identifier, int64_t timeout) * since, as I said, it is as of now just malloc with extra metadata prepended * to it. A _guess_ may be that the metadata makes everything unaligned, which, * just sounds silly. pthreads should be able to cope fine with that, I think. - * - The stack seems to be a prime candidate to cause a stack corruption, which - * puzzled me for a comically long while("why is the value being swapped for - * the key?" "why does duplicating twice cause the former problem to disappear, - * but still obviously creating another one?", ...). * * I am open to issues talking about such fun behaviour and ideas to fix this. * This is a bodge, and potentially a problem, or vulnerability with Cytoplasm/ * Parsee. As long as it isn't "use Rust". Please don't say that. */ - awa = malloc(sizeof(XMPPAwait)); + XMPPAwait awa = { 0 }; + XMLElement *stanza; + struct timespec ts; + + if (!identifier) + { + return NULL; + } + + pthread_mutex_lock(&await_lock); + if (HashMapGet(await_table, identifier)) + { + return NULL; + } + pthread_mutex_unlock(&await_lock); + /* Convert into an absolute timeout. * ================================= @@ -282,29 +284,24 @@ ParseeAwaitStanza(char *identifier, int64_t timeout) pthread_mutex_lock(&await_lock); - pthread_cond_init(&awa->condition, NULL); - pthread_mutex_init(&awa->cond_lock, NULL); - awa->stanza = NULL; - - if (HashMapGet(await_table, identifier)) - { - HashMapDelete(await_table, identifier); - } + pthread_cond_init(&awa.condition, NULL); + pthread_mutex_init(&awa.cond_lock, NULL); + awa.stanza = NULL; - HashMapSet(await_table, identifier, awa); + HashMapSet(await_table, identifier, &awa); pthread_mutex_unlock(&await_lock); - pthread_mutex_lock(&awa->cond_lock); - while (!awa->stanza) + pthread_mutex_lock(&awa.cond_lock); + while (!awa.stanza) { int code; if (timeout <= 0) { - pthread_cond_wait(&awa->condition, &awa->cond_lock); + pthread_cond_wait(&awa.condition, &awa.cond_lock); continue; } - code = pthread_cond_timedwait(&awa->condition, &awa->cond_lock, &ts); + code = pthread_cond_timedwait(&awa.condition, &awa.cond_lock, &ts); if (code == ETIMEDOUT) { /* Timeout detected, give up regardless of the status of our @@ -319,11 +316,10 @@ ParseeAwaitStanza(char *identifier, int64_t timeout) } } - stanza = awa->stanza; - pthread_mutex_unlock(&awa->cond_lock); + stanza = awa.stanza; + pthread_mutex_unlock(&awa.cond_lock); - pthread_cond_destroy(&awa->condition); - pthread_mutex_destroy(&awa->cond_lock); - free(awa); + pthread_cond_destroy(&awa.condition); + pthread_mutex_destroy(&awa.cond_lock); return stanza; } diff --git a/src/XMPPThread/Stanzas/IQ.c b/src/XMPPThread/Stanzas/IQ.c index 0b9009b..f0014c9 100644 --- a/src/XMPPThread/Stanzas/IQ.c +++ b/src/XMPPThread/Stanzas/IQ.c @@ -180,7 +180,7 @@ IQResult(ParseeData *args, XMLElement *stanza, XMPPThread *thr) mxc = ASUpload(args->config, datastream, length, "image/png"); jid = ParseeLookupJID(from); - from_matrix = ParseeEncodeJID(args->config, jid, false); + from_matrix = ParseeGetBridgedUser(args, stanza); ASSetAvatar(args->config, from_matrix, mxc); JsonValueFree(JsonSet( diff --git a/src/XMPPThread/Stanzas/Message.c b/src/XMPPThread/Stanzas/Message.c index 81f50e3..5e2ab2c 100644 --- a/src/XMPPThread/Stanzas/Message.c +++ b/src/XMPPThread/Stanzas/Message.c @@ -148,11 +148,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) return false; } - if (ServerHasXEP421(args, HashMapGet(stanza->attrs, "from"))) - { - - } - to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to")); decode_from = ParseeLookupJID(from); from_matrix = ParseeEncodeJID(args->config, decode_from, true); diff --git a/src/XMPPThread/Stanzas/Presence.c b/src/XMPPThread/Stanzas/Presence.c index d98f196..1da67d8 100644 --- a/src/XMPPThread/Stanzas/Presence.c +++ b/src/XMPPThread/Stanzas/Presence.c @@ -76,8 +76,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) char *from = NULL; char *type = HashMapGet(stanza->attrs, "type"); char *room = ParseeGetBridgedRoom(args, stanza); - char *decode_from = ParseeLookupJID(oid); - char *real_matrix = ParseeDecodeMXID(decode_from); + char *decode_from, *real_matrix; char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false); char *affiliation = HashMapGet(item->attrs, "affiliation"); int power_level = 0; @@ -85,10 +84,18 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) Free(trim); + if (jid) + { + ParseePushJIDTable(oid, jid); + } + decode_from = ParseeLookupJID(oid); + real_matrix = ParseeDecodeMXID(decode_from); + if (!real_matrix || *real_matrix != '@') { Free(real_matrix); - real_matrix = ParseeEncodeJID(args->config, decode_from, false); + /*real_matrix = ParseeEncodeJID(args->config, decode_from, false);*/ + real_matrix = ParseeGetBridgedUserI(args, stanza, oid); } if (StrEquals(affiliation, "owner")) @@ -163,10 +170,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) } } - if (jid) - { - ParseePushJIDTable(oid, jid); - } Free(from); Free(decode_from); @@ -179,8 +182,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) { XMLElement *status_data = ArrayGet(status->children, 0); char *decode_from = ParseeLookupJID(oid); - char *trimmed = ParseeTrimJID(decode_from); - char *from_matrix = ParseeEncodeJID(args->config, trimmed, false); + char *from_matrix = ParseeGetBridgedUser(args, stanza); char *status_str = NULL; if (status_data) { @@ -199,7 +201,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) Free(decode_from); Free(from_matrix); - Free(trimmed); } if (vc) { diff --git a/src/XMPPThread/internal.h b/src/XMPPThread/internal.h index e603991..08951fe 100644 --- a/src/XMPPThread/internal.h +++ b/src/XMPPThread/internal.h @@ -78,4 +78,5 @@ void PresenceStanza(ParseeData *args, XMLElement *stanza); bool ServerHasXEP421(ParseeData *data, char *from); -char * ParseeGetBridgedUser(ParseeData *data, XMLElement *stanza); +char * ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force); +#define ParseeGetBridgedUser(data, stanza) ParseeGetBridgedUserI(data, stanza, NULL)