From e882693c788ec0d38301e1b6cc6847bbfc5427b5 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Fri, 14 Apr 2023 23:59:40 +0000 Subject: [PATCH] Add route for requestToken endpoints. --- TODO.txt | 4 +- src/Routes.c | 2 - src/Routes/RouteRequestToken.c | 149 +++++++++++++++++++++++++++++++++ src/Str.c | 20 +++++ src/include/Routes.h | 1 + src/include/Str.h | 3 + 6 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/Routes/RouteRequestToken.c diff --git a/TODO.txt b/TODO.txt index 6f2fab1..cdba16f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -44,10 +44,10 @@ Milestone: v0.3.0 [x] Pass TLS certs and keys into HttpServer [x] Debug OpenSSL [x] Replace all usages of curl with http -[~] Proper HTTP request router +[x] Proper HTTP request router [x] Support regex matching [x] Replace current routing system - [ ] Add route for requestToken endpoints + [x] Add route for requestToken endpoints [x] Move TelodendriaBuildRouter() to Routes [ ] Token permissions diff --git a/src/Routes.c b/src/Routes.c index 0c76add..b7f362f 100644 --- a/src/Routes.c +++ b/src/Routes.c @@ -60,10 +60,8 @@ RouterBuild(void) R("/_matrix/client/v1/register/m.login.registration_token/validity", RouteTokenValid); -#if 0 R("/_matrix/client/v3/account/password/(email|msisdn)/requestToken", RouteRequestToken); R("/_matrix/client/v3/register/(email|msisdn)/requestToken", RouteRequestToken); -#endif R("/_matrix/client/v3/profile/(.*)", RouteUserProfile); R("/_matrix/client/v3/profile/(.*)/(avatar_url|displayname)", RouteUserProfile); diff --git a/src/Routes/RouteRequestToken.c b/src/Routes/RouteRequestToken.c new file mode 100644 index 0000000..8f36674 --- /dev/null +++ b/src/Routes/RouteRequestToken.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + +#include +#include + +ROUTE_IMPL(RouteRequestToken, path, argp) +{ + RouteArgs *args = argp; + char *type = ArrayGet(path, 0); + HashMap *request; + HashMap *response; + JsonValue *val; + char *str; + + if (HttpRequestMethodGet(args->context) != HTTP_POST) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + return MatrixErrorCreate(M_UNRECOGNIZED); + } + + request = JsonDecode(HttpServerStream(args->context)); + if (!request) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + return MatrixErrorCreate(M_NOT_JSON); + } + + val = HashMapGet(request, "client_secret"); + if (!val || JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + str = JsonValueAsString(val); + if (strlen(str) > 255 || StrBlank(str)) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + val = HashMapGet(request, "send_attempt"); + if (!val || JsonValueType(val) != JSON_INTEGER) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + val = HashMapGet(request, "next_link"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + val = HashMapGet(request, "id_access_token"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + val = HashMapGet(request, "id_server"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + if (strcmp(type, "email") == 0) + { + val = HashMapGet(request, "email"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + } + else if (strcmp(type, "msisdn") == 0) + { + val = HashMapGet(request, "country"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + str = JsonValueAsString(val); + if (strlen(str) != 2) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + + val = HashMapGet(request, "phone_number"); + if (val && JsonValueType(val) != JSON_STRING) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON); + goto finish; + } + } + else + { + /* Should not be possible */ + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + response = MatrixErrorCreate(M_UNKNOWN); + goto finish; + } + + HttpResponseStatus(args->context, HTTP_FORBIDDEN); + response = MatrixErrorCreate(M_THREEPID_DENIED); + +finish: + JsonFree(request); + return response; +} diff --git a/src/Str.c b/src/Str.c index 5b699f9..0d07c82 100644 --- a/src/Str.c +++ b/src/Str.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -194,6 +195,25 @@ StrConcat(size_t nStr,...) return str; } +int +StrBlank(const char *str) +{ + int blank = 1; + size_t i = 0; + + while (str[i]) + { + blank &= isspace(str[i]); + /* No need to continue if we don't have a blank */ + if (!blank) + { + break; + } + i++; + } + return blank; +} + char * StrRandom(size_t len) { diff --git a/src/include/Routes.h b/src/include/Routes.h index 8c83c92..bb93de0 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -63,6 +63,7 @@ ROUTE(RouteWhoami); ROUTE(RouteChangePwd); ROUTE(RouteTokenValid); ROUTE(RouteUserProfile); +ROUTE(RouteRequestToken); ROUTE(RouteStaticDefault); ROUTE(RouteStaticLogin); diff --git a/src/include/Str.h b/src/include/Str.h index ec0bbee..d6aed71 100644 --- a/src/include/Str.h +++ b/src/include/Str.h @@ -38,6 +38,9 @@ extern char * extern char * StrConcat(size_t,...); +extern int + StrBlank(const char *str); + extern char * StrRandom(size_t);