This repository has been archived on 2021-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
lemonbbs/src/dbutil.c
2021-12-15 18:52:53 +01:00

93 lines
3 KiB
C

// LEMONBBS MODULES: DATABASE
// this is a simple sqlite3 database module. To enable it, just call the dbInit() method.
#include <sqlite3.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <memory.h>
#include "dbutil.h"
#include "settings.h"
sqlite3* db;
int dbInsertUser(const char* username, const char* secret) {
uint8_t key[32], salt[32];
RAND_bytes(salt, sizeof(salt));
PKCS5_PBKDF2_HMAC_SHA1(secret, -1, salt, sizeof(salt), 1000, sizeof(key), key);
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db, "insert into users(username, secret, salt) values(?1, ?2, ?3)", 60, &stmt, NULL) != SQLITE_OK) goto panic;
if (sqlite3_bind_text(stmt, 1, username, -1, SQLITE_TRANSIENT) != SQLITE_OK) goto panic;
if (sqlite3_bind_blob(stmt, 2, key, 32, SQLITE_TRANSIENT) != SQLITE_OK) goto panic;
if (sqlite3_bind_blob(stmt, 3, salt, 32, SQLITE_TRANSIENT) != SQLITE_OK) goto panic;
if (sqlite3_step(stmt) != SQLITE_DONE) goto panic;
sqlite3_finalize(stmt);
return 1;
panic:
sqlite3_finalize(stmt);
return -1;
}
int dbUsernameTaken(const char* username) {
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db, "select 1 from users where username=?1", 37, &stmt, NULL) != SQLITE_OK) goto panic;
if (sqlite3_bind_text(stmt, 1, username, -1, SQLITE_TRANSIENT) != SQLITE_OK) goto panic;
int stepResult = sqlite3_step(stmt);
sqlite3_finalize(stmt);
switch (stepResult) {
case SQLITE_DONE:
return 0;
case SQLITE_ROW:
return 1;
default:
return -1;
}
panic:
sqlite3_finalize(stmt);
return -1;
}
/*
* -1 = Database error
* -2 = User not found
* -3 = Secret doesn't match
*/
int64_t dbVerifyLogin(const char* username, const char* secret) {
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db, "select user_id, secret, salt from users where username=?1", 57, &stmt, NULL) != SQLITE_OK) goto panic;
if (sqlite3_bind_text(stmt, 1, username, -1, SQLITE_TRANSIENT) != SQLITE_OK) goto panic;
int stepResult = sqlite3_step(stmt);
int64_t result;
switch (stepResult) {
case SQLITE_DONE:
result = -2; break;
case SQLITE_ROW:
{
const uint8_t *salt, *key;
uint8_t generated[32];
key = sqlite3_column_blob(stmt, 1);
salt = sqlite3_column_blob(stmt, 2);
PKCS5_PBKDF2_HMAC_SHA1(secret, -1, salt, 32, 1000, 32, generated);
result = memcmp(generated, key, 32) == 0 ? sqlite3_column_int64(stmt, 0) : -3;
break;
}
default:
result = -1; break;
}
sqlite3_finalize(stmt);
return result;
panic:
sqlite3_finalize(stmt);
return -1;
}
int dbInit() {
int dbresult = sqlite3_open(DB_PATH, &db);
if (dbresult != SQLITE_OK) {
return -1;
}
if (sqlite3_exec(db, "create table if not exists users(user_id integer primary key, username text not null unique, secret blob not null, salt blob not null)", NULL, NULL, NULL) != SQLITE_OK) {
return -2;
}
return 0;
}