From 5c6d7d605541f76435cc9c69047f8adad00ae5e7 Mon Sep 17 00:00:00 2001 From: Kamil Date: Tue, 17 Nov 2020 03:21:41 +0100 Subject: [PATCH] added a sanity check for entering invalid characters --- src/CNLoginServer.cpp | 36 +++++++++++++++++++++++++++--------- src/Database.cpp | 6 ++++++ src/Database.hpp | 1 + 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 82543e7..9600ec8 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -255,7 +255,7 @@ void CNLoginServer::nameSave(CNSocket* sock, CNPacketData* data) { std::cout << "\tName: " << U16toU8(save->szFirstName) << " " << U16toU8(save->szLastName) << std::endl; ) - resp.iSlotNum = save->iSlotNum; + resp.iSlotNum = save->iSlotNum; resp.iGender = save->iGender; resp.iPC_UID = Database::createCharacter(save, loginSessions[sock].userID); memcpy(resp.szFirstName, save->szFirstName, sizeof(char16_t) * 9); @@ -273,6 +273,15 @@ void CNLoginServer::characterCreate(CNSocket* sock, CNPacketData* data) { return; sP_CL2LS_REQ_CHAR_CREATE* character = (sP_CL2LS_REQ_CHAR_CREATE*)data->buf; + + if (!(Database::validateCharacter(character->PCStyle.iPC_UID, loginSessions[sock].userID) || + loginSessions[sock].characters.find(character->PCStyle.iPC_UID) == loginSessions[sock].characters.end())) { + INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_FAIL, fail); + fail.iErrorCode = 2; + sock->sendPacket((void*)&fail, P_LS2CL_REP_SHARD_SELECT_FAIL, sizeof(sP_LS2CL_REP_SHARD_SELECT_FAIL)); + return; + } + Database::finishCharacter(character); DEBUGLOG( @@ -294,7 +303,7 @@ void CNLoginServer::characterCreate(CNSocket* sock, CNPacketData* data) { std::cout << "\tiEquipFootID: " << (int)character->sOn_Item.iEquipFootID << std::endl; ) - Player player = Database::getPlayer(character->PCStyle.iPC_UID); + Player player = Database::getPlayer(character->PCStyle.iPC_UID); int64_t UID = player.iID; INITSTRUCT(sP_LS2CL_REP_CHAR_CREATE_SUCC, resp); @@ -310,7 +319,7 @@ void CNLoginServer::characterCreate(CNSocket* sock, CNPacketData* data) { loginSessions[sock].lastHeartbeat = getTime(); sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_CREATE_SUCC, sizeof(sP_LS2CL_REP_CHAR_CREATE_SUCC)); - Database::updateSelected(loginSessions[sock].userID, player.slot); + Database::updateSelected(loginSessions[sock].userID, player.slot); } void CNLoginServer::characterDelete(CNSocket* sock, CNPacketData* data) { @@ -324,6 +333,7 @@ void CNLoginServer::characterDelete(CNSocket* sock, CNPacketData* data) { resp.iSlotNum = operationResult; sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_DELETE_SUCC, sizeof(sP_LS2CL_REP_CHAR_DELETE_SUCC)); loginSessions[sock].lastHeartbeat = getTime(); + loginSessions[sock].characters.erase(del->iPC_UID); } void CNLoginServer::characterSelect(CNSocket* sock, CNPacketData* data) { @@ -331,18 +341,26 @@ void CNLoginServer::characterSelect(CNSocket* sock, CNPacketData* data) { return; // character selected - sP_CL2LS_REQ_CHAR_SELECT* chararacter = (sP_CL2LS_REQ_CHAR_SELECT*)data->buf; + sP_CL2LS_REQ_CHAR_SELECT* character = (sP_CL2LS_REQ_CHAR_SELECT*)data->buf; INITSTRUCT(sP_LS2CL_REP_CHAR_SELECT_SUCC, resp); + if (!(Database::validateCharacter(character->iPC_UID, loginSessions[sock].userID) || + loginSessions[sock].characters.find(character->iPC_UID) == loginSessions[sock].characters.end())) { + INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_FAIL, fail); + fail.iErrorCode = 2; + sock->sendPacket((void*)&fail, P_LS2CL_REP_SHARD_SELECT_FAIL, sizeof(sP_LS2CL_REP_SHARD_SELECT_FAIL)); + return; + } + DEBUGLOG( - std::cout << "P_CL2LS_REQ_CHAR_SELECT:" << std::endl; - std::cout << "\tPC_UID: " << chararacter->iPC_UID << std::endl; + std::cout << "P_CL2LS_REQ_CHAR_SELECT:" << std::endl; + std::cout << "\tPC_UID: " << character->iPC_UID << std::endl; ) - loginSessions[sock].lastHeartbeat = getTime(); + loginSessions[sock].lastHeartbeat = getTime(); - loginSessions[sock].selectedChar = chararacter->iPC_UID; - Database::updateSelected(loginSessions[sock].userID, loginSessions[sock].characters[chararacter->iPC_UID].slot); + loginSessions[sock].selectedChar = character->iPC_UID; + Database::updateSelected(loginSessions[sock].userID, loginSessions[sock].characters[character->iPC_UID].slot); sock->sendPacket((void*)&resp, P_LS2CL_REP_CHAR_SELECT_SUCC, sizeof(sP_LS2CL_REP_CHAR_SELECT_SUCC)); } diff --git a/src/Database.cpp b/src/Database.cpp index d5bea4b..4199f5b 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -191,6 +191,12 @@ std::unique_ptr Database::findAccount(std::string login) { std::unique_ptr(new Account(find.front())); } +bool Database::validateCharacter(int characterID, int userID) { + return db.select(&DbPlayer::PlayerID, + where((c(&DbPlayer::PlayerID) == characterID) && (c(&DbPlayer::AccountID) == userID))) + .size() > 0; +} + bool Database::isNameFree(sP_CL2LS_REQ_CHECK_CHAR_NAME* nameCheck) { std::lock_guard lock(dbCrit); diff --git a/src/Database.hpp b/src/Database.hpp index d58f3dc..865fa5d 100644 --- a/src/Database.hpp +++ b/src/Database.hpp @@ -119,6 +119,7 @@ namespace Database { int addAccount(std::string login, std::string password); void updateSelected(int accountId, int playerId); std::unique_ptr findAccount(std::string login); + bool validateCharacter(int characterID, int userID); bool isNameFree(sP_CL2LS_REQ_CHECK_CHAR_NAME* nameCheck); // called after chosing name, returns ID int createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID);