Implement authorization
Read username from user config, check existence of user and then check password.
This commit is contained in:
92
src/server.c
92
src/server.c
@@ -5,25 +5,82 @@
|
||||
#define NOH_IMPLEMENTATION
|
||||
#include "noh.h"
|
||||
|
||||
#define NO_AUTH
|
||||
Noh_Arena temp;
|
||||
|
||||
#include "path.c"
|
||||
#include "users.c"
|
||||
|
||||
#define SV Noh_String_View
|
||||
#define sv noh_sv_from_cstr
|
||||
|
||||
/* To disable Basic auth for testing:
|
||||
#define NO_AUTH
|
||||
This will ignore any auth headers and always log in with username demo.
|
||||
*/
|
||||
|
||||
#define SV Noh_String_View
|
||||
#define sv noh_sv_from_cstr
|
||||
|
||||
Noh_Arena temp;
|
||||
|
||||
#include "id_store.c"
|
||||
#include "library.c"
|
||||
|
||||
typedef struct {
|
||||
SV base_path;
|
||||
SV library_name;
|
||||
} Settings;
|
||||
|
||||
// Authorizes the username from the Basic authorization info in the provided connection.
|
||||
// The username data is guaranteed to live as long as the connection lives.
|
||||
static bool authorize_user(struct MHD_Connection *connection, SV *username, Settings *settings) {
|
||||
#ifdef NO_AUTH
|
||||
(void)connection;
|
||||
|
||||
*username = sv("demo");
|
||||
return false;
|
||||
#else
|
||||
bool result = true;
|
||||
|
||||
struct MHD_BasicAuthInfo *auth = MHD_basic_auth_get_username_password3(connection);
|
||||
if (!auth) return false;
|
||||
|
||||
SV provided_username = { .elems = auth->username, .count = auth->username_len };
|
||||
SV provided_password = { .elems = auth->password, .count = auth->password_len };
|
||||
|
||||
// Read the users file.
|
||||
noh_arena_save(&temp);
|
||||
Noh_String_View file_name = noh_sv_from_cstr("users.conf");
|
||||
Noh_String users_file_path = build_path(false, &settings->base_path, &file_name);
|
||||
noh_string_append_null(&users_file_path);
|
||||
|
||||
Noh_String hashed = {0};
|
||||
Users users = {0};
|
||||
Noh_String users_file = {0};
|
||||
if (!read_users_file(users_file_path.elems, &users_file, &users)) noh_return_defer(false);
|
||||
|
||||
// Find the user in the users list.
|
||||
bool found_user = false;
|
||||
User *user = NULL;
|
||||
for (size_t i = 0; i < users.count && !found_user; i++) {
|
||||
user = &users.elems[i];
|
||||
|
||||
if (noh_sv_eq(provided_username, user->username)) found_user = true;
|
||||
}
|
||||
|
||||
if (!found_user) noh_return_defer(false);
|
||||
|
||||
// Hash the provided password.
|
||||
hashed = hash_password(provided_username, provided_password);
|
||||
|
||||
// Check the hash.
|
||||
if (!noh_sv_eq(noh_sv_from_string(hashed), user->hash)) noh_return_defer(false);
|
||||
|
||||
*username = provided_username;
|
||||
|
||||
defer:
|
||||
noh_string_free(&hashed);
|
||||
noh_da_free(&users);
|
||||
noh_string_free(&users_file_path);
|
||||
noh_string_free(&users_file);
|
||||
noh_arena_reset(&temp);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum MHD_Result send_response(struct MHD_Connection *connection, int status, SV message, bool xml) {
|
||||
struct MHD_Response *response = MHD_create_response_from_buffer(
|
||||
message.count, (void*)message.elems, MHD_RESPMEM_MUST_COPY);
|
||||
@@ -47,6 +104,8 @@ static enum MHD_Result send_epub_file(struct MHD_Connection *connection, int fil
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "id_store.c"
|
||||
#include "library.c"
|
||||
#include "opds_handler.c"
|
||||
#include "get_handler.c"
|
||||
|
||||
@@ -65,20 +124,7 @@ static enum MHD_Result request_handler(
|
||||
noh_log(NOH_INFO, "Request: %s %s %s", version, method, _url);
|
||||
|
||||
SV username;
|
||||
#ifdef NO_AUTH
|
||||
username = sv("demo");
|
||||
#else
|
||||
struct MHD_BasicAuthInfo *auth = MHD_basic_auth_get_username_password3(connection);
|
||||
if (!auth) return send_response(connection, 401, sv(""), false);
|
||||
|
||||
username = (SV){ .elems = auth->username, .count = auth->username_len };
|
||||
SV password = { .elems = auth->password, .count = auth->password_len };
|
||||
|
||||
// TODO: Read username from user config.
|
||||
if (!noh_sv_eq(password, sv("jaja"))) return send_response(connection, 401, sv(""), false);
|
||||
#endif
|
||||
|
||||
noh_log(NOH_INFO, "Authenticated as "Nsv_Fmt, Nsv_Arg(username));
|
||||
if (!authorize_user(connection, &username, &settings)) return send_response(connection, 401, sv(""), false);
|
||||
|
||||
if (strcmp(method, "GET") != 0) return send_response(connection, 405, sv(""), false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user