93 lines
3 KiB
C
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;
|
||
|
}
|