diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/account-server/account.h | 20 | ||||
-rw-r--r-- | src/account-server/accounthandler.cpp | 47 | ||||
-rw-r--r-- | src/common/manaserv_protocol.h | 4 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 39 |
4 files changed, 103 insertions, 7 deletions
diff --git a/src/account-server/account.h b/src/account-server/account.h index 189e3b59..98794fbf 100644 --- a/src/account-server/account.h +++ b/src/account-server/account.h @@ -78,6 +78,24 @@ class Account const std::string &getPassword() const { return mPassword; } + /** + * Set the random salt. This salt is sent to the client, so the client + * can hash its password with this random salt. + * This will help to protect against replay attacks. + * + * @param the new random salt to be sent out next login + */ + void setRandomSalt(const std::string &salt) + { mRandomSalt = salt; } + + + /** + * Get the user random salt. + * + * @return the random salt used for next login. + */ + const std::string &getRandomSalt() const + { return mRandomSalt; } /** * Set the user email address. The email address is expected to be @@ -204,6 +222,8 @@ class Account std::string mName; /**< User name */ std::string mPassword; /**< User password (hashed with salt) */ + std::string mRandomSalt; /**< A random sequence sent to client to + protect against replay attacks.*/ std::string mEmail; /**< User email address (hashed) */ Characters mCharacters; /**< Character data */ int mID; /**< Unique id */ diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index 7bd2a0a7..f5779083 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -89,6 +89,7 @@ protected: void computerDisconnected(NetComputer *comp); private: + void handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg); void handleLoginMessage(AccountClient &client, MessageIn &msg); void handleLogoutMessage(AccountClient &client); void handleReconnectMessage(AccountClient &client, MessageIn &msg); @@ -103,6 +104,10 @@ private: void addServerInfo(MessageOut *msg); + /** List of all accounts which requested a random seed, but are not logged + * yet. This list will be regularly remove (after timeout) old accounts + */ + std::list<Account*> mPendingAccounts; /** List of attributes that the client can send at account creation. */ std::vector<int> mModifiableAttributes; @@ -292,6 +297,32 @@ void AccountHandler::sendCharacterData(AccountClient &client, client.send(charInfo); } +std::string getRandomString(int length) +{ + char s[length]; + // No need to care about zeros. They can be handled. + // But care for endianness + for (int i = 0; i < length; ++i) + s[i] = (char)rand(); + + return std::string(s, length); +} + +void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg) +{ + std::string salt = getRandomString(4); + std::string username = msg.readString(); + + if (Account *acc = storage->getAccount(username)) + { + acc->setRandomSalt(salt); + mPendingAccounts.push_back(acc); + } + MessageOut reply(APMSG_LOGIN_RNDTRGR_RESPONSE); + reply.writeString(salt); + client.send(reply); +} + void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg) { MessageOut reply(APMSG_LOGIN_RESPONSE); @@ -349,9 +380,14 @@ void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg) } // Check if the account exists - Account *acc = storage->getAccount(username); - - if (!acc || acc->getPassword() != sha256(password)) + Account *acc = 0; + std::list<Account*>::iterator ita; + for ( ita = mPendingAccounts.begin() ; ita != mPendingAccounts.end(); ita++ ) + if ((*ita)->getName() == username) + acc = *ita; + mPendingAccounts.remove(acc); + + if (!acc || sha256(acc->getPassword() + acc->getRandomSalt()) != password) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); client.send(reply); @@ -978,6 +1014,11 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message) switch (message.getId()) { + case PAMSG_LOGIN_RNDTRGR: + LOG_DEBUG("Received msg ... PAMSG_LOGIN_RANDTRIGGER"); + handleLoginRandTriggerMessage(client, message); + break; + case PAMSG_LOGIN: LOG_DEBUG("Received msg ... PAMSG_LOGIN"); handleLoginMessage(client, message); diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h index 6c51aef9..710d2f45 100644 --- a/src/common/manaserv_protocol.h +++ b/src/common/manaserv_protocol.h @@ -57,6 +57,8 @@ enum { APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots
PAMSG_LOGOUT = 0x0013, // -
APMSG_LOGOUT_RESPONSE = 0x0014, // B error
+ PAMSG_LOGIN_RNDTRGR = 0x0015, // S username
+ APMSG_LOGIN_RNDTRGR_RESPONSE = 0x0016, // S random seed
PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, B slot, {W stats}*
APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error
PAMSG_CHAR_DELETE = 0x0022, // B slot
@@ -89,7 +91,7 @@ enum { GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y
GPMSG_PLAYER_SERVER_CHANGE = 0x0101, // B*32 token, S game address, W game port
PGMSG_PICKUP = 0x0110, // W*2 position
- PGMSG_DROP = 0x0111, // W slot, W amount
+ PGMSG_DROP = 0x0111, // B slot, B amount
PGMSG_EQUIP = 0x0112, // W inventory slot
PGMSG_UNEQUIP = 0x0113, // W equipment slot
PGMSG_MOVE_ITEM = 0x0114, // W slot1, W slot2, W amount
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index e572791e..2ea2187c 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -448,7 +448,19 @@ static int chr_inv_count(lua_State *s) int id, nb = 0; for (int i = 2; i <= nb_items + 1; ++i) { - id = luaL_checkint(s, i); + ItemClass *it; + if (lua_isnumber(s, i)) + it = itemManager->getItem(lua_tointeger(s, i)); + else + it = itemManager->getItemByName(lua_tostring(s, i)); + + if (!it) + { + raiseScriptError(s, "chr_inv_count called with invalid " + "item id or name."); + return 0; + } + id = it->getDatabaseID(); if (id == 0) { LOG_WARN("chr_inv_count called with id 0! " @@ -537,7 +549,25 @@ static int npc_trade(lua_State *s) for (int i = 0; i < 3; ++i) { lua_rawgeti(s, -1, i + 1); - if (!lua_isnumber(s, -1)) + if (i == 0) // item id or name + { + ItemClass *it; + if (lua_isnumber(s, -1)) + it = itemManager->getItem(lua_tointeger(s, -1)); + else + it = itemManager->getItemByName(lua_tostring(s, -1)); + + if (!it) + { + raiseWarning(s, "npc_trade called with incorrect " + "item id or name."); + t->cancel(); + lua_pushinteger(s, 2); + return 1; + } + v[0] = it->getDatabaseID(); + } + else if (!lua_isnumber(s, -1)) { raiseWarning(s, "npc_trade called with incorrect parameters " "in item table."); @@ -545,7 +575,10 @@ static int npc_trade(lua_State *s) lua_pushinteger(s, 2); return 1; } - v[i] = lua_tointeger(s, -1); + else + { + v[i] = lua_tointeger(s, -1); + } lua_pop(s, 1); } if (t->registerItem(v[0], v[1], v[2])) |