[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);
XMLFreeElement(iq);
ret = ParseeAwaitStanza(identifier, 250);
ret = ParseeAwaitStanza(identifier, 5000);
Free(identifier);
return ret;
}

View file

@ -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");

View file

@ -3,6 +3,7 @@
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Sha.h>
#include <string.h>
@ -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);
}

View file

@ -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;
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);
}
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;
}

View file

@ -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(

View file

@ -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);

View file

@ -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)
{

View file

@ -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)