game: prepare auth login query
Some checks failed
build / Linux asan (push) Has been cancelled
build / Linux release (push) Has been cancelled
build / FreeBSD build (push) Has been cancelled

This commit is contained in:
server
2026-04-14 10:58:11 +02:00
parent f1e64196ae
commit c5cac17125
3 changed files with 227 additions and 51 deletions

View File

@@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include <array>
#include <sstream> #include <sstream>
#include "common/length.h" #include "common/length.h"
@@ -17,9 +18,211 @@
#include "login_data.h" #include "login_data.h"
#include "locale_service.h" #include "locale_service.h"
#include "spam.h" #include "spam.h"
#include "libsql/Statement.h"
extern std::string g_stBlockDate; extern std::string g_stBlockDate;
namespace
{
struct AuthLoginData
{
char encryptedPassword[45 + 1] = {};
char password[45 + 1] = {};
char socialId[SOCIAL_ID_MAX_LEN + 1] = {};
char status[ACCOUNT_STATUS_MAX_LEN + 1] = {};
uint32_t accountId = 0;
uint8_t notAvailable = 0;
std::array<int, PREMIUM_MAX_NUM> premiumTimes = {};
long long createTime = 0;
};
bool IsChannelServiceLogin(const char* login)
{
return login && login[0] == '[';
}
bool PrepareGameStmt(CStmt& stmt, const std::string& query)
{
CAsyncSQL* sql = DBManager::instance().GetDirectSQL();
if (!sql)
{
sys_err("game direct SQL handle is not initialized");
return false;
}
return stmt.Prepare(sql, query.c_str());
}
bool LoadAuthLoginData(const char* login, const char* passwd, AuthLoginData& auth, bool& found)
{
CStmt stmt;
const bool channelServiceLogin = IsChannelServiceLogin(login);
const std::string query = channelServiceLogin
? "SELECT ?, password, social_id, id, status, availDt - NOW() > 0,"
"UNIX_TIMESTAMP(silver_expire),"
"UNIX_TIMESTAMP(gold_expire),"
"UNIX_TIMESTAMP(safebox_expire),"
"UNIX_TIMESTAMP(autoloot_expire),"
"UNIX_TIMESTAMP(fish_mind_expire),"
"UNIX_TIMESTAMP(marriage_fast_expire),"
"UNIX_TIMESTAMP(money_drop_rate_expire),"
"UNIX_TIMESTAMP(create_time)"
" FROM account WHERE login=?"
: "SELECT PASSWORD(?), password, social_id, id, status, availDt - NOW() > 0,"
"UNIX_TIMESTAMP(silver_expire),"
"UNIX_TIMESTAMP(gold_expire),"
"UNIX_TIMESTAMP(safebox_expire),"
"UNIX_TIMESTAMP(autoloot_expire),"
"UNIX_TIMESTAMP(fish_mind_expire),"
"UNIX_TIMESTAMP(marriage_fast_expire),"
"UNIX_TIMESTAMP(money_drop_rate_expire),"
"UNIX_TIMESTAMP(create_time)"
" FROM account WHERE login=?";
found = false;
if (!PrepareGameStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(passwd))
|| !stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(login)))
{
return false;
}
if (!stmt.BindResult(MYSQL_TYPE_STRING, auth.encryptedPassword, sizeof(auth.encryptedPassword))
|| !stmt.BindResult(MYSQL_TYPE_STRING, auth.password, sizeof(auth.password))
|| !stmt.BindResult(MYSQL_TYPE_STRING, auth.socialId, sizeof(auth.socialId))
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.accountId)
|| !stmt.BindResult(MYSQL_TYPE_STRING, auth.status, sizeof(auth.status))
|| !stmt.BindResult(MYSQL_TYPE_TINY, &auth.notAvailable)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_EXP])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_ITEM])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_SAFEBOX])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_AUTOLOOT])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_FISH_MIND])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_MARRIAGE_FAST])
|| !stmt.BindResult(MYSQL_TYPE_LONG, &auth.premiumTimes[PREMIUM_GOLD])
|| !stmt.BindResult(MYSQL_TYPE_LONGLONG, &auth.createTime))
{
return false;
}
if (!stmt.Execute())
return false;
if (stmt.iRows == 0)
return true;
if (!stmt.Fetch())
return false;
found = true;
return true;
}
void FormatCreateDate(const AuthLoginData& auth, char* dst, size_t dstSize)
{
strlcpy(dst, "00000000", dstSize);
if (auth.createTime <= 0)
return;
time_t createTime = static_cast<time_t>(auth.createTime);
struct tm tmBuf;
if (!localtime_r(&createTime, &tmBuf))
return;
strftime(dst, dstSize, "%Y%m%d", &tmBuf);
}
void UpdateAccountLastPlay(uint32_t accountId)
{
CStmt stmt;
const std::string query = "UPDATE account SET last_play=NOW() WHERE id=?";
if (!PrepareGameStmt(stmt, query))
return;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
return;
if (!stmt.Execute())
{
sys_err("failed to update last_play for account %u", accountId);
}
}
void FinalizeAuthLogin(LPDESC d, const char* login, const char* passwd, const AuthLoginData& auth, const char* logPrefix)
{
char createDate[256] = "00000000";
if (LC_IsEurope() || test_server)
{
FormatCreateDate(auth, createDate, sizeof(createDate));
sys_log(0, "Create_Time %lld %s", auth.createTime, createDate);
sys_log(0, "Block Time %d ", strncmp(createDate, g_stBlockDate.c_str(), 8));
}
if (strcmp(auth.encryptedPassword, auth.password))
{
RecordLoginFailure(d->GetHostName());
LoginFailure(d, "WRONGPWD");
sys_log(0, " WRONGPWD");
return;
}
if (auth.notAvailable)
{
LoginFailure(d, "NOTAVAIL");
sys_log(0, " NOTAVAIL");
return;
}
if (DESC_MANAGER::instance().FindByLoginName(login))
{
LoginFailure(d, "ALREADY");
sys_log(0, " ALREADY");
return;
}
if (strcmp(auth.status, "OK"))
{
LoginFailure(d, auth.status);
sys_log(0, " STATUS: %s", auth.status);
return;
}
if (LC_IsEurope())
{
if (strncmp(createDate, g_stBlockDate.c_str(), 8) >= 0)
{
LoginFailure(d, "BLKLOGIN");
sys_log(0, " BLKLOGIN");
return;
}
UpdateAccountLastPlay(auth.accountId);
}
TAccountTable& r = d->GetAccountTable();
int premiumTimes[PREMIUM_MAX_NUM];
r.id = auth.accountId;
trim_and_lower(login, r.login, sizeof(r.login));
strlcpy(r.passwd, passwd, sizeof(r.passwd));
strlcpy(r.social_id, auth.socialId, sizeof(r.social_id));
DESC_MANAGER::instance().ConnectAccount(r.login, d);
ClearLoginFailure(d->GetHostName());
thecore_memcpy(premiumTimes, auth.premiumTimes.data(), sizeof(premiumTimes));
DBManager::instance().LoginPrepare(d, premiumTimes);
sys_log(0, "%s: SUCCESS %s", logPrefix, login);
}
}
DBManager::DBManager() : m_bIsConnect(false) DBManager::DBManager() : m_bIsConnect(false)
{ {
} }
@@ -232,6 +435,28 @@ void DBManager::LoginPrepare(LPDESC d, int * paiPremiumTimes)
SendAuthLogin(d); SendAuthLogin(d);
} }
void DBManager::AuthenticateLogin(LPDESC d, const char* login, const char* passwd)
{
AuthLoginData auth;
bool found = false;
d->SetLogin(login);
sys_log(0, "AUTH_LOGIN_DIRECT: START %u %p", d->GetLoginKey(), get_pointer(d));
if (IsChannelServiceLogin(login))
sys_log(0, "ChannelServiceLogin [%s]", login);
if (!LoadAuthLoginData(login, passwd, auth, found) || !found)
{
sys_log(0, " NOID");
RecordLoginFailure(d->GetHostName());
LoginFailure(d, "NOID");
return;
}
FinalizeAuthLogin(d, login, passwd, auth, "AUTH_LOGIN_DIRECT");
}
void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg) void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
{ {
CReturnQueryInfo * qi = (CReturnQueryInfo *) pMsg->pvUserData; CReturnQueryInfo * qi = (CReturnQueryInfo *) pMsg->pvUserData;

View File

@@ -82,6 +82,7 @@ class DBManager : public singleton<DBManager>
void SendMoneyLog(BYTE type, DWORD vnum, int gold); void SendMoneyLog(BYTE type, DWORD vnum, int gold);
void LoginPrepare(LPDESC d, int * paiPremiumTimes = NULL); void LoginPrepare(LPDESC d, int * paiPremiumTimes = NULL);
void AuthenticateLogin(LPDESC d, const char* login, const char* passwd);
void SendAuthLogin(LPDESC d); void SendAuthLogin(LPDESC d);
void SendLoginPing(const char * c_pszLogin); void SendLoginPing(const char * c_pszLogin);

View File

@@ -141,13 +141,6 @@ bool FN_IS_VALID_LOGIN_STRING(const char *str)
return true; return true;
} }
bool Login_IsInChannelService(const char* c_login)
{
if (c_login[0] == '[')
return true;
return false;
}
CInputAuth::CInputAuth() CInputAuth::CInputAuth()
{ {
RegisterHandlers(); RegisterHandlers();
@@ -233,50 +226,7 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
sys_log(0, "InputAuth::Login : key %u login %s", dwKey, login); sys_log(0, "InputAuth::Login : key %u login %s", dwKey, login);
TPacketCGLogin3 * p = M2_NEW TPacketCGLogin3; DBManager::instance().AuthenticateLogin(d, login, passwd);
thecore_memcpy(p, pinfo, sizeof(TPacketCGLogin3));
char szPasswd[PASSWD_MAX_LEN * 2 + 1];
DBManager::instance().EscapeString(szPasswd, sizeof(szPasswd), passwd, strlen(passwd));
char szLogin[LOGIN_MAX_LEN * 2 + 1];
DBManager::instance().EscapeString(szLogin, sizeof(szLogin), login, strlen(login));
// CHANNEL_SERVICE_LOGIN
if (Login_IsInChannelService(szLogin))
{
sys_log(0, "ChannelServiceLogin [%s]", szLogin);
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
"SELECT '%s',password,social_id,id,status,availDt - NOW() > 0,"
"UNIX_TIMESTAMP(silver_expire),"
"UNIX_TIMESTAMP(gold_expire),"
"UNIX_TIMESTAMP(safebox_expire),"
"UNIX_TIMESTAMP(autoloot_expire),"
"UNIX_TIMESTAMP(fish_mind_expire),"
"UNIX_TIMESTAMP(marriage_fast_expire),"
"UNIX_TIMESTAMP(money_drop_rate_expire),"
"UNIX_TIMESTAMP(create_time)"
" FROM account WHERE login='%s'",
szPasswd, szLogin);
}
// END_OF_CHANNEL_SERVICE_LOGIN
else
{
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
"SELECT PASSWORD('%s'),password,social_id,id,status,availDt - NOW() > 0,"
"UNIX_TIMESTAMP(silver_expire),"
"UNIX_TIMESTAMP(gold_expire),"
"UNIX_TIMESTAMP(safebox_expire),"
"UNIX_TIMESTAMP(autoloot_expire),"
"UNIX_TIMESTAMP(fish_mind_expire),"
"UNIX_TIMESTAMP(marriage_fast_expire),"
"UNIX_TIMESTAMP(money_drop_rate_expire),"
"UNIX_TIMESTAMP(create_time)"
" FROM account WHERE login='%s'",
szPasswd, szLogin);
}
} }
int CInputAuth::Analyze(LPDESC d, uint16_t wHeader, const char * c_pData) int CInputAuth::Analyze(LPDESC d, uint16_t wHeader, const char * c_pData)