diff options
author | Stefan Beller <stefanbeller@googlemail.com> | 2011-08-06 03:24:45 +0200 |
---|---|---|
committer | Stefan Beller <stefanbeller@googlemail.com> | 2011-08-10 21:37:24 +0200 |
commit | 0820d6632b0ce5887c49d16929ac7903aa185fe4 (patch) | |
tree | 9e1d0b608b115371b6911a1a5b239a61c1ef7f50 | |
parent | e10c05a77923093aa2be00b9ca6e5976ca9951e6 (diff) | |
download | manaserv-0820d6632b0ce5887c49d16929ac7903aa185fe4.tar.gz manaserv-0820d6632b0ce5887c49d16929ac7903aa185fe4.tar.bz2 manaserv-0820d6632b0ce5887c49d16929ac7903aa185fe4.tar.xz manaserv-0820d6632b0ce5887c49d16929ac7903aa185fe4.zip |
login with random hash
The account server sends out a random number, which is
additionally used for hashing the password.
Reviewed by Bertram
-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 | 2 |
3 files changed, 66 insertions, 3 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 df7efd18..dc7e47b4 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 |