Fix a vulnerability in password encryption
* There was an error in the encryption used to save passwords, now it's really harder to decrypt the password from the config file * Other minor changes
This commit is contained in:
parent
18af9a45ee
commit
07959ddc04
|
@ -82,6 +82,14 @@ function init()
|
||||||
|
|
||||||
g_keyboard.bindKeyDown('Ctrl+Shift+R', reloadScripts)
|
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 })
|
connect(g_app, { onRun = startup })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ function refresh()
|
||||||
|
|
||||||
local contentsPanel = skillsWindow:getChildById('contentsPanel')
|
local contentsPanel = skillsWindow:getChildById('contentsPanel')
|
||||||
skillsWindow:setContentMinimumHeight(44)
|
skillsWindow:setContentMinimumHeight(44)
|
||||||
skillsWindow:setContentMaximumHeight(contentsPanel:getChildrenRect().height)
|
skillsWindow:setContentMaximumHeight(390)
|
||||||
end
|
end
|
||||||
|
|
||||||
function offline()
|
function offline()
|
||||||
|
|
|
@ -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
|
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
|
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
|
if g_game.getProtocolVersion() >= 950 then -- Vocation is only send in newer clients
|
||||||
spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true)
|
spelllistWindow:getChildById('buttonFilterVocation'):setVisible(true)
|
||||||
else
|
else
|
||||||
|
@ -87,11 +92,13 @@ function setOptions()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function init()
|
function offline()
|
||||||
if g_game.getProtocolVersion() < 870 then return end
|
resetWindow()
|
||||||
|
end
|
||||||
|
|
||||||
connect(g_game, { onGameStart = setOptions,
|
function init()
|
||||||
onGameEnd = resetWindow })
|
connect(g_game, { onGameStart = online,
|
||||||
|
onGameEnd = offline })
|
||||||
|
|
||||||
spelllistWindow = g_ui.displayUI('spelllist', modules.game_interface.getRightPanel())
|
spelllistWindow = g_ui.displayUI('spelllist', modules.game_interface.getRightPanel())
|
||||||
spelllistWindow:hide()
|
spelllistWindow:hide()
|
||||||
|
@ -157,17 +164,12 @@ function init()
|
||||||
g_keyboard.bindKeyPress('Up', function() spellList:focusPreviousChild(KeyboardFocusReason) end, spelllistWindow)
|
g_keyboard.bindKeyPress('Up', function() spellList:focusPreviousChild(KeyboardFocusReason) end, spelllistWindow)
|
||||||
|
|
||||||
initialiseSpelllist()
|
initialiseSpelllist()
|
||||||
setOptions()
|
|
||||||
resizeWindow()
|
resizeWindow()
|
||||||
end
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
if g_game.getProtocolVersion() < 870 then return end
|
disconnect(g_game, { onGameStart = online,
|
||||||
|
onGameEnd = offline })
|
||||||
disconnect(g_game, { onGameStart = setOptions,
|
|
||||||
onGameEnd = resetWindow,
|
|
||||||
onSpellGroupCooldown = modules.game_interface.setGroupCooldown,
|
|
||||||
onSpellCooldown = onSpellCooldown })
|
|
||||||
|
|
||||||
disconnect(spellList, { onChildFocusChange = function(self, focusedChild)
|
disconnect(spellList, { onChildFocusChange = function(self, focusedChild)
|
||||||
if focusedChild == nil then return end
|
if focusedChild == nil then return end
|
||||||
|
|
|
@ -78,6 +78,7 @@ GameDiagonalAnimatedText = 34
|
||||||
GameLoginPending = 35
|
GameLoginPending = 35
|
||||||
GameNewSpeedLaw = 36
|
GameNewSpeedLaw = 36
|
||||||
GameForceFirstAutoWalkStep = 37
|
GameForceFirstAutoWalkStep = 37
|
||||||
|
GameLoginUUID = 38
|
||||||
|
|
||||||
TextColors = {
|
TextColors = {
|
||||||
red = '#f55e5e', --'#c83200'
|
red = '#f55e5e', --'#c83200'
|
||||||
|
|
|
@ -349,6 +349,7 @@ 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
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include <framework/core/application.h>
|
#include <framework/core/application.h>
|
||||||
|
#include <framework/platform/platform.h>
|
||||||
|
#include <framework/util/crypt.h>
|
||||||
|
|
||||||
void ProtocolGame::send(const OutputMessagePtr& outputMessage)
|
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();
|
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)) {
|
if(g_game.getFeature(Otc::GameChallengeOnLogin)) {
|
||||||
msg->addU32(challengeTimestamp);
|
msg->addU32(challengeTimestamp);
|
||||||
msg->addU8(challengeRandom);
|
msg->addU8(challengeRandom);
|
||||||
|
|
|
@ -68,7 +68,7 @@ bool ResourceManager::discoverWorkDir(const std::string& existentFile)
|
||||||
|
|
||||||
bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName)
|
bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName)
|
||||||
{
|
{
|
||||||
std::string userDir = PHYSFS_getUserDir();
|
std::string userDir = getUserDir();
|
||||||
std::string dirName;
|
std::string dirName;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
dirName = stdext::format(".%s", appWriteDirName);
|
dirName = stdext::format(".%s", appWriteDirName);
|
||||||
|
@ -306,6 +306,11 @@ std::string ResourceManager::getBaseDir()
|
||||||
return PHYSFS_getBaseDir();
|
return PHYSFS_getBaseDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ResourceManager::getUserDir()
|
||||||
|
{
|
||||||
|
return PHYSFS_getUserDir();
|
||||||
|
}
|
||||||
|
|
||||||
std::string ResourceManager::guessFileType(const std::string& filename, const std::string& type)
|
std::string ResourceManager::guessFileType(const std::string& filename, const std::string& type)
|
||||||
{
|
{
|
||||||
if(g_resources.fileExists(filename))
|
if(g_resources.fileExists(filename))
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
std::string getRealDir(const std::string& path);
|
std::string getRealDir(const std::string& path);
|
||||||
std::string getCurrentDir();
|
std::string getCurrentDir();
|
||||||
std::string getBaseDir();
|
std::string getBaseDir();
|
||||||
|
std::string getUserDir();
|
||||||
std::string getWriteDir() { return m_writeDir; }
|
std::string getWriteDir() { return m_writeDir; }
|
||||||
std::string getWorkDir() { return m_workDir; }
|
std::string getWorkDir() { return m_workDir; }
|
||||||
std::deque<std::string> getSearchPaths() { return m_searchPaths; }
|
std::deque<std::string> getSearchPaths() { return m_searchPaths; }
|
||||||
|
|
|
@ -111,6 +111,8 @@ void Application::registerLuaFunctions()
|
||||||
// Crypt
|
// Crypt
|
||||||
g_lua.registerSingletonClass("g_crypt");
|
g_lua.registerSingletonClass("g_crypt");
|
||||||
g_lua.bindSingletonFunction("g_crypt", "genUUID", &Crypt::genUUID, &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", "encrypt", &Crypt::encrypt, &g_crypt);
|
||||||
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);
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
#include "crypt.h"
|
#include "crypt.h"
|
||||||
#include <framework/stdext/math.h>
|
#include <framework/stdext/math.h>
|
||||||
#include <framework/core/logger.h>
|
#include <framework/core/logger.h>
|
||||||
|
#include <framework/core/resourcemanager.h>
|
||||||
|
#include <framework/platform/platform.h>
|
||||||
|
|
||||||
#include <boost/uuid/uuid.hpp>
|
|
||||||
#include <boost/uuid/uuid_generators.hpp>
|
#include <boost/uuid/uuid_generators.hpp>
|
||||||
#include <boost/uuid/uuid_io.hpp>
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
|
||||||
|
@ -157,10 +158,28 @@ std::string Crypt::genUUID()
|
||||||
return boost::uuids::to_string(u);
|
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<boost::uuids::uuid> uuid_hasher;
|
boost::hash<boost::uuids::uuid> 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;
|
std::string key;
|
||||||
key.assign((const char *)&hash, sizeof(hash));
|
key.assign((const char *)&hash, sizeof(hash));
|
||||||
return key;
|
return key;
|
||||||
|
@ -171,14 +190,14 @@ std::string Crypt::encrypt(const std::string& decrypted_string)
|
||||||
std::string tmp = "0000" + decrypted_string;
|
std::string tmp = "0000" + decrypted_string;
|
||||||
uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size());
|
uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size());
|
||||||
stdext::writeLE32((uint8*)&tmp[0], sum);
|
stdext::writeLE32((uint8*)&tmp[0], sum);
|
||||||
std::string encrypted = base64Encode(xorCrypt(tmp, genUUIDKey()));
|
std::string encrypted = base64Encode(xorCrypt(tmp, getMachineKey()));
|
||||||
return encrypted;
|
return encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Crypt::decrypt(const std::string& encrypted_string)
|
std::string Crypt::decrypt(const std::string& encrypted_string)
|
||||||
{
|
{
|
||||||
std::string decoded = base64Decode(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) {
|
if(tmp.length() >= 4) {
|
||||||
uint32 readsum = stdext::readLE32((const uint8*)tmp.c_str());
|
uint32 readsum = stdext::readLE32((const uint8*)tmp.c_str());
|
||||||
std::string decrypted_string = tmp.substr(4);
|
std::string decrypted_string = tmp.substr(4);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include "../stdext/types.h"
|
#include "../stdext/types.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/uuid/uuid.hpp>
|
||||||
|
|
||||||
typedef struct rsa_st RSA;
|
typedef struct rsa_st RSA;
|
||||||
|
|
||||||
class Crypt
|
class Crypt
|
||||||
|
@ -38,6 +40,8 @@ public:
|
||||||
std::string base64Decode(const std::string& encoded_string);
|
std::string base64Decode(const std::string& encoded_string);
|
||||||
std::string xorCrypt(const std::string& buffer, const std::string& key);
|
std::string xorCrypt(const std::string& buffer, const std::string& key);
|
||||||
std::string genUUID();
|
std::string genUUID();
|
||||||
|
bool setMachineUUID(const std::string& uuidstr);
|
||||||
|
std::string getMachineUUID();
|
||||||
std::string encrypt(const std::string& decrypted_string);
|
std::string encrypt(const std::string& decrypted_string);
|
||||||
std::string decrypt(const std::string& encrypted_string);
|
std::string decrypt(const std::string& encrypted_string);
|
||||||
std::string md5Encode(const std::string& decoded_string, bool upperCase);
|
std::string md5Encode(const std::string& decoded_string, bool upperCase);
|
||||||
|
@ -52,7 +56,8 @@ public:
|
||||||
bool rsaDecrypt(unsigned char *msg, int size);
|
bool rsaDecrypt(unsigned char *msg, int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string genUUIDKey();
|
std::string getMachineKey();
|
||||||
|
boost::uuids::uuid m_machineUUID;
|
||||||
RSA *m_rsa;
|
RSA *m_rsa;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue