[MOD] HMAC-based mediachecking

This commit is contained in:
LDA 2024-08-25 23:00:31 +02:00
commit 39cc04fc2e
6 changed files with 115 additions and 9 deletions

View file

@ -25,8 +25,8 @@ JoinMUC(ParseeData *data, HashMap *event, char *jid, char *muc, char *name)
while (!XMPPJoinMUC(data->jabber, jid, rev, true) && nonce < 32)
{
char *nonce_str = StrInt(nonce);
char *input = StrConcat(4, sender, name, data->id, nonce_str);
char *hex = ParseeSHA256(input);
char *input = StrConcat(3, sender, name, nonce_str);
char *hex = ParseeHMACS(data->id, input);
if (strlen(hex) >= 8)
{

76
src/Parsee/HMAC.c Normal file
View file

@ -0,0 +1,76 @@
/* CC0 implementation of a HMAC system based on Cytoplasm.
* Ignore the scary "Parsee.h", its practically unused. */
#include <Parsee.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Sha.h>
#include <Cytoplasm/Str.h>
#include <string.h>
/* A 64-byte key! */
static uint8_t *
ComputeKPad(char *key, uint8_t pad)
{
size_t klen;
uint8_t *kp;
uint8_t *kopad;
size_t i;
if ((klen = strlen(key)) <= 64)
{
kp = Malloc(klen * sizeof(uint8_t));
memcpy(kp, key, klen);
}
else
{
kp = (uint8_t *) Sha256(key);
klen = 32;
}
/* Now that we have K', lets compute it XORd with opad */
kopad = Malloc(64 * sizeof(uint8_t));
for (i = 0; i < 64; i++)
{
uint8_t byte = i < klen ? kp[i] : 0x00;
kopad[i] = byte ^ pad;
}
Free(kp);
return kopad;
}
char *
ParseeHMAC(char *key, uint8_t *msg, size_t msglen)
{
uint8_t *opad, *ipad;
uint8_t *innersha;
uint8_t *outer;
unsigned char *sha;
char *str;
if (!key || !msg || !msglen)
{
return NULL;
}
opad = ComputeKPad(key, 0x5C);
ipad = ComputeKPad(key, 0x36);
ipad = Realloc(ipad, 64 + msglen);
memcpy(ipad + 64, msg, msglen);
innersha = Sha256Raw(ipad, 64 + msglen);
outer = Malloc(64 + 32);
memcpy(outer, opad, 64);
memcpy(outer + 64, innersha, 32);
sha = Sha256Raw(outer, 64 + 32);
str = ShaToHex(sha, HASH_SHA256);
Free(innersha);
Free(outer);
Free(ipad);
Free(opad);
Free(sha);
return str;
}

View file

@ -667,7 +667,8 @@ ParseeToUnauth(ParseeData *data, char *mxc)
{
Uri *url = NULL;
char *ret;
#define PAT "%s/_matrix/client/v1/media/download/%s%s"
char *key, *hmac;
#define PAT "%s/_matrix/client/v1/media/download/%s%s?hmac=%s"
size_t l;
if (!data || !mxc)
{
@ -684,18 +685,25 @@ ParseeToUnauth(ParseeData *data, char *mxc)
return NULL;
}
key = StrConcat(2, url->host, url->path);
hmac = ParseeHMACS(data->id, key);
Free(key);
l = snprintf(NULL, 0,
PAT,
data->config->media_base,
url->host, url->path
url->host, url->path,
hmac
);
ret = Malloc(l + 3);
snprintf(ret, l + 1,
PAT,
data->config->media_base,
url->host, url->path
url->host, url->path,
hmac
);
UriFree(url);
Free(hmac);
return ret;
}

View file

@ -2,27 +2,41 @@
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <Matrix.h>
#include <Parsee.h>
#include <AS.h>
#include <string.h>
RouteHead(RouteMedia, arr, argp)
{
ParseeHttpArg *args = argp;
HttpClientContext *cctx;
HashMap *reqh;
HashMap *reqh, *params;
char *server = ArrayGet(arr, 0);
char *identi = ArrayGet(arr, 1);
char *path, *key, *val;
char *hmac, *chkmak = NULL;
params = HttpRequestParams(args->ctx);
hmac = HashMapGet(params, "hmac");
/* TODO: Make it check the DB for its validicity. "Purging" would be useful.
*/
if (!server || !identi)
{
char *concat = StrConcat(3, server, "/", identi);
chkmak = ParseeHMACS(args->data->id, concat);
Free(concat);
}
if (!server || !identi || !hmac || !StrEquals(hmac, chkmak))
{
Free(chkmak);
HttpResponseStatus(args->ctx, HTTP_BAD_REQUEST);
return MatrixCreateError("M_NOT_YET_UPLOADED", "No server/identifier");
}
Free(chkmak);
server = HttpUrlEncode(server);
identi = HttpUrlEncode(identi);

View file

@ -361,4 +361,12 @@ extern char * ParseeGenerateMTO(char *common_id);
* Modifies: the Parsee config */
extern void ParseeSetThreads(int xmpp, int http);
/** Computes an HMAC (with SHA-256) with a known key, and a generic message.
* --------------
* Returns: a hex representation of the HMAC[HEAP].
* Thrasher: Free
* Modifies: NOTHING */
extern char * ParseeHMAC(char *key, uint8_t *msg, size_t msglen);
#define ParseeHMACS(key, msg) ParseeHMAC(key, (uint8_t *) msg, strlen(msg))
#endif