Add UserIdParse() and UserIdFree() functions.

The spec says that a username can be either just the localpart, or a
localpart and a server. This commit now ensures that the login endpoint
actually handles usernames properly by calling the proper parsing
functions.
This commit is contained in:
Jordan Bancino 2023-02-28 13:44:34 +00:00
parent 58dae3a0c9
commit e2806bc810
3 changed files with 94 additions and 4 deletions

View file

@ -48,7 +48,7 @@ ROUTE_IMPL(RouteLogin, args)
char *password; char *password;
char *type; char *type;
char *username; UserId *userId = NULL;
Db *db = args->matrixArgs->db; Db *db = args->matrixArgs->db;
@ -160,9 +160,17 @@ ROUTE_IMPL(RouteLogin, args)
break; break;
} }
username = JsonValueAsString(val); userId = UserParseId(JsonValueAsString(val),
args->matrixArgs->config->serverName);
if (!userId)
{
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
response = MatrixErrorCreate(M_BAD_JSON);
break;
}
if (!UserExists(db, username)) if (strcmp(userId->server, args->matrixArgs->config->serverName) != 0
|| !UserExists(db, userId->localpart))
{ {
HttpResponseStatus(args->context, HTTP_FORBIDDEN); HttpResponseStatus(args->context, HTTP_FORBIDDEN);
response = MatrixErrorCreate(M_FORBIDDEN); response = MatrixErrorCreate(M_FORBIDDEN);
@ -225,7 +233,7 @@ ROUTE_IMPL(RouteLogin, args)
refreshToken = JsonValueAsBoolean(val); refreshToken = JsonValueAsBoolean(val);
} }
user = UserLock(db, username); user = UserLock(db, userId->localpart);
if (!user) if (!user)
{ {
@ -284,6 +292,7 @@ ROUTE_IMPL(RouteLogin, args)
break; break;
} }
UserFreeId(userId);
JsonFree(request); JsonFree(request);
return response; return response;
} }

View file

@ -598,3 +598,72 @@ UserDeleteToken(User * user, char *token)
return 1; return 1;
} }
UserId *
UserParseId(char *id, char *defaultServer)
{
UserId *userId;
if (!id)
{
return NULL;
}
id = StrDuplicate(id);
if (!id)
{
return NULL;
}
userId = Malloc(sizeof(UserId));
if (!userId)
{
goto finish;
}
/* Fully-qualified user ID */
if (*id == '@')
{
char *localStart = id + 1;
char *serverStart = localStart;
while (*serverStart != ':' && *serverStart != '\0')
{
serverStart++;
}
if (*serverStart == '\0')
{
Free(userId);
userId = NULL;
goto finish;
}
*serverStart = '\0';
serverStart++;
userId->localpart = StrDuplicate(localStart);
userId->server = StrDuplicate(serverStart);
}
else
{
/* Treat it as just a localpart */
userId->localpart = StrDuplicate(id);
userId->server = StrDuplicate(defaultServer);
}
finish:
Free(id);
return userId;
}
void
UserFreeId(UserId *id)
{
if (id)
{
Free(id->localpart);
Free(id->server);
Free(id);
}
}

View file

@ -42,6 +42,12 @@ typedef struct UserLoginInfo
char *refreshToken; char *refreshToken;
} UserLoginInfo; } UserLoginInfo;
typedef struct UserId
{
char *localpart;
char *server;
} UserId;
extern int extern int
UserValidate(char *, char *); UserValidate(char *, char *);
@ -93,4 +99,10 @@ extern void
extern int extern int
UserDeleteToken(User *, char *); UserDeleteToken(User *, char *);
extern UserId *
UserParseId(char *, char *);
extern void
UserFreeId(UserId *);
#endif /* TELODENDRIA_USER_H */ #endif /* TELODENDRIA_USER_H */