Add flexibility in login packets
* It's now possible to add custom data in the login packet * Add utility funciton to generate RSA keys * Make the protocol able to use RSA keys with 2048 bits or more
This commit is contained in:
		
							parent
							
								
									6c7a163197
								
							
						
					
					
						commit
						b7eef97239
					
				| 
						 | 
					@ -27,8 +27,7 @@ local function tryLogin(charInfo, tries)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CharacterList.hide()
 | 
					  CharacterList.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local locale = modules.client_locales.getCurrentLocale().name
 | 
					  g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
 | 
				
			||||||
  g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, locale)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...'))
 | 
					  loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...'))
 | 
				
			||||||
  connect(loadBox, { onCancel = function()
 | 
					  connect(loadBox, { onCancel = function()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,8 +215,7 @@ function EnterGame.doLogin()
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if modules.game_things.isLoaded() then
 | 
					  if modules.game_things.isLoaded() then
 | 
				
			||||||
    local locale = modules.client_locales.getCurrentLocale().name
 | 
					    protocolLogin:login(G.host, G.port, G.account, G.password)
 | 
				
			||||||
    protocolLogin:login(G.host, G.port, G.account, G.password, locale)
 | 
					 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    loadBox:destroy()
 | 
					    loadBox:destroy()
 | 
				
			||||||
    loadBox = nil
 | 
					    loadBox = nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,8 +66,6 @@ GameFormatCreatureName = 22
 | 
				
			||||||
GameSpellList = 23
 | 
					GameSpellList = 23
 | 
				
			||||||
GameClientPing = 24
 | 
					GameClientPing = 24
 | 
				
			||||||
GameExtendedClientPing = 25
 | 
					GameExtendedClientPing = 25
 | 
				
			||||||
GameUpdater = 26
 | 
					 | 
				
			||||||
GameLoginLocale = 27
 | 
					 | 
				
			||||||
GameDoubleHealth = 28
 | 
					GameDoubleHealth = 28
 | 
				
			||||||
GameDoubleSkills = 29
 | 
					GameDoubleSkills = 29
 | 
				
			||||||
GameChangeMapAwareRange = 30
 | 
					GameChangeMapAwareRange = 30
 | 
				
			||||||
| 
						 | 
					@ -78,7 +76,6 @@ GameDiagonalAnimatedText = 34
 | 
				
			||||||
GameLoginPending = 35
 | 
					GameLoginPending = 35
 | 
				
			||||||
GameNewSpeedLaw = 36
 | 
					GameNewSpeedLaw = 36
 | 
				
			||||||
GameForceFirstAutoWalkStep = 37
 | 
					GameForceFirstAutoWalkStep = 37
 | 
				
			||||||
GameLoginUUID = 38
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
TextColors = {
 | 
					TextColors = {
 | 
				
			||||||
  red       = '#f55e5e', --'#c83200'
 | 
					  red       = '#f55e5e', --'#c83200'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ function g_game.getRsa()
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function g_game.chooseRsa(host)
 | 
					function g_game.chooseRsa(host)
 | 
				
			||||||
 | 
					  if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
 | 
				
			||||||
  if string.ends(host, '.tibia.com') or string.ends(host, '.cipsoft.com') then
 | 
					  if string.ends(host, '.tibia.com') or string.ends(host, '.cipsoft.com') then
 | 
				
			||||||
    g_game.setRsa(CIPSOFT_RSA)
 | 
					    g_game.setRsa(CIPSOFT_RSA)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,11 +22,10 @@ function g_game.chooseRsa(host)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function g_game.setRsa(rsa)
 | 
					function g_game.setRsa(rsa, e)
 | 
				
			||||||
  if currentRsa ~= rsa then
 | 
					  e = e or '65537'
 | 
				
			||||||
    currentRsa = rsa
 | 
					  g_crypt.rsaSetPublicKey(rsa, e)
 | 
				
			||||||
    g_crypt.rsaSetPublicKey(currentRsa, '65537')
 | 
					  currentRsa = rsa
 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function g_game.isOfficialTibia()
 | 
					function g_game.isOfficialTibia()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ LoginServerUpdateNeeded = 30
 | 
				
			||||||
LoginServerCharacterList = 100
 | 
					LoginServerCharacterList = 100
 | 
				
			||||||
LoginServerExtendedCharacterList = 101
 | 
					LoginServerExtendedCharacterList = 101
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ProtocolLogin:login(host, port, accountName, accountPassword, locale)
 | 
					function ProtocolLogin:login(host, port, accountName, accountPassword)
 | 
				
			||||||
  if string.len(host) == 0 or port == nil or port == 0 then
 | 
					  if string.len(host) == 0 or port == nil or port == 0 then
 | 
				
			||||||
    signalcall(self.onError, self, tr("You must enter a valid server address and port."))
 | 
					    signalcall(self.onError, self, tr("You must enter a valid server address and port."))
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ function ProtocolLogin:login(host, port, accountName, accountPassword, locale)
 | 
				
			||||||
  self.accountName = accountName
 | 
					  self.accountName = accountName
 | 
				
			||||||
  self.accountPassword = accountPassword
 | 
					  self.accountPassword = accountPassword
 | 
				
			||||||
  self.connectCallback = sendLoginPacket
 | 
					  self.connectCallback = sendLoginPacket
 | 
				
			||||||
  self.locale = locale
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  self:connect(host, port)
 | 
					  self:connect(host, port)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -26,21 +25,11 @@ function ProtocolLogin:cancelLogin()
 | 
				
			||||||
  self:disconnect()
 | 
					  self:disconnect()
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ProtocolLogin:sendLoginPacket()
 | 
					function ProtocolLogin:sendLoginPacket(extended)
 | 
				
			||||||
  local msg = OutputMessage.create()
 | 
					  local msg = OutputMessage.create()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  msg:addU8(ClientOpcodes.ClientEnterAccount)
 | 
					  msg:addU8(ClientOpcodes.ClientEnterAccount)
 | 
				
			||||||
  msg:addU16(g_game.getOs())
 | 
					  msg:addU16(g_game.getOs())
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if g_game.getFeature(GameUpdater) then
 | 
					 | 
				
			||||||
    msg:addString(g_app.getOs())
 | 
					 | 
				
			||||||
    msg:addString(g_game.getUpdaterSignature())
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if g_game.getFeature(GameLoginLocale) then
 | 
					 | 
				
			||||||
    msg:addString(self.locale)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  msg:addU16(g_game.getProtocolVersion())
 | 
					  msg:addU16(g_game.getProtocolVersion())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if g_game.getProtocolVersion() >= 971 then
 | 
					  if g_game.getProtocolVersion() >= 971 then
 | 
				
			||||||
| 
						 | 
					@ -55,9 +44,10 @@ function ProtocolLogin:sendLoginPacket()
 | 
				
			||||||
    msg:addU8(0) -- clientType
 | 
					    msg:addU8(0) -- clientType
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local paddingBytes = 128
 | 
					  local offset = msg:getMessageSize()
 | 
				
			||||||
  msg:addU8(0) -- first RSA byte must be 0
 | 
					
 | 
				
			||||||
  paddingBytes = paddingBytes - 1
 | 
					   -- first RSA byte must be 0
 | 
				
			||||||
 | 
					  msg:addU8(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  -- xtea key
 | 
					  -- xtea key
 | 
				
			||||||
  self:generateXteaKey()
 | 
					  self:generateXteaKey()
 | 
				
			||||||
| 
						 | 
					@ -66,25 +56,29 @@ function ProtocolLogin:sendLoginPacket()
 | 
				
			||||||
  msg:addU32(xteaKey[2])
 | 
					  msg:addU32(xteaKey[2])
 | 
				
			||||||
  msg:addU32(xteaKey[3])
 | 
					  msg:addU32(xteaKey[3])
 | 
				
			||||||
  msg:addU32(xteaKey[4])
 | 
					  msg:addU32(xteaKey[4])
 | 
				
			||||||
  paddingBytes = paddingBytes - 16
 | 
					
 | 
				
			||||||
 | 
					  if g_game.getFeature(GameAccountNames) then
 | 
				
			||||||
 | 
					    msg:addString(self.accountName)
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    msg:addU32(tonumber(self.accountName))
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  msg:addString(self.accountPassword)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if self.getLoginExtendedData then
 | 
				
			||||||
 | 
					    local data = self:getLoginExtendedData()
 | 
				
			||||||
 | 
					    msg:addString(data)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset)
 | 
				
			||||||
 | 
					  assert(paddingBytes >= 0)
 | 
				
			||||||
 | 
					  msg:addPaddingBytes(paddingBytes, 0)
 | 
				
			||||||
 | 
					  msg:encryptRsa()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if g_game.getFeature(GameProtocolChecksum) then
 | 
					  if g_game.getFeature(GameProtocolChecksum) then
 | 
				
			||||||
    self:enableChecksum()
 | 
					    self:enableChecksum()
 | 
				
			||||||
  end
 | 
					  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, 0)
 | 
					 | 
				
			||||||
  msg:encryptRsa(128)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  self:send(msg)
 | 
					  self:send(msg)
 | 
				
			||||||
  self:enableXteaEncryption()
 | 
					  self:enableXteaEncryption()
 | 
				
			||||||
  self:recv()
 | 
					  self:recv()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,8 +337,6 @@ namespace Otc
 | 
				
			||||||
        GameSpellList = 23,
 | 
					        GameSpellList = 23,
 | 
				
			||||||
        GameClientPing = 24,
 | 
					        GameClientPing = 24,
 | 
				
			||||||
        GameExtendedClientPing = 25,
 | 
					        GameExtendedClientPing = 25,
 | 
				
			||||||
        GameUpdater = 26,
 | 
					 | 
				
			||||||
        GameLoginLocale = 27,
 | 
					 | 
				
			||||||
        GameDoubleHealth = 28,
 | 
					        GameDoubleHealth = 28,
 | 
				
			||||||
        GameDoubleSkills = 29,
 | 
					        GameDoubleSkills = 29,
 | 
				
			||||||
        GameChangeMapAwareRange = 30,
 | 
					        GameChangeMapAwareRange = 30,
 | 
				
			||||||
| 
						 | 
					@ -349,7 +347,6 @@ namespace Otc
 | 
				
			||||||
        GameLoginPending = 35,
 | 
					        GameLoginPending = 35,
 | 
				
			||||||
        GameNewSpeedLaw = 36,
 | 
					        GameNewSpeedLaw = 36,
 | 
				
			||||||
        GameForceFirstAutoWalkStep = 37,
 | 
					        GameForceFirstAutoWalkStep = 37,
 | 
				
			||||||
        GameLoginUUID = 38,
 | 
					 | 
				
			||||||
        // 51-100 reserved to be defined in lua
 | 
					        // 51-100 reserved to be defined in lua
 | 
				
			||||||
        LastGameFeature = 101
 | 
					        LastGameFeature = 101
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,7 +473,7 @@ void Game::processWalkCancel(Otc::Direction direction)
 | 
				
			||||||
    m_localPlayer->cancelWalk(direction);
 | 
					    m_localPlayer->cancelWalk(direction);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& locale)
 | 
					void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(m_protocolGame || isOnline())
 | 
					    if(m_protocolGame || isOnline())
 | 
				
			||||||
        stdext::throw_exception("Unable to login into a world while already online or logging.");
 | 
					        stdext::throw_exception("Unable to login into a world while already online or logging.");
 | 
				
			||||||
| 
						 | 
					@ -488,7 +488,7 @@ void Game::loginWorld(const std::string& account, const std::string& password, c
 | 
				
			||||||
    m_localPlayer->setName(characterName);
 | 
					    m_localPlayer->setName(characterName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_protocolGame = ProtocolGamePtr(new ProtocolGame);
 | 
					    m_protocolGame = ProtocolGamePtr(new ProtocolGame);
 | 
				
			||||||
    m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName, locale);
 | 
					    m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName);
 | 
				
			||||||
    m_characterName = characterName;
 | 
					    m_characterName = characterName;
 | 
				
			||||||
    m_worldName = worldName;
 | 
					    m_worldName = worldName;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@ protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    // login related
 | 
					    // login related
 | 
				
			||||||
    void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& locale);
 | 
					    void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName);
 | 
				
			||||||
    void cancelLogin();
 | 
					    void cancelLogin();
 | 
				
			||||||
    void forceLogout();
 | 
					    void forceLogout();
 | 
				
			||||||
    void safeLogout();
 | 
					    void safeLogout();
 | 
				
			||||||
| 
						 | 
					@ -270,9 +270,6 @@ public:
 | 
				
			||||||
    void setCustomOs(int os) { m_clientCustomOs = os; }
 | 
					    void setCustomOs(int os) { m_clientCustomOs = os; }
 | 
				
			||||||
    int getOs();
 | 
					    int getOs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void setUpdaterSignature(const std::string& sig) { m_clientSignature = sig; }
 | 
					 | 
				
			||||||
    std::string getUpdaterSignature() { return m_clientSignature; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool canPerformGameAction();
 | 
					    bool canPerformGameAction();
 | 
				
			||||||
    bool checkBotProtection();
 | 
					    bool checkBotProtection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,8 +238,6 @@ void Client::registerLuaFunctions()
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "setUpdaterSignature", &Game::setUpdaterSignature, &g_game);
 | 
					 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "getUpdaterSignature", &Game::getUpdaterSignature, &g_game);
 | 
					 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "setCustomOs", &Game::setCustomOs, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "setCustomOs", &Game::setCustomOs, &g_game);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "getOs", &Game::getOs, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "getOs", &Game::getOs, &g_game);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);
 | 
					    g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,12 +26,11 @@
 | 
				
			||||||
#include "item.h"
 | 
					#include "item.h"
 | 
				
			||||||
#include "localplayer.h"
 | 
					#include "localplayer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& locale)
 | 
					void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_accountName = accountName;
 | 
					    m_accountName = accountName;
 | 
				
			||||||
    m_accountPassword = accountPassword;
 | 
					    m_accountPassword = accountPassword;
 | 
				
			||||||
    m_characterName = characterName;
 | 
					    m_characterName = characterName;
 | 
				
			||||||
    m_locale = locale;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connect(host, port);
 | 
					    connect(host, port);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@
 | 
				
			||||||
class ProtocolGame : public Protocol
 | 
					class ProtocolGame : public Protocol
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& locale);
 | 
					    void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName);
 | 
				
			||||||
    void send(const OutputMessagePtr& outputMessage);
 | 
					    void send(const OutputMessagePtr& outputMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
 | 
					    void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
 | 
				
			||||||
| 
						 | 
					@ -235,7 +235,6 @@ private:
 | 
				
			||||||
    std::string m_accountName;
 | 
					    std::string m_accountName;
 | 
				
			||||||
    std::string m_accountPassword;
 | 
					    std::string m_accountPassword;
 | 
				
			||||||
    std::string m_characterName;
 | 
					    std::string m_characterName;
 | 
				
			||||||
    std::string m_locale;
 | 
					 | 
				
			||||||
    stdext::timer m_pingTimer;
 | 
					    stdext::timer m_pingTimer;
 | 
				
			||||||
    LocalPlayerPtr m_localPlayer;
 | 
					    LocalPlayerPtr m_localPlayer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,17 +53,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
 | 
				
			||||||
    OutputMessagePtr msg(new OutputMessage);
 | 
					    OutputMessagePtr msg(new OutputMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    msg->addU8(Proto::ClientPendingGame);
 | 
					    msg->addU8(Proto::ClientPendingGame);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    msg->addU16(g_game.getOs());
 | 
					    msg->addU16(g_game.getOs());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(g_game.getFeature(Otc::GameUpdater)) {
 | 
					 | 
				
			||||||
        msg->addString(g_app.getOs());
 | 
					 | 
				
			||||||
        msg->addString(g_game.getUpdaterSignature());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(g_game.getFeature(Otc::GameLoginLocale))
 | 
					 | 
				
			||||||
        msg->addString(m_locale);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    msg->addU16(g_game.getProtocolVersion());
 | 
					    msg->addU16(g_game.getProtocolVersion());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(g_game.getProtocolVersion() >= 971) {
 | 
					    if(g_game.getProtocolVersion() >= 971) {
 | 
				
			||||||
| 
						 | 
					@ -71,9 +61,9 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
 | 
				
			||||||
        msg->addU8(0); // clientType
 | 
					        msg->addU8(0); // clientType
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int paddingBytes = 128;
 | 
					    int offset = msg->getMessageSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    msg->addU8(0); // first RSA byte must be 0
 | 
					    msg->addU8(0); // first RSA byte must be 0
 | 
				
			||||||
    paddingBytes -= 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // xtea key
 | 
					    // xtea key
 | 
				
			||||||
    generateXteaKey();
 | 
					    generateXteaKey();
 | 
				
			||||||
| 
						 | 
					@ -82,46 +72,34 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
 | 
				
			||||||
    msg->addU32(m_xteaKey[2]);
 | 
					    msg->addU32(m_xteaKey[2]);
 | 
				
			||||||
    msg->addU32(m_xteaKey[3]);
 | 
					    msg->addU32(m_xteaKey[3]);
 | 
				
			||||||
    msg->addU8(0); // is gm set?
 | 
					    msg->addU8(0); // is gm set?
 | 
				
			||||||
    paddingBytes -= 17;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(g_game.getFeature(Otc::GameProtocolChecksum))
 | 
					    if(g_game.getFeature(Otc::GameAccountNames))
 | 
				
			||||||
        enableChecksum();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(g_game.getFeature(Otc::GameAccountNames)) {
 | 
					 | 
				
			||||||
        msg->addString(m_accountName);
 | 
					        msg->addString(m_accountName);
 | 
				
			||||||
        msg->addString(m_characterName);
 | 
					    else
 | 
				
			||||||
        msg->addString(m_accountPassword);
 | 
					 | 
				
			||||||
        paddingBytes -= 6 + m_accountName.length() + m_characterName.length() + m_accountPassword.length();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        msg->addU32(stdext::from_string<uint32>(m_accountName));
 | 
					        msg->addU32(stdext::from_string<uint32>(m_accountName));
 | 
				
			||||||
        msg->addString(m_characterName);
 | 
					 | 
				
			||||||
        msg->addString(m_accountPassword);
 | 
					 | 
				
			||||||
        paddingBytes -= 8 + m_characterName.length() + m_accountPassword.length();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(g_game.getFeature(Otc::GameLoginUUID)) {
 | 
					    msg->addString(m_characterName);
 | 
				
			||||||
        std::string uuid = g_crypt.getMachineUUID();
 | 
					    msg->addString(m_accountPassword);
 | 
				
			||||||
        msg->addString(uuid);
 | 
					 | 
				
			||||||
        paddingBytes -= 2 + uuid.length();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(g_game.getFeature(Otc::GameChallengeOnLogin)) {
 | 
					    if(g_game.getFeature(Otc::GameChallengeOnLogin)) {
 | 
				
			||||||
        msg->addU32(challengeTimestamp);
 | 
					        msg->addU32(challengeTimestamp);
 | 
				
			||||||
        msg->addU8(challengeRandom);
 | 
					        msg->addU8(challengeRandom);
 | 
				
			||||||
        paddingBytes -= 5;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(paddingBytes < 0) {
 | 
					    std::string extended = callLuaField<std::string>("getLoginExtendedData");
 | 
				
			||||||
        g_game.processLoginError("AccountName or Password or CharacterName are too big!\nPlease contact game support.");
 | 
					    if(!extended.empty())
 | 
				
			||||||
        g_game.processDisconnect();
 | 
					        msg->addString(extended);
 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // complete the 128 bytes for rsa encryption with zeros
 | 
					    // complete the bytes for rsa encryption with zeros
 | 
				
			||||||
 | 
					    int paddingBytes = g_crypt.rsaGetSize() - (msg->getMessageSize() - offset);
 | 
				
			||||||
 | 
					    assert(paddingBytes >= 0);
 | 
				
			||||||
    msg->addPaddingBytes(paddingBytes);
 | 
					    msg->addPaddingBytes(paddingBytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // encrypt with RSA
 | 
					    // encrypt with RSA
 | 
				
			||||||
    msg->encryptRsa(128);
 | 
					    msg->encryptRsa();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(g_game.getFeature(Otc::GameProtocolChecksum))
 | 
				
			||||||
 | 
					        enableChecksum();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    send(msg);
 | 
					    send(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,9 +117,11 @@ void Application::registerLuaFunctions()
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "decrypt", &Crypt::decrypt, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "decrypt", &Crypt::decrypt, &g_crypt);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "sha1Encode", &Crypt::sha1Encode, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "sha1Encode", &Crypt::sha1Encode, &g_crypt);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "md5Encode", &Crypt::md5Encode, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "md5Encode", &Crypt::md5Encode, &g_crypt);
 | 
				
			||||||
 | 
					    g_lua.bindSingletonFunction("g_crypt", "rsaGenerateKey", &Crypt::rsaGenerateKey, &g_crypt);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "rsaSetPublicKey", &Crypt::rsaSetPublicKey, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "rsaSetPublicKey", &Crypt::rsaSetPublicKey, &g_crypt);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "rsaSetPrivateKey", &Crypt::rsaSetPrivateKey, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "rsaSetPrivateKey", &Crypt::rsaSetPrivateKey, &g_crypt);
 | 
				
			||||||
    g_lua.bindSingletonFunction("g_crypt", "rsaCheckKey", &Crypt::rsaCheckKey, &g_crypt);
 | 
					    g_lua.bindSingletonFunction("g_crypt", "rsaCheckKey", &Crypt::rsaCheckKey, &g_crypt);
 | 
				
			||||||
 | 
					    g_lua.bindSingletonFunction("g_crypt", "rsaGetSize", &Crypt::rsaGetSize, &g_crypt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Clock
 | 
					    // Clock
 | 
				
			||||||
    g_lua.registerSingletonClass("g_clock");
 | 
					    g_lua.registerSingletonClass("g_clock");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,12 +89,14 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
 | 
				
			||||||
    m_messageSize += bytes;
 | 
					    m_messageSize += bytes;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OutputMessage::encryptRsa(int size)
 | 
					void OutputMessage::encryptRsa()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    int size = g_crypt.rsaGetSize();
 | 
				
			||||||
    if(m_messageSize < size)
 | 
					    if(m_messageSize < size)
 | 
				
			||||||
        throw stdext::exception("insufficient bytes in buffer to encrypt");
 | 
					        throw stdext::exception("insufficient bytes in buffer to encrypt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_crypt.rsaEncrypt((unsigned char*)m_buffer + m_writePos - size, size);
 | 
					    if(!g_crypt.rsaEncrypt((unsigned char*)m_buffer + m_writePos - size, size))
 | 
				
			||||||
 | 
					        throw stdext::exception("rsa encryption failed");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OutputMessage::writeChecksum()
 | 
					void OutputMessage::writeChecksum()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ public:
 | 
				
			||||||
    void addString(const std::string& buffer);
 | 
					    void addString(const std::string& buffer);
 | 
				
			||||||
    void addPaddingBytes(int bytes, uint8 byte = 0);
 | 
					    void addPaddingBytes(int bytes, uint8 byte = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void encryptRsa(int size);
 | 
					    void encryptRsa();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint16 getWritePos() { return m_writePos; }
 | 
					    uint16 getWritePos() { return m_writePos; }
 | 
				
			||||||
    uint16 getMessageSize() { return m_messageSize; }
 | 
					    uint16 getMessageSize() { return m_messageSize; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,11 +292,21 @@ std::string Crypt::sha512Encode(const std::string& decoded_string, bool upperCas
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Crypt::rsaGenerateKey(int bits, int e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    RSA *rsa = RSA_generate_key(bits, e, nullptr, nullptr);
 | 
				
			||||||
 | 
					    g_logger.info(stdext::format("%d bits (%d bytes) RSA key generated", bits, bits / 8));
 | 
				
			||||||
 | 
					    g_logger.info(std::string("p = ") + BN_bn2dec(m_rsa->p));
 | 
				
			||||||
 | 
					    g_logger.info(std::string("q = ") + BN_bn2dec(m_rsa->q));
 | 
				
			||||||
 | 
					    g_logger.info(std::string("d = ") + BN_bn2dec(m_rsa->d));
 | 
				
			||||||
 | 
					    g_logger.info(std::string("n = ") + BN_bn2dec(m_rsa->n));
 | 
				
			||||||
 | 
					    g_logger.info(std::string("e = ") + BN_bn2dec(m_rsa->e));
 | 
				
			||||||
 | 
					    RSA_free(rsa);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Crypt::rsaSetPublicKey(const std::string& n, const std::string& e)
 | 
					void Crypt::rsaSetPublicKey(const std::string& n, const std::string& e)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    RSA_free(m_rsa);
 | 
					 | 
				
			||||||
    m_rsa = RSA_new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    BN_dec2bn(&m_rsa->n, n.c_str());
 | 
					    BN_dec2bn(&m_rsa->n, n.c_str());
 | 
				
			||||||
    BN_dec2bn(&m_rsa->e, e.c_str());
 | 
					    BN_dec2bn(&m_rsa->e, e.c_str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -331,12 +341,20 @@ bool Crypt::rsaCheckKey()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Crypt::rsaEncrypt(unsigned char *msg, int size)
 | 
					bool Crypt::rsaEncrypt(unsigned char *msg, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(size <= 128);
 | 
					    if(size != RSA_size(m_rsa))
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
    return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
 | 
					    return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Crypt::rsaDecrypt(unsigned char *msg, int size)
 | 
					bool Crypt::rsaDecrypt(unsigned char *msg, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(size <= 128);
 | 
					    if(size != RSA_size(m_rsa))
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
    return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
 | 
					    return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int Crypt::rsaGetSize()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return RSA_size(m_rsa);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,11 +49,13 @@ public:
 | 
				
			||||||
    std::string sha256Encode(const std::string& decoded_string, bool upperCase);
 | 
					    std::string sha256Encode(const std::string& decoded_string, bool upperCase);
 | 
				
			||||||
    std::string sha512Encode(const std::string& decoded_string, bool upperCase);
 | 
					    std::string sha512Encode(const std::string& decoded_string, bool upperCase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void rsaGenerateKey(int bits, int e);
 | 
				
			||||||
    void rsaSetPublicKey(const std::string& n, const std::string& e);
 | 
					    void rsaSetPublicKey(const std::string& n, const std::string& e);
 | 
				
			||||||
    void rsaSetPrivateKey(const std::string &p, const std::string &q, const std::string &d);
 | 
					    void rsaSetPrivateKey(const std::string &p, const std::string &q, const std::string &d);
 | 
				
			||||||
    bool rsaCheckKey();
 | 
					    bool rsaCheckKey();
 | 
				
			||||||
    bool rsaEncrypt(unsigned char *msg, int size);
 | 
					    bool rsaEncrypt(unsigned char *msg, int size);
 | 
				
			||||||
    bool rsaDecrypt(unsigned char *msg, int size);
 | 
					    bool rsaDecrypt(unsigned char *msg, int size);
 | 
				
			||||||
 | 
					    int rsaGetSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    std::string getMachineKey();
 | 
					    std::string getMachineKey();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue