// LEMONBBS MODULES: DATABASE // this is a simple sqlite3 database module. To enable it, just call the dbInit() method. #include #include #include #include #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; }