Compare commits

...

4 Commits

9 changed files with 95 additions and 101 deletions

View File

@ -16,3 +16,6 @@ gamefiles/data/quest/qc
# Test folder # Test folder
test/ test/
# Built files
build/

View File

@ -9,7 +9,7 @@ RUN echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https:
# Update the system and install various dependencies # Update the system and install various dependencies
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y git cmake ninja-build build-essential tar curl zip unzip pkg-config autoconf python3 \ apt-get install -y git cmake ninja-build build-essential tar curl zip unzip pkg-config autoconf python3 \
libdevil-dev libncurses5-dev libbsd-dev libdevil-dev libncurses5-dev libbsd-dev
# Arm specific # Arm specific
ENV VCPKG_FORCE_SYSTEM_BINARIES=1 ENV VCPKG_FORCE_SYSTEM_BINARIES=1
@ -17,7 +17,7 @@ ENV VCPKG_FORCE_SYSTEM_BINARIES=1
# Install vcpkg and the required libraries # Install vcpkg and the required libraries
RUN git clone https://github.com/Microsoft/vcpkg.git RUN git clone https://github.com/Microsoft/vcpkg.git
RUN bash ./vcpkg/bootstrap-vcpkg.sh RUN bash ./vcpkg/bootstrap-vcpkg.sh
RUN ./vcpkg/vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog RUN ./vcpkg/vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog argon2
COPY . . COPY . .

View File

@ -39,7 +39,7 @@ Install `vcpkg` according to the [lastest instructions](https://vcpkg.io/en/gett
Build and install the required libraries: Build and install the required libraries:
```shell ```shell
vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog argon2
``` ```
Then, it's time to build your binaries. Your commands should look along the lines of: Then, it's time to build your binaries. Your commands should look along the lines of:
@ -81,6 +81,7 @@ goodies you wish. Also, a lot of time.
- Refactored macros to modern C++ functions. - Refactored macros to modern C++ functions.
- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `CONFIG` file. (Might need further work) - Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `CONFIG` file. (Might need further work)
- Refactored logging to use [spdlog](https://github.com/gabime/spdlog) for more consistent function calls. - Refactored logging to use [spdlog](https://github.com/gabime/spdlog) for more consistent function calls.
- Refactored login code to use Argon2ID.
## 4. Bugfixes ## 4. Bugfixes
**WARNING: This project is based on the "kraizy" leak. That was over 10 years ago. **WARNING: This project is based on the "kraizy" leak. That was over 10 years ago.

View File

@ -51,8 +51,8 @@ mysql_query = function(query)
end end
math.randomseed(os.time()) math.randomseed(os.time())
local fi,t,out = 'mysql_data_'..math.random(10^9)+math.random(2^4,2^10),{},{} local fi,t,out = 'mysql_data_'..math.random(10^9)+math.random(2^4,2^10),{},{}
--os.execute('mysql '..pre..' --e='..string.format('%q',query)..' > '..fi) -- für MySQL51 --os.execute('mysql '..pre..' --e='..string.format('%q',query)..' > '..fi) -- f<EFBFBD>r MySQL51
os.execute('mysql '..pre..' -e'..string.format('%q',query)..' > '..fi) -- für MySQL55 os.execute('mysql '..pre..' -e'..string.format('%q',query)..' > '..fi) -- f<EFBFBD>r MySQL55
for av in io.open(fi,'r'):lines() do table.insert(t,split(av,'\t')) end; os.remove(fi); for av in io.open(fi,'r'):lines() do table.insert(t,split(av,'\t')) end; os.remove(fi);
for i = 2, table.getn(t) do table.foreach(t[i],function(a,b) for i = 2, table.getn(t) do table.foreach(t[i],function(a,b)
out[i-1] = out[i-1] or {} out[i-1] = out[i-1] or {}
@ -100,7 +100,7 @@ function mysql_query_old(query,user,pass,db,ip)
os.remove(path) os.remove(path)
if type(q.l[1]) ~= "table" then if type(q.l[1]) ~= "table" then
return "ERROR" return "ERROR"
--error("Fehler bei der MySQL Verbindung oder bei der Rückgabe! Abbruch!") --error("Fehler bei der MySQL Verbindung oder bei der R<EFBFBD>ckgabe! Abbruch!")
end end
local ix = 0 local ix = 0
table.foreachi(q.l,function(i,l) table.foreachi(q.l,function(i,l)
@ -115,7 +115,7 @@ function mysql_query_old(query,user,pass,db,ip)
end) end end) end
end) end)
-- ENDE der eigentlichen MySQL-Funktion -- ENDE der eigentlichen MySQL-Funktion
-- START Zusatz: Hanashi-Kompatibilität & Fehlerbehandlung -- START Zusatz: Hanashi-Kompatibilit<EFBFBD>t & Fehlerbehandlung
q.out.__data = q.l[1] q.out.__data = q.l[1]
setmetatable(q.out, { __index = function(a,b) setmetatable(q.out, { __index = function(a,b)
if type(b) == "number" then if type(b) == "number" then
@ -132,7 +132,7 @@ end
@name define @name define
@author Mijago @author Mijago
@descr @descr
Gibt die Möglichkeit, globale Variablen zu definieren. Es können auch Funktionen genutzt werden! Diese werden dann AUSGEFÜHRT zurückgegeben! Gibt die M<EFBFBD>glichkeit, globale Variablen zu definieren. Es k<EFBFBD>nnen auch Funktionen genutzt werden! Diese werden dann AUSGEF<EFBFBD>HRT zur<EFBFBD>ckgegeben!
--]] --]]
_G.__data = {} _G.__data = {}
local meta = getmetatable(_G) or {} local meta = getmetatable(_G) or {}
@ -155,7 +155,7 @@ end
@name duration @name duration
@author Mijago @author Mijago
@descr @descr
Gibt die verbleibende Zeit als String zurück. Gibt die verbleibende Zeit als String zur<EFBFBD>ck.
--]] --]]
function duration(ipe) function duration(ipe)
local ipe,dat= ipe or 0,'' local ipe,dat= ipe or 0,''
@ -183,7 +183,7 @@ end
@name is_number @name is_number
@author Mijago @author Mijago
@descr @descr
Prüft, ob eine Variable eine Zahl ist. Pr<EFBFBD>ft, ob eine Variable eine Zahl ist.
--]] --]]
function is_number(var) function is_number(var)
return (type(var) == "number") return (type(var) == "number")
@ -194,7 +194,7 @@ end
@name is_string @name is_string
@author Mijago @author Mijago
@descr @descr
Prüft, ob eine Variable ein String ist. Pr<EFBFBD>ft, ob eine Variable ein String ist.
--]] --]]
function is_string(var) function is_string(var)
return (type(var) == "string") return (type(var) == "string")
@ -205,7 +205,7 @@ end
@name is_table @name is_table
@author Mijago @author Mijago
@descr @descr
Prüft, ob eine Variable eine Tabelle ist. Pr<EFBFBD>ft, ob eine Variable eine Tabelle ist.
--]] --]]
function is_table(var) function is_table(var)
return (type(var) == "table") return (type(var) == "table")
@ -216,7 +216,7 @@ end
@name in_table @name in_table
@author Mijago @author Mijago
@descr @descr
Prüft, ob eine Variablei in einer Tabelle ist. Pr<EFBFBD>ft, ob eine Variablei in einer Tabelle ist.
Aufruf: in_table(var,table) Aufruf: in_table(var,table)
--]] --]]
function in_table ( e, t ) function in_table ( e, t )
@ -292,7 +292,7 @@ end
@name math.minmax @name math.minmax
@author Mijago @author Mijago
@descr @descr
Ermöglicht die Angabe von min und max auf einmal Erm<EFBFBD>glicht die Angabe von min und max auf einmal
--]] --]]
math.minmax = function(min,num,max) math.minmax = function(min,num,max)
return math.min(math.max(num,min),max) return math.min(math.max(num,min),max)
@ -304,8 +304,8 @@ end
@name n_input @name n_input
@author Mijago @author Mijago
@descr @descr
Für Inputs nur r Zahlen. F<EFBFBD>r Inputs nur f<EFBFBD>r Zahlen.
Die Zahl ist IMMER positiv. Wenn sie nicht gültig ist, ist sie 0. Die Zahl ist IMMER positiv. Wenn sie nicht g<EFBFBD>ltig ist, ist sie 0.
--]] --]]
function n_input() function n_input()
return math.abs(tonumber(input()) or 0) return math.abs(tonumber(input()) or 0)
@ -316,7 +316,7 @@ end
@name long_input @name long_input
@author Mijago @author Mijago
@descr @descr
Ermöglicht es, ngere Inputs zu nutzen. Erm<EFBFBD>glicht es, l<EFBFBD>ngere Inputs zu nutzen.
--]] --]]
function long_input() function long_input()
local str,t = "",input() local str,t = "",input()
@ -358,7 +358,7 @@ function select2(tab,...)
outputstr=outputstr..'sel = select("'..l..'"' outputstr=outputstr..'sel = select("'..l..'"'
elseif outputcount == max and tablen > outputcount+incit then elseif outputcount == max and tablen > outputcount+incit then
if tablen ~= outputcount+incit+1 then if tablen ~= outputcount+incit+1 then
outputstr=outputstr..',"'..l..'","Nächste Seite") + '..incit..' ' outputstr=outputstr..',"'..l..'","N<EFBFBD>chste Seite") + '..incit..' '
if nextc > 0 then if nextc > 0 then
outputstr = outputstr..'end ' outputstr = outputstr..'end '
end end
@ -392,7 +392,7 @@ end
@descr @descr
Wie Select2: Wie Select2:
Eine Tabelle oder eine Stringliste wird auf Seiten aufgeteilt. Eine Tabelle oder eine Stringliste wird auf Seiten aufgeteilt.
Weiter, Zurück und Abbrechen (-1) Buttons. Weiter, Zur<EFBFBD>ck und Abbrechen (-1) Buttons.
--]] --]]
function select3(...) function select3(...)
arg.n = nil arg.n = nil
@ -438,7 +438,7 @@ function select3(...)
pe[i] = copy_tab(px[i]) pe[i] = copy_tab(px[i])
local next,back,exit = 0,0,0 local next,back,exit = 0,0,0
if i < table.getn(pe) and table.getn(pe) ~=1 then table.insert(pe[i],table.getn(pe[i])+1,'Weiter zu Seite '..(i+1)); next = table.getn(pe[i]) end if i < table.getn(pe) and table.getn(pe) ~=1 then table.insert(pe[i],table.getn(pe[i])+1,'Weiter zu Seite '..(i+1)); next = table.getn(pe[i]) end
if i > 1 then table.insert(pe[i],table.getn(pe[i])+1,'Zurück zu Seite '..(i-1)); back = table.getn(pe[i]) end if i > 1 then table.insert(pe[i],table.getn(pe[i])+1,'Zur<EFBFBD>ck zu Seite '..(i-1)); back = table.getn(pe[i]) end
table.insert(pe[i],table.getn(pe[i])+1,'Abbruch'); exit = table.getn(pe[i]) table.insert(pe[i],table.getn(pe[i])+1,'Abbruch'); exit = table.getn(pe[i])
if table.getn(pe) > 1 then if table.getn(pe) > 1 then
say('Seite '..i..' von '..table.getn(pe)) say('Seite '..i..' von '..table.getn(pe))
@ -564,7 +564,7 @@ zt.s_ms = function(s)
@name Autoumbruch in Say @name Autoumbruch in Say
@author Mijago @author Mijago
@descr @descr
Fügt die Funktion say2 an. F<EFBFBD>gt die Funktion say2 an.
Mit ihr werden Texte automatisch umgebrochen. Mit ihr werden Texte automatisch umgebrochen.
--]] --]]
function say2(str,dx) function say2(str,dx)
@ -616,13 +616,14 @@ end
@author Mijago; Idee von Benhero @author Mijago; Idee von Benhero
@needs mysql_query @needs mysql_query
@descr @descr
Funktion zum Ändern des Nutzerpasswortes. Funktion zum <EFBFBD>ndern des Nutzerpasswortes.
Angabe des Accounts kann weggelassen werden, als Accountname oder als Account ID angegeben werden. Angabe des Accounts kann weggelassen werden, als Accountname oder als Account ID angegeben werden.
--]] --]]
account = account or {} account = account or {}
function account.set_pw(pw,ac) function account.set_pw(pw,ac)
if pw == nil then error("Fehler... Passwort muss gesetzt werden!") end if pw == nil then error("Fehler... Passwort muss gesetzt werden!") end
local ac = ac or pc.get_account_id() local ac = ac or pc.get_account_id()
-- This is weird behaviour and might need to be changed if ever used.
if type(ac) == "string" then if type(ac) == "string" then
mysql_query("UPDATE player.player,account.account SET account.password = password("..string.format('%q',pw)..") WHERE account.id = player.account_id and player.name = '"..ac.."' LIMIT 1") mysql_query("UPDATE player.player,account.account SET account.password = password("..string.format('%q',pw)..") WHERE account.id = player.account_id and player.name = '"..ac.."' LIMIT 1")
elseif type(ac) == "number" then elseif type(ac) == "number" then
@ -635,7 +636,7 @@ end
@name pc.check_inventory_place @name pc.check_inventory_place
@author Mijago @author Mijago
@descr @descr
Checkt auf Freie Inventarplätze für Items der größe X (he). Checkt auf Freie Inventarpl<EFBFBD>tze f<EFBFBD>r Items der gr<EFBFBD><EFBFBD>e X (H<EFBFBD>he).
--]] --]]
function pc.check_inventory_place(size) function pc.check_inventory_place(size)
if size <= 0 or size > 3 then if size <= 0 or size > 3 then
@ -663,7 +664,7 @@ end
@name do_for_other @name do_for_other
@author Mijago @author Mijago
@descr @descr
Führt einen String als Luabefehle bei einem anderem User aus. F<EFBFBD>hrt einen String als Luabefehle bei einem anderem User aus.
--]] --]]
function do_for_other(name,ding) function do_for_other(name,ding)
local t = pc.select(find_pc_by_name(name)) local t = pc.select(find_pc_by_name(name))
@ -678,7 +679,7 @@ end
@descr @descr
Setzt die Questflag eines anderen Spielers. Setzt die Questflag eines anderen Spielers.
--]] --]]
function local_pc_setqf(name, qf,wert) -- Für die aktuelle Quest function local_pc_setqf(name, qf,wert) -- F<EFBFBD>r die aktuelle Quest
local target = find_pc_by_name(name) local target = find_pc_by_name(name)
local t = pc.select(target) local t = pc.select(target)
pc.setqf(qf,wert) pc.setqf(qf,wert)
@ -753,7 +754,7 @@ end
@name download @name download
@author Mijago @author Mijago
@descr @descr
Lädt eine Datei in den Data-Ordner. L<EFBFBD>dt eine Datei in den Data-Ordner.
--]] --]]
function download(url) os.execute("cd data && fetch "..url.." && cd ..") end function download(url) os.execute("cd data && fetch "..url.." && cd ..") end
@ -762,7 +763,7 @@ function download(url) os.execute("cd data && fetch "..url.." && cd ..") end
@name dot @name dot
@author Mijago @author Mijago
@descr @descr
Führt alles Zwischen $ und $ im String aus. F<EFBFBD>hrt alles Zwischen $ und $ im String aus.
--]] --]]
function dot(x) function dot(x)
return string.gsub(x, "%$(.-)%$", function (s) return loadstring(s)() end) return string.gsub(x, "%$(.-)%$", function (s) return loadstring(s)() end)
@ -773,7 +774,7 @@ end
@name dostr @name dostr
@author Mijago @author Mijago
@descr @descr
Führt einen String als Lua-Befehl aus. F<EFBFBD>hrt einen String als Lua-Befehl aus.
--]] --]]
function dostr(str) function dostr(str)
assert(loadstring(str))() assert(loadstring(str))()
@ -785,7 +786,7 @@ end
@author Mijago @author Mijago
@needs mysql_query @needs mysql_query
@descr @descr
Versetzt alle Accounts (außer GM-Accounts) in einen "Wartungsmodus" und wieder zurück. Versetzt alle Accounts (au<EFBFBD>er GM-Accounts) in einen "Wartungsmodus" und wieder zur<EFBFBD>ck.
--]] --]]
function wartungsmodus(v) function wartungsmodus(v)
if v == 1 or v == true then if v == 1 or v == true then
@ -815,7 +816,7 @@ end
@name INI-Parser @name INI-Parser
@author Mijago @author Mijago
@descr @descr
Ein NEUER Parser für INI-Dateien. Ein NEUER Parser f<EFBFBD>r INI-Dateien.
--]] --]]
ini = { ini = {
open = function(path) open = function(path)
@ -840,7 +841,7 @@ ini = {
else else
r = r.."\n["..section.."]\n"..key.."="..value r = r.."\n["..section.."]\n"..key.."="..value
end end
-- überflüssige leerzeichen löschen -- <EFBFBD>berfl<EFBFBD>ssige leerzeichen l<>schen
r=string.gsub(string.gsub(string.gsub(r,"^(\n)",""),"(\n)$",""),"\n\n","\n") r=string.gsub(string.gsub(string.gsub(r,"^(\n)",""),"(\n)$",""),"\n\n","\n")
local d = io.open(self.path,"w") local d = io.open(self.path,"w")
d:write(r) d:write(r)
@ -895,7 +896,7 @@ ini = {
@needs split @needs split
@descr @descr
-- OUTDATED -- -- OUTDATED --
Ein Parser für Ini-Dateien. Ein Parser f<EFBFBD>r Ini-Dateien.
Besitzt eine Eigene Beschreibung der einzelnen Funktionen im Code. Besitzt eine Eigene Beschreibung der einzelnen Funktionen im Code.
--]] --]]
do do
@ -906,9 +907,9 @@ do
-- var:write_int(sub,name,wert) -- var:write_int(sub,name,wert)
-- var:write_bool(sub,name,boolean) -- var:write_bool(sub,name,boolean)
-- var:clear() -- var:clear()
-- var:read_str(sub,name,norm) -- Gibt einen String zurück. -| -- var:read_str(sub,name,norm) -- Gibt einen String zur<EFBFBD>ck. -|
-- var:read_int(sub,name,norm) -- Gibt eine Zahl zurück -| norm wird zurückgegeben, wenn sub[name] nicht existiert. -- var:read_int(sub,name,norm) -- Gibt eine Zahl zur<EFBFBD>ck -| norm wird zur<75>ckgegeben, wenn sub[name] nicht existiert.
-- var:read_bool(sub,name,norm) -- Gibt true / False zurück -| -- var:read_bool(sub,name,norm) -- Gibt true / False zur<EFBFBD>ck -|
-- var:delete_key(sub,nm) -- var:delete_key(sub,nm)
-- var:delete_section(sub) -- var:delete_section(sub)
local ini_f = {} local ini_f = {}
@ -997,7 +998,7 @@ do
if self.sub[sub] == nil then return norm end if self.sub[sub] == nil then return norm end
if self.sub[sub][nm] == nil then return norm else return tonumber(self.sub[sub][nm]) end if self.sub[sub][nm] == nil then return norm else return tonumber(self.sub[sub][nm]) end
end end
function ini_f:read_bool(sub,nm,norm) -- Norm wird zurückgegeben, wenn der Key nm nicht existiert function ini_f:read_bool(sub,nm,norm) -- Norm wird zur<EFBFBD>ckgegeben, wenn der Key nm nicht existiert
if sub == '' or nm == '' or sub == nil or nm == nil then return end if sub == '' or nm == '' or sub == nil or nm == nil then return end
self:parse() self:parse()
if self.sub[sub] == nil then return norm end if self.sub[sub] == nil then return norm end
@ -1032,7 +1033,7 @@ end
Wie die alten col-Befehle, sendet aber selbst. Wie die alten col-Befehle, sendet aber selbst.
Also kein say(col.red('bla')) Also kein say(col.red('bla'))
sondern sondern
csay.red('bla') reicht völlig aus. csay.red('bla') reicht v<EFBFBD>llig aus.
--]] --]]
csay = setmetatable({__d = { csay = setmetatable({__d = {
["aliceblue"] = {240, 248, 255}, ["antiquewhite"] = {250, 235, 215}, ["aqua"] = {0, 255, 255}, ["aquamarine"] = {127, 255, 212}, ["aliceblue"] = {240, 248, 255}, ["antiquewhite"] = {250, 235, 215}, ["aqua"] = {0, 255, 255}, ["aquamarine"] = {127, 255, 212},
@ -1082,7 +1083,7 @@ csay = setmetatable({__d = {
@name Farbcodes @name Farbcodes
@author Mijago @author Mijago
@descr @descr
Farbcodes für Say Farbcodes f<EFBFBD>r Say
--]] --]]
col = col or {} col = col or {}
col.list= { col.list= {

View File

@ -30,6 +30,10 @@ target_compile_options(${PROJECT_NAME} PUBLIC -fsigned-char)
find_package(unofficial-libmysql REQUIRED) find_package(unofficial-libmysql REQUIRED)
target_link_libraries(${PROJECT_NAME} unofficial::libmysql::libmysql) target_link_libraries(${PROJECT_NAME} unofficial::libmysql::libmysql)
# Argon2
find_package(unofficial-argon2 CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} unofficial::argon2::libargon2)
# Crypto++ # Crypto++
find_package(cryptopp CONFIG REQUIRED) find_package(cryptopp CONFIG REQUIRED)
target_link_libraries (${PROJECT_NAME} cryptopp::cryptopp) target_link_libraries (${PROJECT_NAME} cryptopp::cryptopp)

View File

@ -284,9 +284,9 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
int col = 0; int col = 0;
// PASSWORD('%s'), password, securitycode, social_id, id, status // '%s', password, securitycode, social_id, id, status
char szEncrytPassword[45 + 1]; char szPlainPassword[128 + 1];
char szPassword[45 + 1]; char szHashedPassword[128 + 1];
char szMatrixCode[MATRIX_CODE_MAX_LEN + 1]; char szMatrixCode[MATRIX_CODE_MAX_LEN + 1];
char szSocialID[SOCIAL_ID_MAX_LEN + 1]; char szSocialID[SOCIAL_ID_MAX_LEN + 1];
char szStatus[ACCOUNT_STATUS_MAX_LEN + 1]; char szStatus[ACCOUNT_STATUS_MAX_LEN + 1];
@ -296,19 +296,19 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
{ {
SPDLOG_ERROR("error column {}", col); SPDLOG_ERROR("error column {}", col);
M2_DELETE(pinfo); M2_DELETE(pinfo);
break; break;
} }
strlcpy(szEncrytPassword, row[col++], sizeof(szEncrytPassword)); strlcpy(szPlainPassword, row[col++], sizeof(szPlainPassword));
if (!row[col]) if (!row[col])
{ {
SPDLOG_ERROR("error column {}", col); SPDLOG_ERROR("error column {}", col);
M2_DELETE(pinfo); M2_DELETE(pinfo);
break; break;
} }
strlcpy(szPassword, row[col++], sizeof(szPassword)); strlcpy(szHashedPassword, row[col++], sizeof(szHashedPassword));
if (!row[col]) if (!row[col])
{ {
@ -321,29 +321,29 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
} }
if (!row[col]) if (!row[col])
{ {
SPDLOG_ERROR("error column {}", col); SPDLOG_ERROR("error column {}", col);
M2_DELETE(pinfo); M2_DELETE(pinfo);
break; break;
} }
strlcpy(szSocialID, row[col++], sizeof(szSocialID)); strlcpy(szSocialID, row[col++], sizeof(szSocialID));
if (!row[col]) if (!row[col])
{ {
SPDLOG_ERROR("error column {}", col); SPDLOG_ERROR("error column {}", col);
M2_DELETE(pinfo); M2_DELETE(pinfo);
break; break;
} }
str_to_number(dwID, row[col++]); str_to_number(dwID, row[col++]);
if (!row[col]) if (!row[col])
{ {
SPDLOG_ERROR("error column {}", col); SPDLOG_ERROR("error column {}", col);
M2_DELETE(pinfo); M2_DELETE(pinfo);
break; break;
} }
strlcpy(szStatus, row[col++], sizeof(szStatus)); strlcpy(szStatus, row[col++], sizeof(szStatus));
@ -374,9 +374,9 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
SPDLOG_DEBUG("Create_Time {} {}", retValue, szCreateDate); SPDLOG_DEBUG("Create_Time {} {}", retValue, szCreateDate);
SPDLOG_DEBUG("Block Time {} ", strncmp(szCreateDate, g_stBlockDate.c_str(), 8)); SPDLOG_DEBUG("Block Time {} ", strncmp(szCreateDate, g_stBlockDate.c_str(), 8));
int nPasswordDiff = strcmp(szEncrytPassword, szPassword); bool loginStatus = hash_secure_verify(szHashedPassword, szPlainPassword);
if (nPasswordDiff) if (!loginStatus)
{ {
LoginFailure(d, "WRONGPWD"); LoginFailure(d, "WRONGPWD");
SPDLOG_DEBUG(" WRONGPWD"); SPDLOG_DEBUG(" WRONGPWD");

View File

@ -55,7 +55,7 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
return; return;
} }
// string 무결성을 위해 복사 // Copy for string integrity
char login[LOGIN_MAX_LEN + 1]; char login[LOGIN_MAX_LEN + 1];
trim_and_lower(pinfo->login, login, sizeof(login)); trim_and_lower(pinfo->login, login, sizeof(login));
@ -106,41 +106,18 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
char szLogin[LOGIN_MAX_LEN * 2 + 1]; char szLogin[LOGIN_MAX_LEN * 2 + 1];
DBManager::instance().EscapeString(szLogin, sizeof(szLogin), login, strlen(login)); DBManager::instance().EscapeString(szLogin, sizeof(szLogin), login, strlen(login));
// CHANNEL_SERVICE_LOGIN DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
if (Login_IsInChannelService(szLogin)) "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
{ "UNIX_TIMESTAMP(silver_expire),"
SPDLOG_DEBUG("ChannelServiceLogin [{}]", szLogin); "UNIX_TIMESTAMP(gold_expire),"
"UNIX_TIMESTAMP(safebox_expire),"
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p, "UNIX_TIMESTAMP(autoloot_expire),"
"SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0," "UNIX_TIMESTAMP(fish_mind_expire),"
"UNIX_TIMESTAMP(silver_expire)," "UNIX_TIMESTAMP(marriage_fast_expire),"
"UNIX_TIMESTAMP(gold_expire)," "UNIX_TIMESTAMP(money_drop_rate_expire),"
"UNIX_TIMESTAMP(safebox_expire)," "UNIX_TIMESTAMP(create_time)"
"UNIX_TIMESTAMP(autoloot_expire)," " FROM account WHERE login='%s'",
"UNIX_TIMESTAMP(fish_mind_expire)," szPasswd, szLogin);
"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,securitycode,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, BYTE bHeader, const char * c_pData) int CInputAuth::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)

View File

@ -1,5 +1,11 @@
#include <argon2.h>
#include "stdafx.h" #include "stdafx.h"
bool hash_secure_verify(const char *hashed_pwd, const char *plain_pwd)
{
return argon2id_verify(hashed_pwd, plain_pwd, strlen(plain_pwd)) == ARGON2_OK;
}
static int global_time_gap = 0; static int global_time_gap = 0;
time_t get_global_time() time_t get_global_time()

View File

@ -9,6 +9,8 @@
#define REMOVE_BIT(var, bit) ((var) &= ~(bit)) #define REMOVE_BIT(var, bit) ((var) &= ~(bit))
#define TOGGLE_BIT(var, bit) ((var) = (var) ^ (bit)) #define TOGGLE_BIT(var, bit) ((var) = (var) ^ (bit))
bool hash_secure_verify(const char *, const char *);
inline float DISTANCE_SQRT(int dx, int dy) inline float DISTANCE_SQRT(int dx, int dy)
{ {
return ::sqrt((float)dx * dx + (float)dy * dy); return ::sqrt((float)dx * dx + (float)dy * dy);