From fae9eb44731609cb756b6e4f6fe6ad3de3aef2a1 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Tue, 28 Feb 2023 15:17:11 +0000 Subject: [PATCH] Implement password-based user interactive authentication. --- TODO.txt | 31 +++++++++-------------- src/Routes/RouteRegister.c | 3 ++- src/Uia.c | 50 ++++++++++++++++++++++++++++++++++++-- src/User.c | 4 +-- src/include/Uia.h | 2 +- 5 files changed, 64 insertions(+), 26 deletions(-) diff --git a/TODO.txt b/TODO.txt index ad78780..9e997bd 100644 --- a/TODO.txt +++ b/TODO.txt @@ -13,9 +13,6 @@ Milestone: v0.2.0 [ ] Abstract /email/requestToken and /msidsn/requestToken -[x] Json API - [x] Trailing commas should not be allowed in arrays and objects - [x] Fix empty arrays not parsing [~] Db API [x] If object is in cache, but doesn't exist on disk, delete from cache [ ] Allow cache to be totally disabled (no MIN_CACHE_SIZE) @@ -26,25 +23,13 @@ Milestone: v0.2.0 [x] Delete refresh token if present [ ] Logout all [ ] Login fallback (static HTML page) -[~] User Interactive - [ ] Passwords - [ ] Registration tokens - [~] Caller builds flows - [ ] Document Uia (move docs from Matrix) -[x] Non-JSON endpoints - [x] Home page (like Synapse's "it works!") +[x] User Interactive + [x] Passwords + [x] Caller builds flows [ ] Document new User functions [ ] Document new JSON functions - -[x] Refactor usage of StrDuplicate() - - Functions that keep strings do the duplication, - NOT their callers; callers free strings when they are - done with them. - [x] Remove HashMapGetKey() function - [x] HashMap - [x] JsonValueString() - [x] Db +[ ] Document Uia (move docs from Matrix) Milestone: v0.3.0 ----------------- @@ -55,10 +40,16 @@ Milestone: v0.3.0 [ ] Multi-output [ ] HTTP Client +[ ] Move configuration to database + - How is the initial configuration done? + [ ] /_telodendria/admin/config endpoint + [ ] Refactor TelodendriaConfig to just Config (ConfigLock() and ConfigUnlock()) + [ ] Client-Server API [ ] 4: Token-based user registration - [ ] Refactor user-interactive auth flow + [ ] Implement user-interactive auth flow [ ] Token validity endpoint + [ ] Add m.login.registration_token to registration endpoint flow [ ] 4: Account management [ ] Deactivate [ ] Change password diff --git a/src/Routes/RouteRegister.c b/src/Routes/RouteRegister.c index 9fe2e5b..4c7723c 100644 --- a/src/Routes/RouteRegister.c +++ b/src/Routes/RouteRegister.c @@ -112,7 +112,8 @@ ROUTE_IMPL(RouteRegister, args) /* TODO: Add registration token flow */ uiaResult = UiaComplete(uiaFlows, args->context, - args->matrixArgs->db, request, &response); + args->matrixArgs->db, request, &response, + args->matrixArgs->config); if (uiaResult < 0) { diff --git a/src/Uia.c b/src/Uia.c index 4517a3c..8348638 100644 --- a/src/Uia.c +++ b/src/Uia.c @@ -31,6 +31,7 @@ #include #include +#include struct UiaStage { @@ -201,7 +202,7 @@ UiaBuildStage(char *type, HashMap * params) int UiaComplete(Array * flows, HttpServerContext * context, Db * db, - HashMap * request, HashMap ** response) + HashMap * request, HashMap ** response, TelodendriaConfig * config) { JsonValue *val; HashMap *auth; @@ -334,7 +335,52 @@ UiaComplete(Array * flows, HttpServerContext * context, Db * db, } else if (strcmp(authType, "m.login.password") == 0) { - /* TODO */ + char *password = JsonValueAsString(HashMapGet(auth, "password")); + HashMap *identifier = JsonValueAsObject(HashMapGet(auth, "identifier")); + char *type; + UserId *userId; + User *user; + + if (!password || !identifier) + { + HttpResponseStatus(context, HTTP_UNAUTHORIZED); + ret = BuildResponse(flows, db, response, session, dbRef); + goto finish; + } + + type = JsonValueAsString(HashMapGet(identifier, "type")); + userId = UserParseId(JsonValueAsString(HashMapGet(identifier, "user")), + config->serverName); + + if (!type || strcmp(type, "m.id.user") != 0 + || !userId || strcmp(userId->server, config->serverName) != 0) + { + HttpResponseStatus(context, HTTP_UNAUTHORIZED); + ret = BuildResponse(flows, db, response, session, dbRef); + UserFreeId(userId); + goto finish; + } + + user = UserLock(db, userId->localpart); + if (!user) + { + HttpResponseStatus(context, HTTP_UNAUTHORIZED); + ret = BuildResponse(flows, db, response, session, dbRef); + UserFreeId(userId); + goto finish; + } + + if (!UserCheckPassword(user, password)) + { + HttpResponseStatus(context, HTTP_UNAUTHORIZED); + ret = BuildResponse(flows, db, response, session, dbRef); + UserFreeId(userId); + UserUnlock(user); + goto finish; + } + + UserFreeId(userId); + UserUnlock(user); } else if (strcmp(authType, "m.login.registration_token") == 0) { diff --git a/src/User.c b/src/User.c index 8935658..3c2f3aa 100644 --- a/src/User.c +++ b/src/User.c @@ -657,8 +657,8 @@ finish: return userId; } -void -UserFreeId(UserId *id) +void +UserFreeId(UserId * id) { if (id) { diff --git a/src/include/Uia.h b/src/include/Uia.h index 0ee4fa3..209ce91 100644 --- a/src/include/Uia.h +++ b/src/include/Uia.h @@ -41,7 +41,7 @@ extern void UiaCleanup(MatrixHttpHandlerArgs *); extern int - UiaComplete(Array *, HttpServerContext *, Db *, HashMap *, HashMap **); + UiaComplete(Array *, HttpServerContext *, Db *, HashMap *, HashMap **, TelodendriaConfig *); extern void UiaFlowsFree(Array *);