1
0
forked from 0ad/0ad

Fix Unicode support in lobby.

Fix EncryptPassword being called with the wrong argument order, and
encrypting username instead of password. (This will break all existing
lobby accounts.)

Fix EncryptPassword not using all of salt_base.

This was SVN commit r14123.
This commit is contained in:
Ykkrosh 2013-11-09 23:26:17 +00:00
parent 35d48d2fe8
commit d7ec8c47a6
4 changed files with 114 additions and 77 deletions

View File

@ -621,23 +621,27 @@ bool HasXmppClient(void* UNUSED(cbdata))
}
#if CONFIG2_LOBBY
void StartXmppClient(void* cbdata, std::string sUsername, std::string sPassword, std::string sRoom, std::string sNick)
void StartXmppClient(void* cbdata, std::wstring username, std::wstring password, std::wstring room, std::wstring nick)
{
CGUIManager* guiManager = static_cast<CGUIManager*> (cbdata);
ENSURE(!g_XmppClient);
g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), sUsername, sPassword, sRoom, sNick);
g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(),
utf8_from_wstring(username), utf8_from_wstring(password),
utf8_from_wstring(room), utf8_from_wstring(nick));
g_rankedGame = true;
}
void StartRegisterXmppClient(void* cbdata, std::string sUsername, std::string sPassword)
void StartRegisterXmppClient(void* cbdata, std::wstring username, std::wstring password)
{
CGUIManager* guiManager = static_cast<CGUIManager*> (cbdata);
ENSURE(!g_XmppClient);
g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), sUsername, sPassword, "", "", true);
g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(),
utf8_from_wstring(username), utf8_from_wstring(password),
"", "", true);
}
void StopXmppClient(void* UNUSED(cbdata))
@ -701,11 +705,11 @@ void SendUnregisterGame(void* UNUSED(cbdata))
g_XmppClient->SendIqUnregisterGame();
}
void SendChangeStateGame(void* UNUSED(cbdata), std::string nbp, std::string players)
void SendChangeStateGame(void* UNUSED(cbdata), std::wstring nbp, std::wstring players)
{
if (!g_XmppClient)
return;
g_XmppClient->SendIqChangeStateGame(nbp, players);
g_XmppClient->SendIqChangeStateGame(utf8_from_wstring(nbp), utf8_from_wstring(players));
}
CScriptVal GetPlayerList(void* UNUSED(cbdata))
@ -748,102 +752,101 @@ CScriptVal LobbyGuiPollMessage(void* UNUSED(cbdata))
return poll.get();
}
void LobbySendMessage(void* UNUSED(cbdata), std::string message)
void LobbySendMessage(void* UNUSED(cbdata), std::wstring message)
{
if (!g_XmppClient)
return;
g_XmppClient->SendMUCMessage(message);
g_XmppClient->SendMUCMessage(utf8_from_wstring(message));
}
void LobbySetPlayerPresence(void* UNUSED(cbdata), std::string presence)
void LobbySetPlayerPresence(void* UNUSED(cbdata), std::wstring presence)
{
if (!g_XmppClient)
return;
g_XmppClient->SetPresence(presence);
g_XmppClient->SetPresence(utf8_from_wstring(presence));
}
void LobbySetNick(void* UNUSED(cbdata), std::string nick)
void LobbySetNick(void* UNUSED(cbdata), std::wstring nick)
{
if (!g_XmppClient)
return;
g_XmppClient->SetNick(nick);
g_XmppClient->SetNick(utf8_from_wstring(nick));
}
std::string LobbyGetNick(void* UNUSED(cbdata))
std::wstring LobbyGetNick(void* UNUSED(cbdata))
{
if (!g_XmppClient)
return "";
return L"";
std::string nick;
g_XmppClient->GetNick(nick);
return nick;
return wstring_from_utf8(nick);
}
void LobbyKick(void* UNUSED(cbdata), std::string nick, std::string reason)
void LobbyKick(void* UNUSED(cbdata), std::wstring nick, std::wstring reason)
{
if (!g_XmppClient)
return;
g_XmppClient->kick(nick, reason);
g_XmppClient->kick(utf8_from_wstring(nick), utf8_from_wstring(reason));
}
void LobbyBan(void* UNUSED(cbdata), std::string nick, std::string reason)
void LobbyBan(void* UNUSED(cbdata), std::wstring nick, std::wstring reason)
{
if (!g_XmppClient)
return;
g_XmppClient->ban(nick, reason);
g_XmppClient->ban(utf8_from_wstring(nick), utf8_from_wstring(reason));
}
std::string LobbyGetPlayerPresence(void* UNUSED(cbdata), std::string nickname)
std::wstring LobbyGetPlayerPresence(void* UNUSED(cbdata), std::wstring nickname)
{
if (!g_XmppClient)
return "";
return L"";
std::string presence;
g_XmppClient->GetPresence(nickname, presence);
return presence;
g_XmppClient->GetPresence(utf8_from_wstring(nickname), presence);
return wstring_from_utf8(presence);
}
// Non-public secure PBKDF2 hash function with salting and 1,337 iterations
void EncryptPassword(const std::string& username, std::string& password)
static std::string EncryptPassword(const std::string& password, const std::string& username)
{
const int DIGESTSIZE = SHA_DIGEST_SIZE;
const int ITERATIONS = 1337;
const int DIGESTSIZE = SHA_DIGEST_SIZE;
const int ITERATIONS = 1337;
static const byte salt_base[DIGESTSIZE] = {
244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 };
static const byte salt_base[DIGESTSIZE] = {
244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 };
// initialize the salt buffer
byte salt_buffer[DIGESTSIZE] = {0};
SHA256 hash;
hash.update(salt_base, username.length());
hash.update(username.c_str(), username.length());
hash.finish(salt_buffer);
// initialize the salt buffer
byte salt_buffer[DIGESTSIZE] = {0};
SHA256 hash;
hash.update(salt_base, sizeof(salt_base));
hash.update(username.c_str(), username.length());
hash.finish(salt_buffer);
// PBKDF2 to create the buffer
byte encrypted[DIGESTSIZE];
pbkdf2(encrypted, (byte*)password.c_str(), password.length(), salt_buffer, DIGESTSIZE, ITERATIONS);
// PBKDF2 to create the buffer
byte encrypted[DIGESTSIZE];
pbkdf2(encrypted, (byte*)password.c_str(), password.length(), salt_buffer, DIGESTSIZE, ITERATIONS);
static const char base16[] = "0123456789ABCDEF";
char hex[2 * DIGESTSIZE];
for(int i = 0; i < DIGESTSIZE; ++i)
{
hex[i*2] = base16[encrypted[i] >> 4]; // 4 high bits
hex[i*2 + 1] = base16[encrypted[i] & 0x0F];// 4 low bits
}
password.assign(hex, sizeof(hex));
static const char base16[] = "0123456789ABCDEF";
char hex[2 * DIGESTSIZE];
for (int i = 0; i < DIGESTSIZE; ++i)
{
hex[i*2] = base16[encrypted[i] >> 4]; // 4 high bits
hex[i*2 + 1] = base16[encrypted[i] & 0x0F];// 4 low bits
}
return std::string(hex, sizeof(hex));
}
// Public hash interface.
std::string EncryptPassword(void* UNUSED(cbdata), std::string user, std::string pass)
std::wstring EncryptPassword(void* UNUSED(cbdata), std::wstring pass, std::wstring user)
{
EncryptPassword(user, pass);
return pass;
return wstring_from_utf8(EncryptPassword(utf8_from_wstring(pass), utf8_from_wstring(user)));
}
bool IsRankedGame(void* UNUSED(cbdata))
@ -969,8 +972,8 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
// Lobby functions
scriptInterface.RegisterFunction<bool, &HasXmppClient>("HasXmppClient");
#if CONFIG2_LOBBY // Allow the lobby to be disabled
scriptInterface.RegisterFunction<void, std::string, std::string, std::string, std::string, &StartXmppClient>("StartXmppClient");
scriptInterface.RegisterFunction<void, std::string, std::string, &StartRegisterXmppClient>("StartRegisterXmppClient");
scriptInterface.RegisterFunction<void, std::wstring, std::wstring, std::wstring, std::wstring, &StartXmppClient>("StartXmppClient");
scriptInterface.RegisterFunction<void, std::wstring, std::wstring, &StartRegisterXmppClient>("StartRegisterXmppClient");
scriptInterface.RegisterFunction<void, &StopXmppClient>("StopXmppClient");
scriptInterface.RegisterFunction<void, &ConnectXmppClient>("ConnectXmppClient");
scriptInterface.RegisterFunction<void, &DisconnectXmppClient>("DisconnectXmppClient");
@ -980,19 +983,19 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<void, CScriptVal, &SendRegisterGame>("SendRegisterGame");
scriptInterface.RegisterFunction<void, CScriptVal, &SendGameReport>("SendGameReport");
scriptInterface.RegisterFunction<void, &SendUnregisterGame>("SendUnregisterGame");
scriptInterface.RegisterFunction<void, std::string, std::string, &SendChangeStateGame>("SendChangeStateGame");
scriptInterface.RegisterFunction<void, std::wstring, std::wstring, &SendChangeStateGame>("SendChangeStateGame");
scriptInterface.RegisterFunction<CScriptVal, &GetPlayerList>("GetPlayerList");
scriptInterface.RegisterFunction<CScriptVal, &GetGameList>("GetGameList");
scriptInterface.RegisterFunction<CScriptVal, &GetBoardList>("GetBoardList");
scriptInterface.RegisterFunction<CScriptVal, &LobbyGuiPollMessage>("LobbyGuiPollMessage");
scriptInterface.RegisterFunction<void, std::string, &LobbySendMessage>("LobbySendMessage");
scriptInterface.RegisterFunction<void, std::string, &LobbySetPlayerPresence>("LobbySetPlayerPresence");
scriptInterface.RegisterFunction<void, std::string, &LobbySetNick>("LobbySetNick");
scriptInterface.RegisterFunction<std::string, &LobbyGetNick>("LobbyGetNick");
scriptInterface.RegisterFunction<void, std::string, std::string, &LobbyKick>("LobbyKick");
scriptInterface.RegisterFunction<void, std::string, std::string, &LobbyBan>("LobbyBan");
scriptInterface.RegisterFunction<std::string, std::string, &LobbyGetPlayerPresence>("LobbyGetPlayerPresence");
scriptInterface.RegisterFunction<std::string, std::string, std::string, &EncryptPassword>("EncryptPassword");
scriptInterface.RegisterFunction<void, std::wstring, &LobbySendMessage>("LobbySendMessage");
scriptInterface.RegisterFunction<void, std::wstring, &LobbySetPlayerPresence>("LobbySetPlayerPresence");
scriptInterface.RegisterFunction<void, std::wstring, &LobbySetNick>("LobbySetNick");
scriptInterface.RegisterFunction<std::wstring, &LobbyGetNick>("LobbyGetNick");
scriptInterface.RegisterFunction<void, std::wstring, std::wstring, &LobbyKick>("LobbyKick");
scriptInterface.RegisterFunction<void, std::wstring, std::wstring, &LobbyBan>("LobbyBan");
scriptInterface.RegisterFunction<std::wstring, std::wstring, &LobbyGetPlayerPresence>("LobbyGetPlayerPresence");
scriptInterface.RegisterFunction<std::wstring, std::wstring, std::wstring, &EncryptPassword>("EncryptPassword");
scriptInterface.RegisterFunction<bool, &IsRankedGame>("IsRankedGame");
scriptInterface.RegisterFunction<void, bool, &SetRankedGame>("SetRankedGame");
#endif // CONFIG2_LOBBY

View File

@ -19,6 +19,8 @@
#include "XmppClient.h"
#include "StanzaExtensions.h"
#include "lib/utf8.h"
// Debug
// TODO: Use builtin error/warning/logging functions.
#include <iostream>
@ -301,9 +303,9 @@ void XmppClient::SendIqGameReport(CScriptVal data)
m_ScriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties);
for (std::vector<int>::size_type i = 0; i != properties.size(); i++)
{
std::string value;
std::wstring value;
m_ScriptInterface.GetProperty(dataval, properties[i].c_str(), value);
report->addAttribute(properties[i], value);
report->addAttribute(properties[i], utf8_from_wstring(value));
}
// Add stanza to IQ
@ -338,9 +340,9 @@ void XmppClient::SendIqRegisterGame(CScriptVal data)
m_ScriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties);
for (std::vector<int>::size_type i = 0; i != properties.size(); i++)
{
std::string value;
std::wstring value;
m_ScriptInterface.GetProperty(dataval, properties[i].c_str(), value);
game->addAttribute(properties[i], value);
game->addAttribute(properties[i], utf8_from_wstring(value));
}
// Push the stanza onto the IQ
@ -470,10 +472,10 @@ CScriptValRooted XmppClient::GUIGetPlayerList()
CScriptValRooted player;
GetPresenceString(it->second, presence);
m_ScriptInterface.Eval("({})", player);
m_ScriptInterface.SetProperty(player.get(), "name", it->first.c_str());
m_ScriptInterface.SetProperty(player.get(), "presence", presence.c_str());
m_ScriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first));
m_ScriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(presence));
m_ScriptInterface.SetProperty(playerList.get(), it->first.c_str(), player);
m_ScriptInterface.SetProperty(playerList.get(), wstring_from_utf8(it->first).c_str(), player);
}
return playerList;
@ -496,7 +498,7 @@ CScriptValRooted XmppClient::GUIGetGameList()
const char* stats[] = { "name", "ip", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
short stats_length = 11;
for (short i = 0; i < stats_length; i++)
m_ScriptInterface.SetProperty(game.get(), stats[i], (*it)->findAttribute(stats[i]).c_str());
m_ScriptInterface.SetProperty(game.get(), stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string()));
m_ScriptInterface.CallFunctionVoid(gameList.get(), "push", game);
}
@ -521,7 +523,7 @@ CScriptValRooted XmppClient::GUIGetBoardList()
const char* attributes[] = { "name", "rank", "rating" };
short attributes_length = 3;
for (short i = 0; i < attributes_length; i++)
m_ScriptInterface.SetProperty(board.get(), attributes[i], (*it)->findAttribute(attributes[i]).c_str());
m_ScriptInterface.SetProperty(board.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string()));
m_ScriptInterface.CallFunctionVoid(boardList.get(), "push", board);
}
@ -574,8 +576,8 @@ void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Me
CScriptValRooted message;
m_ScriptInterface.Eval("({ 'type':'mucmessage'})", message);
m_ScriptInterface.SetProperty(message.get(), "from", msg.from().resource().to_string());
m_ScriptInterface.SetProperty(message.get(), "text", msg.body().to_string());
m_ScriptInterface.SetProperty(message.get(), "from", wstring_from_utf8(msg.from().resource().to_string()));
m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(msg.body().to_string()));
PushGuiMessage(message);
}
@ -589,8 +591,8 @@ void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::M
CScriptValRooted message;
m_ScriptInterface.Eval("({'type':'message'})", message);
m_ScriptInterface.SetProperty(message.get(), "from", msg.from().username().to_string());
m_ScriptInterface.SetProperty(message.get(), "text", msg.body().to_string());
m_ScriptInterface.SetProperty(message.get(), "from", wstring_from_utf8(msg.from().username().to_string()));
m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(msg.body().to_string()));
PushGuiMessage(message);
}
@ -654,10 +656,10 @@ void XmppClient::CreateSimpleMessage(const std::string& type, const std::string&
{
CScriptValRooted message;
m_ScriptInterface.Eval("({})", message);
m_ScriptInterface.SetProperty(message.get(), "type", type);
m_ScriptInterface.SetProperty(message.get(), "level", level);
m_ScriptInterface.SetProperty(message.get(), "text", text);
m_ScriptInterface.SetProperty(message.get(), "data", data);
m_ScriptInterface.SetProperty(message.get(), "type", wstring_from_utf8(type));
m_ScriptInterface.SetProperty(message.get(), "level", wstring_from_utf8(level));
m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(text));
m_ScriptInterface.SetProperty(message.get(), "data", wstring_from_utf8(data));
PushGuiMessage(message);
}

View File

@ -803,6 +803,24 @@ bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, boo
return true;
}
bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate)
{
uintN attrs = 0;
if (constant)
attrs |= JSPROP_READONLY | JSPROP_PERMANENT;
if (enumerate)
attrs |= JSPROP_ENUMERATE;
if (! JSVAL_IS_OBJECT(obj))
return false;
JSObject* object = JSVAL_TO_OBJECT(obj);
utf16string name16(name, name + wcslen(name));
if (! JS_DefineUCProperty(m->m_cx, object, reinterpret_cast<const jschar*>(name16.c_str()), name16.length(), value, NULL, NULL, attrs))
return false;
return true;
}
bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate)
{
uintN attrs = 0;

View File

@ -189,6 +189,13 @@ public:
template<typename T>
bool SetProperty(jsval obj, const char* name, const T& value, bool constant = false, bool enumerate = true);
/**
* Set the named property on the given object.
* Optionally makes it {ReadOnly, DontDelete, DontEnum}.
*/
template<typename T>
bool SetProperty(jsval obj, const wchar_t* name, const T& value, bool constant = false, bool enumerate = true);
/**
* Set the integer-named property on the given object.
* Optionally makes it {ReadOnly, DontDelete, DontEnum}.
@ -327,6 +334,7 @@ private:
bool Eval_(const wchar_t* code, jsval& ret);
bool SetGlobal_(const char* name, jsval value, bool replace);
bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate);
bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate);
bool SetPropertyInt_(jsval obj, int name, jsval value, bool readonly, bool enumerate);
bool GetProperty_(jsval obj, const char* name, jsval& value);
bool GetPropertyInt_(jsval obj, int name, jsval& value);
@ -464,6 +472,12 @@ bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, b
return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly, enumerate);
}
template<typename T>
bool ScriptInterface::SetProperty(jsval obj, const wchar_t* name, const T& value, bool readonly, bool enumerate)
{
return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly, enumerate);
}
template<typename T>
bool ScriptInterface::SetPropertyInt(jsval obj, int name, const T& value, bool readonly, bool enumerate)
{