diff --git a/modules/client_entergame/entergame.otmod b/modules/client_entergame/entergame.otmod index b8141fdf..e56508b9 100644 --- a/modules/client_entergame/entergame.otmod +++ b/modules/client_entergame/entergame.otmod @@ -8,7 +8,6 @@ Module - client_topmenu @onLoad: | - dofile 'protocollogin' dofile 'entergame' dofile 'characterlist' EnterGame.init() diff --git a/modules/client_entergame/protocollogin.lua b/modules/client_entergame/protocollogin.lua deleted file mode 100644 index 8f937a03..00000000 --- a/modules/client_entergame/protocollogin.lua +++ /dev/null @@ -1,184 +0,0 @@ -ProtocolLogin = extends(Protocol) - -function ProtocolLogin.create() - local protocolLogin = ProtocolLogin.internalCreate() - return protocolLogin -end - -LoginServerError = 10 -LoginServerMotd = 20 -LoginServerUpdateNeeded = 30 -LoginServerCharacterList = 100 - -GameExtendedOpcode = 0 -GameProtocolChecksum = 1 -GameAccountNames = 2 -GameChallangeOnLogin = 3 -GameStackposOnTileAddThing = 4 -GamePenalityOnDeath = 5 -GameNameOnNpcTrade = 6 -GameDoubleFreeCapacity = 7 -GameDoubleExperience = 8 -GameTotalCapacity = 9 -GameSkillsBase = 10 -GameAdditionalPlayerStats = 11 -GameIdOnCancelAttack = 12 -GameChannelPlayerList = 13 -GamePlayerMounts = 14 -GameEnvironmentEffect = 15 -GameCreatureType = 16 -GameCreatureAdditionalInfo = 17 -GameCreaturePassableInfo = 18 -GameItemAnimationPhase = 19 -GameTrucatedPingOpcode = 20 -GameReverseCreatureStack = 21 - -RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413" - -function ProtocolLogin:parseError(msg) - local errorMessage = msg:getString() - signalcall(self.onError, self, errorMessage, false) -end - -function ProtocolLogin:parseMotd(msg) - local motd = msg:getString() - signalcall(self.onMotd, self, motd) -end - -function ProtocolLogin:parseCharacterList(msg) - local characters = {} - local charactersCount = msg:getU8() - for i=1,charactersCount do - local character = {} - character[1] = msg:getString() - character[2] = msg:getString() - character[3] = iptostring(msg:getU32()) - character[4] = msg:getU16() - characters[i] = character - end - local premDays = msg:getU16() - signalcall(self.onCharacterList, self, characters, premDays) -end - -function ProtocolLogin:onOpcode(opcode, msg) - if opcode == LoginServerError then - self:parseError(msg) - elseif opcode == LoginServerMotd then - self:parseMotd(msg) - elseif opcode == LoginServerUpdateNeeded then - return false - elseif opcode == LoginServerCharacterList then - self:parseCharacterList(msg) - else - return false - end - return true -end - -function ProtocolLogin:sendLoginPacket() - local msg = OutputMessage.create() - msg:addU8(1) -- ClientEnterAccount - msg:addU16(1) -- ClientOs - msg:addU16(g_game.getClientVersion()) - - msg:addU32(g_thingsType.getSignature()) - msg:addU32(g_sprites.getSignature()) - msg:addU32(0) -- pic sig - - local paddingBytes = 128 - msg:addU8(0) -- first RSA byte must be 0 - paddingBytes = paddingBytes - 1 - - -- xtea key - self:generateXteaKey() - local xteaKey = self:getXteaKey() - msg:addU32(xteaKey[1]) - msg:addU32(xteaKey[2]) - msg:addU32(xteaKey[3]) - msg:addU32(xteaKey[4]) - paddingBytes = paddingBytes - 16 - - if g_game.getFeature(GameProtocolChecksum) then - self:enableChecksum() - end - - if g_game.getFeature(GameAccountNames) then - msg:addString(self.accountName) - msg:addString(self.accountPassword) - paddingBytes = paddingBytes - (4 + string.len(self.accountName) + string.len(self.accountPassword)) - else - msg:addU32(tonumber(self.accountName)) - msg:addString(self.accountPassword) - paddingBytes = paddingBytes - (6 + string.len(self.accountPassword)) - end - - msg:addPaddingBytes(paddingBytes) -- this crashes without 0 - msg:encryptRSA(128, RSA) - - self:send(msg) - self:enableChecksum() - self:recv() -end - --- void ProtocolLogin::sendLoginPacket() --- { --- OutputMessagePtr msg(new OutputMessage); - --- msg->addU8(Proto::ClientEnterAccount); --- msg->addU16(Proto::ClientOs); --- msg->addU16(Proto::ClientVersion); - --- msg->addU32(g_thingsType.getSignature()); // data signature --- msg->addU32(g_sprites.getSignature()); // sprite signature --- msg->addU32(Proto::PicSignature); // pic signature - --- int paddingBytes = 128; --- msg->addU8(0); // first RSA byte must be 0 --- paddingBytes -= 1; - --- // xtea key --- generateXteaKey(); - --- msg->addU32(m_xteaKey[0]); --- msg->addU32(m_xteaKey[1]); --- msg->addU32(m_xteaKey[2]); --- msg->addU32(m_xteaKey[3]); --- paddingBytes -= 16; - --- if(g_game.getFeature(Otc::GameProtocolChecksum)) --- enableChecksum(); - --- if(g_game.getFeature(Otc::GameAccountNames)) { --- msg->addString(m_accountName); --- msg->addString(m_accountPassword); --- paddingBytes -= 4 + m_accountName.length() + m_accountPassword.length(); --- } else { --- msg->addU32(stdext::from_string(m_accountName)); --- msg->addString(m_accountPassword); --- paddingBytes -= 6 + m_accountPassword.length(); --- } - --- msg->addPaddingBytes(paddingBytes); // complete the 128 bytes for rsa encryption with zeros --- msg->encryptRSA(128, Proto::RSA); - --- send(msg); --- enableXteaEncryption(); --- recv(); --- } - --- events -function ProtocolLogin:onConnect() - self:sendLoginPacket() -end - --- public functions -function ProtocolLogin:login(host, port, accountName, accountPassword) - if string.len(accountName) == 0 or string.len(accountPassword) == 0 then - signalcall(self.onError, self, "You must enter an account name and password.", false) - end - - self.accountName = accountName - self.accountPassword = accountPassword - - self:connect(host, port) -end diff --git a/modules/game/const.lua b/modules/game/const.lua index 24f65899..7092932e 100644 --- a/modules/game/const.lua +++ b/modules/game/const.lua @@ -31,3 +31,36 @@ NorthEast = 4 SouthEast = 5 SouthWest = 6 NorthWest = 7 + +ClientEnterAccount = 1 +ClientEnterGame = 10 + +LoginServerError = 10 +LoginServerMotd = 20 +LoginServerUpdateNeeded = 30 +LoginServerCharacterList = 100 + +GameExtendedOpcode = 0 +GameProtocolChecksum = 1 +GameAccountNames = 2 +GameChallangeOnLogin = 3 +GameStackposOnTileAddThing = 4 +GamePenalityOnDeath = 5 +GameNameOnNpcTrade = 6 +GameDoubleFreeCapacity = 7 +GameDoubleExperience = 8 +GameTotalCapacity = 9 +GameSkillsBase = 10 +GameAdditionalPlayerStats = 11 +GameIdOnCancelAttack = 12 +GameChannelPlayerList = 13 +GamePlayerMounts = 14 +GameEnvironmentEffect = 15 +GameCreatureType = 16 +GameCreatureAdditionalInfo = 17 +GameCreaturePassableInfo = 18 +GameItemAnimationPhase = 19 +GameTrucatedPingOpcode = 20 +GameReverseCreatureStack = 21 + +OTSERV_RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413" diff --git a/modules/game/game.otmod b/modules/game/game.otmod index d355baae..7771b880 100644 --- a/modules/game/game.otmod +++ b/modules/game/game.otmod @@ -38,6 +38,8 @@ Module dofile 'const' + dofile 'protocollogin' + dofile 'widgets/uigamemap' dofile 'widgets/uiitem' dofile 'widgets/uiminiwindow' diff --git a/modules/game/protocollogin.lua b/modules/game/protocollogin.lua new file mode 100644 index 00000000..ff327976 --- /dev/null +++ b/modules/game/protocollogin.lua @@ -0,0 +1,121 @@ +ProtocolLogin = extends(Protocol) + +-- private functions +local function sendLoginPacket(protocol) + local msg = OutputMessage.create() + msg:addU8(ClientEnterAccount) + msg:addU16(1) -- todo: ClientOs + msg:addU16(g_game.getClientVersion()) + + msg:addU32(g_thingsType.getSignature()) + msg:addU32(g_sprites.getSignature()) + msg:addU32(0) -- todo: pic signature + + local paddingBytes = 128 + msg:addU8(0) -- first RSA byte must be 0 + paddingBytes = paddingBytes - 1 + + -- xtea key + protocol:generateXteaKey() + local xteaKey = protocol:getXteaKey() + msg:addU32(xteaKey[1]) + msg:addU32(xteaKey[2]) + msg:addU32(xteaKey[3]) + msg:addU32(xteaKey[4]) + paddingBytes = paddingBytes - 16 + + if g_game.getFeature(GameProtocolChecksum) then + protocol:enableChecksum() + end + + if g_game.getFeature(GameAccountNames) then + msg:addString(protocol.accountName) + msg:addString(protocol.accountPassword) + paddingBytes = paddingBytes - (4 + string.len(protocol.accountName) + string.len(protocol.accountPassword)) + else + msg:addU32(tonumber(protocol.accountName)) + msg:addString(protocol.accountPassword) + paddingBytes = paddingBytes - (6 + string.len(protocol.accountPassword)) + end + + msg:addPaddingBytes(paddingBytes, 0) + msg:encryptRSA(128, OTSERV_RSA) -- todo: check whether to use cip or ot rsa + + protocol:send(msg) + protocol:enableXteaEncryption() + protocol:recv() +end + +-- events +function ProtocolLogin:onConnect() + self:connectCallback(self) +end + +function ProtocolLogin:onRecv(msg) + while not msg:eof() do + local opcode = msg:getU8() + if opcode == LoginServerError then + self:parseError(msg) + elseif opcode == LoginServerMotd then + self:parseMotd(msg) + elseif opcode == LoginServerUpdateNeeded then + signalcall(self.onError, self, "Client needs update.", false) + elseif opcode == LoginServerCharacterList then + self:parseCharacterList(msg) + else + self:parseOpcode(opcode, msg) + end + end + self:disconnect() +end + +-- public functions +function ProtocolLogin.create() + return ProtocolLogin.internalCreate() +end + +function ProtocolLogin:login(host, port, accountName, accountPassword) + if string.len(accountName) == 0 or string.len(accountPassword) == 0 then + signalcall(self.onError, self, "You must enter an account name and password.", false) + return + end + + self.accountName = accountName + self.accountPassword = accountPassword + self.connectCallback = sendLoginPacket + + self:connect(host, port) +end + +function ProtocolLogin:cancelLogin() + self:disconnect() +end + +function ProtocolLogin:parseError(msg) + local errorMessage = msg:getString() + signalcall(self.onError, self, errorMessage, false) +end + +function ProtocolLogin:parseMotd(msg) + local motd = msg:getString() + signalcall(self.onMotd, self, motd) +end + +function ProtocolLogin:parseCharacterList(msg) + local characters = {} + local charactersCount = msg:getU8() + for i=1,charactersCount do + local character = {} + character[1] = msg:getString() + character[2] = msg:getString() + character[3] = iptostring(msg:getU32()) + character[4] = msg:getU16() + characters[i] = character + end + local premDays = msg:getU16() + signalcall(self.onCharacterList, self, characters, premDays) +end + +function ProtocolLogin:parseOpcode(opcode, msg) + signalcall(self.onOpcode, self, opcode, msg) +end diff --git a/src/framework/net/outputmessage.cpp b/src/framework/net/outputmessage.cpp index 3c2955ac..9f52f3fe 100644 --- a/src/framework/net/outputmessage.cpp +++ b/src/framework/net/outputmessage.cpp @@ -91,6 +91,9 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte) void OutputMessage::encryptRSA(int size, const std::string& key) { + if(m_writePos - size < 0) + throw NetworkException("writePos - size < 0"); + RSA::encrypt((char*)m_buffer + m_writePos - size, size, key.c_str()); } diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index 8b8f0f86..7c45d683 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -229,3 +229,14 @@ void Protocol::onConnect() { callLuaField("onConnect"); } + +void Protocol::onRecv(const InputMessagePtr& inputMessage) +{ + callLuaField("onRecv", inputMessage); +} + +void Protocol::onError(const boost::system::error_code& err) +{ + callLuaField("onError", err.message(), true); + disconnect(); +} diff --git a/src/framework/net/protocol.h b/src/framework/net/protocol.h index 89baa1b0..bd4083fd 100644 --- a/src/framework/net/protocol.h +++ b/src/framework/net/protocol.h @@ -54,8 +54,8 @@ public: protected: virtual void onConnect(); - virtual void onRecv(const InputMessagePtr& inputMessage) {} - virtual void onError(const boost::system::error_code& err) {} + virtual void onRecv(const InputMessagePtr& inputMessage); + virtual void onError(const boost::system::error_code& err); uint32 m_xteaKey[4]; diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index 1a83cd55..63de03fb 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -57,7 +57,6 @@ SET(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ui/uimap.cpp # otclient net - ${CMAKE_CURRENT_LIST_DIR}/net/protocollogin.cpp ${CMAKE_CURRENT_LIST_DIR}/net/protocolgame.cpp ${CMAKE_CURRENT_LIST_DIR}/net/protocolgamesend.cpp ${CMAKE_CURRENT_LIST_DIR}/net/protocolgameparse.cpp diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 1dbe9b74..9b97c21f 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/src/otclient/net/protocollogin.cpp b/src/otclient/net/protocollogin.cpp deleted file mode 100644 index 387fd959..00000000 --- a/src/otclient/net/protocollogin.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "protocollogin.h" -#include -#include -#include -#include -#include -#include - -void ProtocolLogin::onRecv(const InputMessagePtr& msg) -{ - try { - while(!msg->eof()) { - int opcode = msg->getU8(); - - // try to parse in lua first - if(callLuaField("onOpcode", opcode, msg)) - continue; - - switch(opcode) { - case Proto::LoginServerUpdateNeeded: - callLuaField("onError", "Client needs update."); - break; - default: - stdext::throw_exception(stdext::format("unknown opcode %d", opcode)); - break; - } - } - } catch(stdext::exception& e) { - g_logger.error(stdext::format("Network exception in login protocol: %s", e.what())); - } - disconnect(); -} - -void ProtocolLogin::onError(const boost::system::error_code& error) -{ - callLuaField("onError", error.message(), true); - disconnect(); -} - -void ProtocolLogin::sendLoginPacket() -{ - OutputMessagePtr msg(new OutputMessage); - - msg->addU8(Proto::ClientEnterAccount); - msg->addU16(Proto::ClientOs); - msg->addU16(Proto::ClientVersion); - - msg->addU32(g_thingsType.getSignature()); // data signature - msg->addU32(g_sprites.getSignature()); // sprite signature - msg->addU32(Proto::PicSignature); // pic signature - - int paddingBytes = 128; - msg->addU8(0); // first RSA byte must be 0 - paddingBytes -= 1; - - // xtea key - generateXteaKey(); - - msg->addU32(m_xteaKey[0]); - msg->addU32(m_xteaKey[1]); - msg->addU32(m_xteaKey[2]); - msg->addU32(m_xteaKey[3]); - paddingBytes -= 16; - - if(g_game.getFeature(Otc::GameProtocolChecksum)) - enableChecksum(); - - if(g_game.getFeature(Otc::GameAccountNames)) { - msg->addString(m_accountName); - msg->addString(m_accountPassword); - paddingBytes -= 4 + m_accountName.length() + m_accountPassword.length(); - } else { - msg->addU32(stdext::from_string(m_accountName)); - msg->addString(m_accountPassword); - paddingBytes -= 6 + m_accountPassword.length(); - } - - msg->addPaddingBytes(paddingBytes); // complete the 128 bytes for rsa encryption with zeros - msg->encryptRSA(128, Proto::RSA); - - send(msg); - enableXteaEncryption(); - recv(); -} diff --git a/src/otclient/net/protocollogin.h b/src/otclient/net/protocollogin.h deleted file mode 100644 index 72049dc2..00000000 --- a/src/otclient/net/protocollogin.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef PROTOCOLLOGIN_H -#define PROTOCOLLOGIN_H - -#include "declarations.h" -#include - -class ProtocolLogin; -typedef std::shared_ptr ProtocolLoginPtr; - -class ProtocolLogin : public Protocol -{ -public: - static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); } - - void login(const std::string& host, int port, const std::string& accountName, const std::string& accountPassword); - void cancelLogin() { disconnect(); } - - void onConnect(); - void onRecv(const InputMessagePtr& inputMessage); - void onError(const boost::system::error_code& error); - - ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast(shared_from_this()); } - -private: - void sendLoginPacket(); - - std::string m_accountName, m_accountPassword; - -}; - -#endif