From 5b51d9159ea104c10ae267d7392a548eecd0ebb2 Mon Sep 17 00:00:00 2001 From: LDA Date: Wed, 28 Aug 2024 19:55:04 +0200 Subject: [PATCH] [MOD] Stateless /message tokins --- src/User.c | 105 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 31 deletions(-) diff --git a/src/User.c b/src/User.c index 3990af0..ac539a2 100644 --- a/src/User.c +++ b/src/User.c @@ -24,11 +24,12 @@ */ #include #include -#include #include +#include +#include +#include #include #include -#include #include #include @@ -233,7 +234,10 @@ UserCreate(Db * db, char *name, char *password) if (!name) { - user->name = StrRandom(12); + char *casing = StrRandom(12); + + user->name = StrLower(casing); + Free(casing); } else { @@ -1501,28 +1505,74 @@ UserGetEvents(User *user, char *batch, char *roomId) return ret; } +static char * +EncodeMessageToken(char *room, char *event) +{ + size_t roomLen = room ? strlen(room) : 0; + size_t eventLen = event ? strlen(event) : 0; + size_t sum = roomLen + 1 + eventLen; + char concatenation[sum + 8]; + if (!room || !event) + { + return NULL; + } + + /* TODO: Consider setting an HMAC/signature to be sure + * that the token isn't forged. */ + memcpy(concatenation, room, roomLen); + concatenation[roomLen] = '|'; + memcpy(concatenation + roomLen + 1, event, eventLen); + return Base64Encode(concatenation, sum); +} +static bool +DecodeMessageToken(char *tokin, char **room, char **event) +{ + char *token, *nultoken; + char *off; + size_t len, roomLen; + if (!tokin || !room || !event) + { + return false; + } + + *room = NULL; + *event = NULL; + + len = Base64DecodedSize(tokin, strlen(tokin)); + token = Base64Decode(tokin, strlen(tokin)); + nultoken = Malloc(len + 1); + memcpy(nultoken, token, len); + nultoken[len] = '\0'; + Free(token); + + if (!(off = strchr(nultoken, '|'))) + { + Free(nultoken); + return false; + } + + roomLen = off - nultoken; + *room = Malloc(roomLen + 1); + memcpy(*room, nultoken, roomLen); + (*room)[roomLen] = '\0'; + + *event = StrDuplicate(off + 1); + + Free(nultoken); + return true; +} char * UserNewMessageToken(User *user, char *room, char *event) { - DbRef *messageRef; - HashMap *json; char *messageToken; if (!user || !room || !event) { return NULL; } - messageToken = StrRandom(16); - messageRef = DbCreate(user->db, - 4, "users", user->name, "msg", messageToken - ); - json = DbJson(messageRef); - - HashMapSet(json, "room", JsonValueString(room)); - HashMapSet(json, "from", JsonValueString(event)); - - DbUnlock(user->db, messageRef); + /* TODO: User checks, HMACs */ + messageToken = EncodeMessageToken(room, event); return messageToken; } @@ -1531,10 +1581,8 @@ UserFetchMessages(User *user, int n, char *token, char **next) { Array *messages = NULL; Array *nexts = NULL; - DbRef *messageRef; - HashMap *json; Room *room; - char *roomId; + char *roomId, *eId; size_t i; bool limited = false; @@ -1551,24 +1599,19 @@ UserFetchMessages(User *user, int n, char *token, char **next) dir = true; } - messageRef = DbLock(user->db, - 4, "users", user->name, "msg", token - ); - json = DbJson(messageRef); - if (!messageRef) + if (!DecodeMessageToken(token, &roomId, &eId)) { - /* Regenerate a new one */ return NULL; } - roomId = JsonValueAsString(HashMapGet(json, "room")); room = RoomLock(user->db, roomId); /* TODO (very important): CHECK IF THE USER IS ABLE TO SEE * HISTORY. THROUGHOUT THE STEPS HERE. */ if (!room) { - DbUnlock(user->db, messageRef); + Free(roomId); + Free(eId); return NULL; } @@ -1576,9 +1619,7 @@ UserFetchMessages(User *user, int n, char *token, char **next) messages = ArrayCreate(); /* A stack of elements to deal with the DAG. */ - ArrayAdd(nexts, - StrDuplicate(JsonValueAsString(HashMapGet(json, "from"))) - ); + ArrayAdd(nexts, StrDuplicate(eId)); for (i = 0; i < (size_t) n && ArraySize(nexts); i++) { char *curr = ArrayDelete(nexts, ArraySize(nexts) - 1); @@ -1588,7 +1629,8 @@ UserFetchMessages(User *user, int n, char *token, char **next) Free(curr); - /* Push event into our message list. */ + /* Push event into our message list. + * TODO: Check if the user has the right to see the event/room. */ ArrayAdd(messages, event); prevEvents = JsonValueAsArray(HashMapGet(event, "prev_events")); @@ -1627,12 +1669,13 @@ UserFetchMessages(User *user, int n, char *token, char **next) *next = UserNewMessageToken(user, roomId, eId); } - DbUnlock(user->db, messageRef); for (i = 0; i < ArraySize(messages); i++) { HashMap *e = ArrayGet(messages, i); ArraySet(messages, i, JsonValueObject(e)); } + Free(roomId); + Free(eId); return messages; }