Implement authorization

Read username from user config, check existence of user and then check password.
This commit was merged in pull request #1.
This commit is contained in:
2026-06-11 16:26:55 +02:00
parent b07043a226
commit 9b75e87149
5 changed files with 189 additions and 125 deletions

View File

@@ -1,15 +1,15 @@
#include <stdio.h>
#include <sha256.h>
#include <dirent.h>
#define NOH_IMPLEMENTATION
#include "noh.h"
#define SV Noh_String_View
#define sv noh_sv_from_cstr
Noh_Arena temp;
#include "path.c"
#include "users.c"
Noh_Arena temp;
#define SV Noh_String_View
#define sv noh_sv_from_cstr
static void show_usage(char *program_name, char *error) {
noh_log(NOH_INFO, "Usage:");
@@ -35,42 +35,6 @@ static void show_usage(char *program_name, char *error) {
exit(1);
}
Noh_String hash_password(Noh_String_View username, Noh_String_View password) {
// Build the sha input string.
Noh_String input = {0};
noh_string_append_sv(&input, username);
noh_string_append_cstr(&input, "<><>");
noh_string_append_sv(&input, password);
// Calculate the hash.
SHA256_CTX ctx = {0};
BYTE hash[32];
sha256_init(&ctx);
sha256_update(&ctx, (BYTE*)input.elems, input.count);
sha256_final(&ctx, hash);
// Build the result string.
noh_arena_save(&temp);
Noh_String result = {0};
for (int i = 0; i < 32; i++) {
noh_string_append_cstr(&result, noh_arena_sprintf(&temp, "%02x", hash[i]));
}
noh_arena_reset(&temp);
return result;
}
typedef struct {
Noh_String_View username;
Noh_String_View hash;
} User;
typedef struct {
User *elems;
size_t count;
size_t capacity;
} Users;
bool remove_directory(char *path) {
noh_arena_save(&temp);
bool result = true;
@@ -103,55 +67,6 @@ bool remove_directory(char *path) {
return result;
}
bool read_users_file(char *file_path, Users *users) {
Noh_String users_file = {0};
noh_log(NOH_INFO, "Reading users file: %s", file_path);
if (!noh_file_exists(file_path)) return true;
if (!noh_string_read_file(&users_file, file_path)) return false;
Noh_String_View users_file_sv = noh_sv_from_string(users_file);
Noh_String_View line = {0};
for (size_t i = 0; users_file_sv.count > 0; i++) {
line = noh_sv_chop_line(&users_file_sv);
// Ignore empty lines.
noh_sv_trim_space(&line);
if (line.count == 0) continue;
Noh_String_View un = noh_sv_chop_by_delim(&line, ':');
if (line.count == 0) {
noh_log(NOH_ERROR, "%s %zu: Line not in username:hash format.", file_path, i);
noh_string_free(&users_file);
return false;
}
noh_da_append(users, ((User){ .username = un, .hash = line }));
}
return true;
}
bool write_users_file(char *file_path, Users *users, User *user_to_skip) {
Noh_String users_file = {0};
for (size_t i = 0; i < users->count; i++) {
User *u = &users->elems[i];
if (u == user_to_skip) continue;
noh_string_append_sv(&users_file, u->username);
noh_string_append_cstr(&users_file, ":");
noh_string_append_sv(&users_file, u->hash);
noh_string_append_cstr(&users_file, "\n");
}
bool result = noh_string_write_file(&users_file, file_path);
noh_string_free(&users_file);
return result;
}
/// Prompts a user with a question and returns their response.
bool prompt_user(char *question) {
noh_arena_save(&temp);
@@ -168,18 +83,22 @@ bool prompt_user(char *question) {
}
bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_String_View password) {
bool result = true;
// Read the file.
Noh_String_View file_name = noh_sv_from_cstr("users.conf");
Noh_String users_file_path = build_path(false, &library_path, &file_name);
noh_string_append_null(&users_file_path);
// Build users map.
Noh_String hashed = {0};
Users users = {0};
if (!read_users_file(users_file_path.elems, &users)) return false;
bool result = true;
Noh_String users_file = {0};
Noh_String user_folder_path = {0};
if (!read_users_file(users_file_path.elems, &users_file, &users)) noh_return_defer(false);
// Hash the password.
Noh_String hashed = hash_password(username, password);
hashed = hash_password(username, password);
// Find the user in the map of users.
for (size_t i = 0; i < users.count; i++) {
@@ -197,7 +116,7 @@ bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_S
if (!write_users_file(users_file_path.elems, &users, NULL)) noh_return_defer(false);
// Create user folder if needed.
Noh_String user_folder_path = build_path(false, &library_path, &username);
user_folder_path = build_path(false, &library_path, &username);
noh_string_append_null(&user_folder_path);
if (!noh_mkdir_if_needed(user_folder_path.elems)) noh_return_defer(false);
@@ -210,25 +129,32 @@ bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_S
if (!write_users_file(users_file_path.elems, &users, NULL)) noh_return_defer(false);
// Create user folder if needed.
Noh_String user_folder_path = build_path(false, &library_path, &username);
user_folder_path = build_path(false, &library_path, &username);
noh_string_append_null(&user_folder_path);
if (!noh_mkdir_if_needed(user_folder_path.elems)) noh_return_defer(false);
defer:
noh_string_free(&users_file_path);
noh_string_free(&user_folder_path);
noh_da_free(&users);
noh_string_free(&users_file);
noh_string_free(&hashed);
return result;
}
bool delete_user(Noh_String_View library_path, Noh_String_View username) {
bool result = true;
// Read the file.
Noh_String_View file_name = noh_sv_from_cstr("users.conf");
Noh_String users_file_path = build_path(false, &library_path, &file_name);
noh_string_append_null(&users_file_path);
// Build users map.
Noh_String user_folder_path = {0};
Users users = {0};
if (!read_users_file(users_file_path.elems, &users)) return false;
bool result = true;
Noh_String users_file = {0};
if (!read_users_file(users_file_path.elems, &users_file, &users)) noh_return_defer(false);
// Check if the user exists.
User *user_to_delete = NULL;
@@ -256,7 +182,7 @@ bool delete_user(Noh_String_View library_path, Noh_String_View username) {
if (!write_users_file(users_file_path.elems, &users, user_to_delete)) noh_return_defer(false);
// Prompt to delete the user's library folder.
Noh_String user_folder_path = build_path(false, &library_path, &username);
user_folder_path = build_path(false, &library_path, &username);
noh_string_append_null(&user_folder_path);
if (!noh_file_exists(user_folder_path.elems)) noh_return_defer(true);
@@ -266,7 +192,10 @@ bool delete_user(Noh_String_View library_path, Noh_String_View username) {
}
defer:
noh_string_free(&user_folder_path);
noh_string_free(&users_file_path);
noh_da_free(&users);
noh_string_free(&users_file);
return result;
}
@@ -278,11 +207,13 @@ bool list_users(Noh_String_View library_path) {
// Build users map.
Users users = {0};
if (!read_users_file(users_file_path.elems, &users)) return false;
Noh_String users_file = {0};
if (!read_users_file(users_file_path.elems, &users_file, &users)) return false;
if (users.count == 0) {
noh_log(NOH_INFO, "No users registered.");
noh_da_free(&users);
noh_string_free(&users_file);
return true;
}
@@ -294,7 +225,9 @@ bool list_users(Noh_String_View library_path) {
}
noh_arena_reset(&temp);
noh_string_free(&users_file_path);
noh_da_free(&users);
noh_string_free(&users_file);
return true;
}