[MOD/WIP] Continue XEP-0421

This commit is contained in:
LDA 2024-07-19 17:07:13 +02:00
commit c9f8d69802
8 changed files with 120 additions and 66 deletions

View file

@ -515,7 +515,7 @@ XMPPSendDisco(XMPPComponent *jabber, char *from, char *to)
pthread_mutex_unlock(&jabber->write_lock); pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq); XMLFreeElement(iq);
ret = ParseeAwaitStanza(identifier, 250); ret = ParseeAwaitStanza(identifier, 5000);
Free(identifier); Free(identifier);
return ret; return ret;
} }

View file

@ -43,12 +43,19 @@ NoflyCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *o
XMLAddAttr(x, "type", "result"); XMLAddAttr(x, "type", "result");
{ {
DbRef *ref = DbLock(data->db, 1, "global_bans"); DbRef *ref = DbLock(data->db, 1, "global_bans");
HashMap *bans = DbJson(ref); HashMap *bans;
char *banned, *reason; char *banned, *reason;
JsonValue *ban_val; JsonValue *ban_val;
reported = XMLCreateTag("reported"); reported = XMLCreateTag("reported");
XMLAddChild(x, reported); XMLAddChild(x, reported);
if (!ref)
{
ref = DbCreate(data->db, 1, "global_bans");
}
bans = DbJson(ref);
/* Report */ /* Report */
Report("ban", "Banned glob"); Report("ban", "Banned glob");
Report("reason", "Reason for the nofly"); Report("reason", "Reason for the nofly");

View file

@ -3,6 +3,7 @@
#include <Cytoplasm/Memory.h> #include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h> #include <Cytoplasm/Log.h>
#include <Cytoplasm/Sha.h>
#include <string.h> #include <string.h>
@ -116,6 +117,7 @@ ParseeVerifyAllStanza(ParseeData *args, XMLElement *stanza)
return ret; return ret;
} }
/* TODO: Cache this information. */
bool bool
ServerHasXEP421(ParseeData *data, char *from) ServerHasXEP421(ParseeData *data, char *from)
{ {
@ -153,32 +155,84 @@ ServerHasXEP421(ParseeData *data, char *from)
Free(server); Free(server);
return ret; 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 * char *
ParseeGetBridgedUser(ParseeData *data, XMLElement *stanza) ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force)
{ {
char *user, *xmpp_from, *type; 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) if (!data || !stanza)
{ {
return NULL; return NULL;
} }
xmpp_from = HashMapGet(stanza->attrs, "from"); xmpp_from = force ? force : HashMapGet(stanza->attrs, "from");
type = HashMapGet(stanza->attrs, "type"); type = HashMapGet(stanza->attrs, "type");
decode_from = ParseeLookupJID(xmpp_from); decode_from = ParseeLookupJID(xmpp_from);
/* TODO: On semi-anonymous MUCs, it might be preferable to use a is_chat = StrEquals(type, "chat");
* form of the occupant ID as the base, as it is more unique, and if (!is_chat)
* less prone to trigger the character limit on Matrix. {
* I'll need to detect these first.... has_anon = ServerHasXEP421(data, xmpp_from);
* is_anon = has_anon && StrEquals(xmpp_from, decode_from);
* See: https://xmpp.org/extensions/xep-0421.html */ }
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( user = ParseeEncodeJID(
data->config, data->config,
decode_from, decode_from,
StrEquals(type, "chat") type ? is_chat : false
); );
Free(decode_from); Free(decode_from);
return user; return user;
}
Free(decode_from);
return ScrambleOID(data, occ_id);
} }

View file

@ -229,15 +229,6 @@ ParseeXMPPThread(void *argp)
XMLElement * XMLElement *
ParseeAwaitStanza(char *identifier, int64_t timeout) 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 /* 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 * Cytoplasm's Malloc wrapper(which are essentially the same thing, plus
* some memchecking as of now), or the stack, as done previously. * 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 * 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, * 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. * 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. * 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/ * 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. */ * 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. /* Convert into an absolute timeout.
* ================================= * =================================
@ -282,29 +284,24 @@ ParseeAwaitStanza(char *identifier, int64_t timeout)
pthread_mutex_lock(&await_lock); pthread_mutex_lock(&await_lock);
pthread_cond_init(&awa->condition, NULL); pthread_cond_init(&awa.condition, NULL);
pthread_mutex_init(&awa->cond_lock, NULL); pthread_mutex_init(&awa.cond_lock, NULL);
awa->stanza = NULL; awa.stanza = NULL;
if (HashMapGet(await_table, identifier)) HashMapSet(await_table, identifier, &awa);
{
HashMapDelete(await_table, identifier);
}
HashMapSet(await_table, identifier, awa);
pthread_mutex_unlock(&await_lock); pthread_mutex_unlock(&await_lock);
pthread_mutex_lock(&awa->cond_lock); pthread_mutex_lock(&awa.cond_lock);
while (!awa->stanza) while (!awa.stanza)
{ {
int code; int code;
if (timeout <= 0) if (timeout <= 0)
{ {
pthread_cond_wait(&awa->condition, &awa->cond_lock); pthread_cond_wait(&awa.condition, &awa.cond_lock);
continue; continue;
} }
code = pthread_cond_timedwait(&awa->condition, &awa->cond_lock, &ts); code = pthread_cond_timedwait(&awa.condition, &awa.cond_lock, &ts);
if (code == ETIMEDOUT) if (code == ETIMEDOUT)
{ {
/* Timeout detected, give up regardless of the status of our /* Timeout detected, give up regardless of the status of our
@ -319,11 +316,10 @@ ParseeAwaitStanza(char *identifier, int64_t timeout)
} }
} }
stanza = awa->stanza; stanza = awa.stanza;
pthread_mutex_unlock(&awa->cond_lock); pthread_mutex_unlock(&awa.cond_lock);
pthread_cond_destroy(&awa->condition); pthread_cond_destroy(&awa.condition);
pthread_mutex_destroy(&awa->cond_lock); pthread_mutex_destroy(&awa.cond_lock);
free(awa);
return stanza; return stanza;
} }

View file

@ -180,7 +180,7 @@ IQResult(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
mxc = ASUpload(args->config, datastream, length, "image/png"); mxc = ASUpload(args->config, datastream, length, "image/png");
jid = ParseeLookupJID(from); jid = ParseeLookupJID(from);
from_matrix = ParseeEncodeJID(args->config, jid, false); from_matrix = ParseeGetBridgedUser(args, stanza);
ASSetAvatar(args->config, from_matrix, mxc); ASSetAvatar(args->config, from_matrix, mxc);
JsonValueFree(JsonSet( JsonValueFree(JsonSet(

View file

@ -148,11 +148,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
return false; return false;
} }
if (ServerHasXEP421(args, HashMapGet(stanza->attrs, "from")))
{
}
to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to")); to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
decode_from = ParseeLookupJID(from); decode_from = ParseeLookupJID(from);
from_matrix = ParseeEncodeJID(args->config, decode_from, true); from_matrix = ParseeEncodeJID(args->config, decode_from, true);

View file

@ -76,8 +76,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
char *from = NULL; char *from = NULL;
char *type = HashMapGet(stanza->attrs, "type"); char *type = HashMapGet(stanza->attrs, "type");
char *room = ParseeGetBridgedRoom(args, stanza); char *room = ParseeGetBridgedRoom(args, stanza);
char *decode_from = ParseeLookupJID(oid); char *decode_from, *real_matrix;
char *real_matrix = ParseeDecodeMXID(decode_from);
char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false); char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false);
char *affiliation = HashMapGet(item->attrs, "affiliation"); char *affiliation = HashMapGet(item->attrs, "affiliation");
int power_level = 0; int power_level = 0;
@ -85,10 +84,18 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
Free(trim); Free(trim);
if (jid)
{
ParseePushJIDTable(oid, jid);
}
decode_from = ParseeLookupJID(oid);
real_matrix = ParseeDecodeMXID(decode_from);
if (!real_matrix || *real_matrix != '@') if (!real_matrix || *real_matrix != '@')
{ {
Free(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")) if (StrEquals(affiliation, "owner"))
@ -163,10 +170,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
} }
} }
if (jid)
{
ParseePushJIDTable(oid, jid);
}
Free(from); Free(from);
Free(decode_from); Free(decode_from);
@ -179,8 +182,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
{ {
XMLElement *status_data = ArrayGet(status->children, 0); XMLElement *status_data = ArrayGet(status->children, 0);
char *decode_from = ParseeLookupJID(oid); char *decode_from = ParseeLookupJID(oid);
char *trimmed = ParseeTrimJID(decode_from); char *from_matrix = ParseeGetBridgedUser(args, stanza);
char *from_matrix = ParseeEncodeJID(args->config, trimmed, false);
char *status_str = NULL; char *status_str = NULL;
if (status_data) if (status_data)
{ {
@ -199,7 +201,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
Free(decode_from); Free(decode_from);
Free(from_matrix); Free(from_matrix);
Free(trimmed);
} }
if (vc) if (vc)
{ {

View file

@ -78,4 +78,5 @@ void PresenceStanza(ParseeData *args, XMLElement *stanza);
bool ServerHasXEP421(ParseeData *data, char *from); 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)