Add MatrixUserValidate() and MatrixHistoricalUserValidate()

This commit is contained in:
Jordan Bancino 2022-12-18 20:20:08 +00:00
parent f32e5eafce
commit c0bd70a391
4 changed files with 102 additions and 12 deletions

View file

@ -1,4 +1,4 @@
.Dd $Mdocdate: December 16 2022 $
.Dd $Mdocdate: December 18 2022 $
.Dt MATRIX 3
.Os Telodendria Project
.Sh NAME
@ -16,6 +16,10 @@
.Fn MatrixAuthenticate "HttpServerContext *" "Db *"
.Ft HashMap *
.Fn MatrixRateLimit "HttpServerContext *" "Db *"
.Ft int
.Fn MatrixUserValidate "char *" "char *"
.Ft int
.Fn MatrixHistoricalUserValidate "char *" "char *"
.Sh DESCRIPTION
.Nm
provides some helper functions that bind to the
@ -100,6 +104,18 @@ user is authenticated.
determines whether or not the request should be rate limited. It is
expected that this will occur before most, if not all of the caller's
logic.
.Pp
.Fn MatrixUserValidate
and
.Fn MatrixHistoricalUserValidate
take a Matrix ID local part and a domain name, in that order, and
check to see if it is valid according to the specification.
.Fn MatrixUserValidate
checks for a strictly spec-compliant user ID, but the specification
also requires historical usernames which do not meet the requirements
of the latest speck to also be supported, so
.Fn MatrixHistoricalUserValidate
can be used in cases where historical usernames may be dealt with.
.Sh RETURN VALUES
.Pp
.Fn MatrixErrorCreate
@ -115,6 +131,12 @@ return NULL, then the caller can proceed assuming that all is well
and no further action needs to be taken. If these functions do not
return NULL, then the returned JSON object should be passed along to the
client immediately without continuing.
.Pp
.Fn MatrixUserValidate
and
.Fn MatrixHistoricalUserValidate
return a boolean value, where 0 indicates the provided ID is
not valid, and non-zero values indicate the provided ID is valid.
.Sh SEE ALSO
.Xr HttpServer 3 ,
.Xr Log 3 ,

View file

@ -463,3 +463,57 @@ MatrixRateLimit(HttpServerContext *context, Db *db)
(void) db;
return NULL;
}
int
MatrixUserValidate(char *localpart, char *domain)
{
size_t maxLen = 255 - strlen(domain) - 1;
size_t i = 0;
while (localpart[i])
{
char c = localpart[i];
if (i > maxLen)
{
return 0;
}
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
(c == '.') || (c == '_') || (c == '=') || (c == '-') ||
(c == '/')))
{
return 0;
}
i++;
}
return 1;
}
int
MatrixHistoricalUserValidate(char *localpart, char *domain)
{
size_t maxLen = 255 - strlen(domain) - 1;
size_t i = 0;
while (localpart[i])
{
char c = localpart[i];
if (i > maxLen)
{
return 0;
}
if (!(c >= 0x21 && c <= 0x39) || (c >= 0x3B && c <= 0x7E))
{
return 0;
}
i++;
}
return 1;
}

View file

@ -70,6 +70,25 @@ ROUTE_IMPL(RouteRegister, args)
goto finish;
}
val = HashMapGet(request, "username");
if (val)
{
if (JsonValueType(val) != JSON_STRING)
{
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
response = MatrixErrorCreate(M_BAD_JSON);
goto finish;
}
username = JsonValueAsString(val);
if (!MatrixUserValidate(username, args->matrixArgs->config->serverName))
{
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
response = MatrixErrorCreate(M_INVALID_USERNAME);
goto finish;
}
}
response = MatrixUserInteractiveAuth(args->context,
args->matrixArgs->db, request);
@ -88,17 +107,6 @@ ROUTE_IMPL(RouteRegister, args)
goto finish;
}
val = HashMapGet(request, "username");
if (val)
{
if (JsonValueType(val) != JSON_STRING)
{
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
response = MatrixErrorCreate(M_BAD_JSON);
goto finish;
}
username = JsonValueAsString(val);
}
val = HashMapGet(request, "password");
if (!val)

View file

@ -89,4 +89,10 @@ extern HashMap *
extern HashMap *
MatrixRateLimit(HttpServerContext *, Db *);
extern int
MatrixUserValidate(char *, char *);
extern int
MatrixHistoricalUserValidate(char *, char *);
#endif