2 Commits

Author SHA1 Message Date
234ec46f36 Move timingSafeStrcmp to main 2024-11-16 19:16:49 -08:00
4d0553e9ef Refactor login packet handler for more flexible auth 2024-11-16 13:42:20 -08:00
6 changed files with 12 additions and 52 deletions

View File

@@ -1,8 +0,0 @@
BEGIN TRANSACTION;
-- New Columns
ALTER TABLE Accounts ADD Email TEXT DEFAULT '' NOT NULL;
ALTER TABLE Accounts ADD LastPasswordReset INTEGER DEFAULT 0 NOT NULL;
-- Update DB Version
UPDATE Meta SET Value = 6 WHERE Key = 'DatabaseVersion';
UPDATE Meta SET Value = strftime('%s', 'now') WHERE Key = 'LastMigration';
COMMIT;

View File

@@ -1,16 +1,14 @@
CREATE TABLE IF NOT EXISTS Accounts ( CREATE TABLE IF NOT EXISTS Accounts (
AccountID INTEGER NOT NULL, AccountID INTEGER NOT NULL,
Login TEXT NOT NULL UNIQUE COLLATE NOCASE, Login TEXT NOT NULL UNIQUE COLLATE NOCASE,
Password TEXT NOT NULL, Password TEXT NOT NULL,
Selected INTEGER DEFAULT 1 NOT NULL, Selected INTEGER DEFAULT 1 NOT NULL,
AccountLevel INTEGER NOT NULL, AccountLevel INTEGER NOT NULL,
Created INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, Created INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
LastLogin INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, LastLogin INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
BannedUntil INTEGER DEFAULT 0 NOT NULL, BannedUntil INTEGER DEFAULT 0 NOT NULL,
BannedSince INTEGER DEFAULT 0 NOT NULL, BannedSince INTEGER DEFAULT 0 NOT NULL,
BanReason TEXT DEFAULT '' NOT NULL, BanReason TEXT DEFAULT '' NOT NULL,
Email TEXT DEFAULT '' NOT NULL,
LastPasswordReset INTEGER DEFAULT 0 NOT NULL,
PRIMARY KEY(AccountID AUTOINCREMENT) PRIMARY KEY(AccountID AUTOINCREMENT)
); );

View File

@@ -396,14 +396,6 @@ static void heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
static void exitGame(CNSocket* sock, CNPacketData* data) { static void exitGame(CNSocket* sock, CNPacketData* data) {
auto exitData = (sP_CL2FE_REQ_PC_EXIT*)data->buf; auto exitData = (sP_CL2FE_REQ_PC_EXIT*)data->buf;
// Refresh any auth cookie, in case "change character" was used
Player* plr = getPlayer(sock);
if (plr != nullptr) {
// 5 seconds should be enough to log in again
Database::refreshCookie(plr->accountId, 5);
}
INITSTRUCT(sP_FE2CL_REP_PC_EXIT_SUCC, response); INITSTRUCT(sP_FE2CL_REP_PC_EXIT_SUCC, response);
response.iID = exitData->iID; response.iID = exitData->iID;

View File

@@ -5,7 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define DATABASE_VERSION 6 #define DATABASE_VERSION 5
namespace Database { namespace Database {
@@ -56,7 +56,6 @@ namespace Database {
// return true if cookie is valid for the account. // return true if cookie is valid for the account.
// invalidates the stored cookie afterwards // invalidates the stored cookie afterwards
bool checkCookie(int accountId, const char *cookie); bool checkCookie(int accountId, const char *cookie);
void refreshCookie(int accountId, int durationSec);
// interface for the /ban command // interface for the /ban command
bool banPlayer(int playerId, std::string& reason); bool banPlayer(int playerId, std::string& reason);

View File

@@ -151,27 +151,6 @@ bool Database::checkCookie(int accountId, const char *tryCookie) {
return match; return match;
} }
void Database::refreshCookie(int accountId, int durationSec) {
std::lock_guard<std::mutex> lock(dbCrit);
const char* sql = R"(
UPDATE Auth
SET Expires = ?
WHERE AccountID = ?;
)";
int expires = getTimestamp() + durationSec;
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
sqlite3_bind_int(stmt, 1, expires);
sqlite3_bind_int(stmt, 2, accountId);
int rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (rc != SQLITE_DONE)
std::cout << "[WARN] Database fail on refreshCookie(): " << sqlite3_errmsg(db) << std::endl;
}
void Database::updateSelected(int accountId, int slot) { void Database::updateSelected(int accountId, int slot) {
std::lock_guard<std::mutex> lock(dbCrit); std::lock_guard<std::mutex> lock(dbCrit);

View File

@@ -698,7 +698,7 @@ bool CNLoginServer::checkToken(CNSocket* sock, Database::Account& account, std::
} }
} }
// cookie check disabled or failed; check to see if it's a plaintext password // cookie check failed; check to see if it's a plaintext password sent by auto-login
if (CNLoginServer::isAuthMethodAllowed(AuthMethod::PASSWORD) if (CNLoginServer::isAuthMethodAllowed(AuthMethod::PASSWORD)
&& CNLoginServer::isPasswordCorrect(account.Password, token)) { && CNLoginServer::isPasswordCorrect(account.Password, token)) {
return true; return true;