diff --git a/man/man3/Matrix.3 b/man/man3/Matrix.3 index 4a7d4d4..d565389 100644 --- a/man/man3/Matrix.3 +++ b/man/man3/Matrix.3 @@ -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 , diff --git a/src/Matrix.c b/src/Matrix.c index e365f53..d9af288 100644 --- a/src/Matrix.c +++ b/src/Matrix.c @@ -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; +} diff --git a/src/Routes/RouteRegister.c b/src/Routes/RouteRegister.c index 3ce3ad2..9cc922a 100644 --- a/src/Routes/RouteRegister.c +++ b/src/Routes/RouteRegister.c @@ -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) diff --git a/src/include/Matrix.h b/src/include/Matrix.h index fa11709..f005dff 100644 --- a/src/include/Matrix.h +++ b/src/include/Matrix.h @@ -89,4 +89,10 @@ extern HashMap * extern HashMap * MatrixRateLimit(HttpServerContext *, Db *); +extern int + MatrixUserValidate(char *, char *); + +extern int + MatrixHistoricalUserValidate(char *, char *); + #endif