#include "auth.h" #include #include #include #include #include "util.h" #define ARGON2_T_COST 3 #define ARGON2_M_COST (64 * 1024) #define ARGON2_PARALLELISM 1 #define ARGON2_SALT_LEN 16 #define ARGON2_HASH_LEN 32 int auth_hash_password(const char *pw, char **out_phc) { if (!pw) return -1; unsigned char salt[ARGON2_SALT_LEN]; if (util_random(salt, sizeof salt) != 0) return -1; char encoded[256]; int rc = argon2id_hash_encoded(ARGON2_T_COST, ARGON2_M_COST, ARGON2_PARALLELISM, pw, strlen(pw), salt, sizeof salt, ARGON2_HASH_LEN, encoded, sizeof encoded); if (rc != ARGON2_OK) return -1; *out_phc = xstrdup(encoded); return 0; } int auth_verify_password(const char *phc, const char *pw) { if (!phc || !pw) return -1; return argon2id_verify(phc, pw, strlen(pw)) == ARGON2_OK ? 0 : -1; } void auth_hash_token(const char *token, unsigned char out[32]) { util_sha256(token, strlen(token), out); } char *auth_generate_token(void) { unsigned char raw[32]; if (util_random(raw, sizeof raw) != 0) { fprintf(stderr, "fatal: no entropy source\n"); exit(1); } char *body = util_b64url(raw, sizeof raw); size_t n = strlen(body) + sizeof AUTH_TOKEN_PREFIX + 1; char *token = xmalloc(n); snprintf(token, n, "%s%s", AUTH_TOKEN_PREFIX, body); free(body); return token; } int64_t auth_user_lookup(sqlite3 *db, const char *username, char **out_pwhash, char **out_display, int *out_is_admin, int *out_disabled) { sqlite3_stmt *st = NULL; int rc = sqlite3_prepare_v2( db, "SELECT id, pw_hash, display_name, is_admin, disabled_at FROM users" " WHERE username = ?1", -1, &st, NULL); if (rc != SQLITE_OK) return -2; sqlite3_bind_text(st, 1, username, -1, SQLITE_TRANSIENT); int64_t id = -1; if (sqlite3_step(st) == SQLITE_ROW) { id = sqlite3_column_int64(st, 0); if (out_pwhash) { const unsigned char *p = sqlite3_column_text(st, 1); *out_pwhash = p ? xstrdup((const char *)p) : NULL; } if (out_display) { const unsigned char *p = sqlite3_column_text(st, 2); *out_display = p ? xstrdup((const char *)p) : NULL; } if (out_is_admin) *out_is_admin = sqlite3_column_int(st, 3); if (out_disabled) *out_disabled = sqlite3_column_type(st, 4) != SQLITE_NULL; } sqlite3_finalize(st); return id; }