diff --git a/modules/client/client.lua b/modules/client/client.lua index ec7ed2c3..02e345fe 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -82,6 +82,14 @@ function init() g_keyboard.bindKeyDown('Ctrl+Shift+R', reloadScripts) + -- generate machine uuid, this is a security measure for storing passwords + if not g_crypt.setMachineUUID(g_configs.get('uuid')) then + local uuid = g_crypt.genUUID() + g_crypt.setMachineUUID(uuid) + g_configs.set('uuid', uuid) + g_configs.save() + end + connect(g_app, { onRun = startup }) end diff --git a/modules/game_skills/skills.lua b/modules/game_skills/skills.lua index 21a4e018..7811efe8 100644 --- a/modules/game_skills/skills.lua +++ b/modules/game_skills/skills.lua @@ -213,7 +213,7 @@ function refresh() local contentsPanel = skillsWindow:getChildById('contentsPanel') skillsWindow:setContentMinimumHeight(44) - skillsWindow:setContentMaximumHeight(contentsPanel:getChildrenRect().height) + skillsWindow:setContentMaximumHeight(390) end function offline() diff --git a/modules/game_spelllist/spelllist.lua b/modules/game_spelllist/spelllist.lua index 5d8fb051..458d2996 100644 --- a/modules/game_spelllist/spelllist.lua +++ b/modules/game_spelllist/spelllist.lua @@ -79,7 +79,12 @@ function getIconImageClip(id) return (((id-1)%12)*SpelllistSettings[SpelllistProfile].iconSize.width) .. ' ' .. ((math.ceil(id/12)-1)*SpelllistSettings[SpelllistProfile].iconSize.height) .. ' ' .. SpelllistSettings[SpelllistProfile].iconSize.width .. ' ' .. SpelllistSettings[SpelllistProfile].iconSize.height end -function setOptions() +function online() + if g_game.getProtocolVersion() < 870 then + spelllistButton:setVisible(false) + else + spelllistButton:setVisible(true) + end if g_game.getProtocolVersion() >= 950 then -- Vocation is only send in newer clients spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true) else @@ -87,11 +92,13 @@ function setOptions() end end -function init() - if g_game.getProtocolVersion() < 870 then return end +function offline() + resetWindow() +end - connect(g_game, { onGameStart = setOptions, - onGameEnd = resetWindow }) +function init() + connect(g_game, { onGameStart = online, + onGameEnd = offline }) spelllistWindow = g_ui.displayUI('spelllist', modules.game_interface.getRightPanel()) spelllistWindow:hide() @@ -157,17 +164,12 @@ function init() g_keyboard.bindKeyPress('Up', function() spellList:focusPreviousChild(KeyboardFocusReason) end, spelllistWindow) initialiseSpelllist() - setOptions() resizeWindow() end function terminate() - if g_game.getProtocolVersion() < 870 then return end - - disconnect(g_game, { onGameStart = setOptions, - onGameEnd = resetWindow, - onSpellGroupCooldown = modules.game_interface.setGroupCooldown, - onSpellCooldown = onSpellCooldown }) + disconnect(g_game, { onGameStart = online, + onGameEnd = offline }) disconnect(spellList, { onChildFocusChange = function(self, focusedChild) if focusedChild == nil then return end diff --git a/modules/gamelib/const.lua b/modules/gamelib/const.lua index 3b4c25df..03fab2e6 100644 --- a/modules/gamelib/const.lua +++ b/modules/gamelib/const.lua @@ -78,6 +78,7 @@ GameDiagonalAnimatedText = 34 GameLoginPending = 35 GameNewSpeedLaw = 36 GameForceFirstAutoWalkStep = 37 +GameLoginUUID = 38 TextColors = { red = '#f55e5e', --'#c83200' diff --git a/src/client/const.h b/src/client/const.h index afee6ada..817b8db2 100644 --- a/src/client/const.h +++ b/src/client/const.h @@ -349,6 +349,7 @@ namespace Otc GameLoginPending = 35, GameNewSpeedLaw = 36, GameForceFirstAutoWalkStep = 37, + GameLoginUUID = 38, // 51-100 reserved to be defined in lua LastGameFeature = 101 }; diff --git a/src/client/protocolgamesend.cpp b/src/client/protocolgamesend.cpp index c6c2c007..f388a7e3 100644 --- a/src/client/protocolgamesend.cpp +++ b/src/client/protocolgamesend.cpp @@ -24,6 +24,8 @@ #include "game.h" #include "client.h" #include +#include +#include void ProtocolGame::send(const OutputMessagePtr& outputMessage) { @@ -97,6 +99,12 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando paddingBytes -= 8 + m_characterName.length() + m_accountPassword.length(); } + if(g_game.getFeature(Otc::GameLoginUUID)) { + std::string uuid = g_crypt.getMachineUUID(); + msg->addString(uuid); + paddingBytes -= 2 + uuid.length(); + } + if(g_game.getFeature(Otc::GameChallengeOnLogin)) { msg->addU32(challengeTimestamp); msg->addU8(challengeRandom); diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp index 70455e95..806d650b 100644 --- a/src/framework/core/resourcemanager.cpp +++ b/src/framework/core/resourcemanager.cpp @@ -68,7 +68,7 @@ bool ResourceManager::discoverWorkDir(const std::string& existentFile) bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName) { - std::string userDir = PHYSFS_getUserDir(); + std::string userDir = getUserDir(); std::string dirName; #ifndef WIN32 dirName = stdext::format(".%s", appWriteDirName); @@ -306,6 +306,11 @@ std::string ResourceManager::getBaseDir() return PHYSFS_getBaseDir(); } +std::string ResourceManager::getUserDir() +{ + return PHYSFS_getUserDir(); +} + std::string ResourceManager::guessFileType(const std::string& filename, const std::string& type) { if(g_resources.fileExists(filename)) diff --git a/src/framework/core/resourcemanager.h b/src/framework/core/resourcemanager.h index 1938a1fa..40588b46 100644 --- a/src/framework/core/resourcemanager.h +++ b/src/framework/core/resourcemanager.h @@ -66,6 +66,7 @@ public: std::string getRealDir(const std::string& path); std::string getCurrentDir(); std::string getBaseDir(); + std::string getUserDir(); std::string getWriteDir() { return m_writeDir; } std::string getWorkDir() { return m_workDir; } std::deque getSearchPaths() { return m_searchPaths; } diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 6241f53b..1d0b15d1 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -111,6 +111,8 @@ void Application::registerLuaFunctions() // Crypt g_lua.registerSingletonClass("g_crypt"); g_lua.bindSingletonFunction("g_crypt", "genUUID", &Crypt::genUUID, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "setMachineUUID", &Crypt::setMachineUUID, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "getMachineUUID", &Crypt::getMachineUUID, &g_crypt); g_lua.bindSingletonFunction("g_crypt", "encrypt", &Crypt::encrypt, &g_crypt); g_lua.bindSingletonFunction("g_crypt", "decrypt", &Crypt::decrypt, &g_crypt); g_lua.bindSingletonFunction("g_crypt", "sha1Encode", &Crypt::sha1Encode, &g_crypt); diff --git a/src/framework/util/crypt.cpp b/src/framework/util/crypt.cpp index 3a94e582..52b854f7 100644 --- a/src/framework/util/crypt.cpp +++ b/src/framework/util/crypt.cpp @@ -23,8 +23,9 @@ #include "crypt.h" #include #include +#include +#include -#include #include #include @@ -157,10 +158,28 @@ std::string Crypt::genUUID() return boost::uuids::to_string(u); } -std::string Crypt::genUUIDKey() +bool Crypt::setMachineUUID(const std::string& uuidstr) +{ + if(uuidstr.empty()) + return false; + std::stringstream ss; + ss << uuidstr; + ss >> m_machineUUID; + return !m_machineUUID.is_nil(); +} + +std::string Crypt::getMachineUUID() +{ + return boost::uuids::to_string(m_machineUUID); +} + +std::string Crypt::getMachineKey() { boost::hash uuid_hasher; - std::size_t hash = uuid_hasher(boost::uuids::uuid()); + + boost::uuids::name_generator gen(m_machineUUID); + boost::uuids::uuid u = gen(g_platform.getCPUName() + g_platform.getOSName() + g_resources.getUserDir()); + std::size_t hash = uuid_hasher(u); std::string key; key.assign((const char *)&hash, sizeof(hash)); return key; @@ -171,14 +190,14 @@ std::string Crypt::encrypt(const std::string& decrypted_string) std::string tmp = "0000" + decrypted_string; uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size()); stdext::writeLE32((uint8*)&tmp[0], sum); - std::string encrypted = base64Encode(xorCrypt(tmp, genUUIDKey())); + std::string encrypted = base64Encode(xorCrypt(tmp, getMachineKey())); return encrypted; } std::string Crypt::decrypt(const std::string& encrypted_string) { std::string decoded = base64Decode(encrypted_string); - std::string tmp = xorCrypt(base64Decode(encrypted_string), genUUIDKey()); + std::string tmp = xorCrypt(base64Decode(encrypted_string), getMachineKey()); if(tmp.length() >= 4) { uint32 readsum = stdext::readLE32((const uint8*)tmp.c_str()); std::string decrypted_string = tmp.substr(4); diff --git a/src/framework/util/crypt.h b/src/framework/util/crypt.h index 1bda09f8..79ebb6bf 100644 --- a/src/framework/util/crypt.h +++ b/src/framework/util/crypt.h @@ -26,6 +26,8 @@ #include "../stdext/types.h" #include +#include + typedef struct rsa_st RSA; class Crypt @@ -38,6 +40,8 @@ public: std::string base64Decode(const std::string& encoded_string); std::string xorCrypt(const std::string& buffer, const std::string& key); std::string genUUID(); + bool setMachineUUID(const std::string& uuidstr); + std::string getMachineUUID(); std::string encrypt(const std::string& decrypted_string); std::string decrypt(const std::string& encrypted_string); std::string md5Encode(const std::string& decoded_string, bool upperCase); @@ -52,7 +56,8 @@ public: bool rsaDecrypt(unsigned char *msg, int size); private: - std::string genUUIDKey(); + std::string getMachineKey(); + boost::uuids::uuid m_machineUUID; RSA *m_rsa; };