diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2023-05-26 13:03:23 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2023-05-26 13:03:26 +0200 |
commit | 98dd12a2ccf16d9889b9a97b8ddf6ad64011f9c4 (patch) | |
tree | fdfb2f681212ccbb97074baa5f512b9127529046 /src | |
parent | 1f7c7fa192907d90a0ef6bbfbfe770a1e2fffa08 (diff) | |
download | manaserv-master.tar.gz manaserv-master.tar.bz2 manaserv-master.tar.xz manaserv-master.zip |
Not entirely sure if this is what was happening, but if a
PAMSG_LOGIN_RNDTRGR was handled, a new pending account was always
created and appended to mPendingAccounts. However, when handling the
follow-up PAMSG_LOGIN, only the first pending account with matching
username was checked, which could result in a failed login due to
mismatching token.
Resolved this issue by unifying the client-specific random token with
the Stellar token stored on the AccountClient. This means the username
value in PAMSG_LOGIN_RNDTRGR could be removed.
Eventually it would also be nice to simplify this further such that the
token is automatically sent to the client after connecting rather than
being something that needs to be requested.
Diffstat (limited to 'src')
-rw-r--r-- | src/account-server/account.h | 20 | ||||
-rw-r--r-- | src/account-server/accountclient.cpp | 25 | ||||
-rw-r--r-- | src/account-server/accountclient.h | 2 | ||||
-rw-r--r-- | src/account-server/accounthandler.cpp | 73 | ||||
-rw-r--r-- | src/common/manaserv_protocol.h | 2 |
5 files changed, 33 insertions, 89 deletions
diff --git a/src/account-server/account.h b/src/account-server/account.h index 4f4b807e..8a63e9f2 100644 --- a/src/account-server/account.h +++ b/src/account-server/account.h @@ -81,24 +81,6 @@ 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 @@ -230,8 +212,6 @@ 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/accountclient.cpp b/src/account-server/accountclient.cpp index df1b034c..822cbed5 100644 --- a/src/account-server/accountclient.cpp +++ b/src/account-server/accountclient.cpp @@ -20,9 +20,32 @@ #include "account-server/accountclient.h" +/** + * Generates a random string containing lowercase and uppercase characters as + * well as numbers. + */ +static std::string getRandomString(int length) +{ + std::string s; + s.resize(length); + for (int i = 0; i < length; ++i) + { + int r = rand() % 62; + if (r < 10) + s[i] = '0' + r; + else if (r < 36) + s[i] = 'a' + r - 10; + else + s[i] = 'A' + r - 36; + } + + return s; +} + AccountClient::AccountClient(ENetPeer *peer): NetComputer(peer), status(CLIENT_LOGIN), - version(0) + version(0), + token(getRandomString(8)) { } diff --git a/src/account-server/accountclient.h b/src/account-server/accountclient.h index 5ccb0f1d..6c64e2f6 100644 --- a/src/account-server/accountclient.h +++ b/src/account-server/accountclient.h @@ -51,7 +51,7 @@ class AccountClient : public NetComputer AccountClientStatus status; int version; - std::string stellarToken; + std::string token; private: std::unique_ptr<Account> mAccount; diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index e8161fcd..54fa2dbd 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -107,11 +107,6 @@ private: const std::string &email); 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<std::unique_ptr<Account>> mPendingAccounts; - /** List of attributes that the client can send at account creation. */ std::vector<int> mModifiableAttributes; @@ -322,52 +317,10 @@ static void sendFullCharacterData(AccountClient *client, client->send(msg); } -static std::string getRandomData(int length) +void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, MessageIn &) { - std::string s; - s.resize(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 s; -} - -/** - * Generates a random string containing lowercase and uppercase characters as - * well as numbers. - */ -static std::string getRandomString(int length) -{ - std::string s; - s.resize(length); - for (int i = 0; i < length; ++i) - { - int r = rand() % 62; - if (r < 10) - s[i] = '0' + r; - else if (r < 36) - s[i] = 'a' + r - 10; - else - s[i] = 'A' + r - 36; - } - - return s; -} - -void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg) -{ - std::string salt = getRandomData(4); - std::string username = msg.readString(); - - if (auto acc = storage->getAccount(username)) - { - acc->setRandomSalt(salt); - mPendingAccounts.push_back(std::move(acc)); - } MessageOut reply(APMSG_LOGIN_RNDTRGR_RESPONSE); - reply.writeString(salt); + reply.writeString(client.token); client.send(reply); } @@ -391,11 +344,9 @@ void AccountHandler::handleStellarLoginMessage(AccountClient &client, MessageIn return; } - client.stellarToken = getRandomString(8); - reply.writeInt8(ERRMSG_OK); - reply.writeString(client.stellarToken); - reply.writeString(mStellarLoginUrl + "?token=" + client.stellarToken); + reply.writeString(client.token); + reply.writeString(mStellarLoginUrl + "?token=" + client.token); client.send(reply); } @@ -457,19 +408,9 @@ void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg) } // Check if the account exists - auto accIt = std::find_if(mPendingAccounts.begin(), - mPendingAccounts.end(), - [&] (const std::unique_ptr<Account> &acc) { - return acc->getName() == username; - }); - - std::unique_ptr<Account> acc; - if (accIt != mPendingAccounts.end()) { - acc = std::move(*accIt); - mPendingAccounts.erase(accIt); - } + auto acc = storage->getAccount(username); - if (!acc || sha256(acc->getPassword() + acc->getRandomSalt()) != password) + if (!acc || sha256(acc->getPassword() + client.token) != password) { reply.writeInt8(ERRMSG_INVALID_ARGUMENT); client.send(reply); @@ -1087,7 +1028,7 @@ void AccountHandler::handleStellarLogin(const std::string &token, const std::str [token](NetComputer *client) -> bool { auto c = static_cast<AccountClient *>(client); - return c->stellarToken == token; + return c->token == token; }); if (it == clients.end()) diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h index 9bb50337..67e812ac 100644 --- a/src/common/manaserv_protocol.h +++ b/src/common/manaserv_protocol.h @@ -77,7 +77,7 @@ enum { APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots, {content of APMSG_CHAR_CREATE_RESPONSE (without error code)}* PAMSG_LOGOUT = 0x0013, // - APMSG_LOGOUT_RESPONSE = 0x0014, // B error - PAMSG_LOGIN_RNDTRGR = 0x0015, // S username + PAMSG_LOGIN_RNDTRGR = 0x0015, // - APMSG_LOGIN_RNDTRGR_RESPONSE = 0x0016, // S random seed PAMSG_STELLAR_LOGIN = 0x0017, // D version APMSG_STELLAR_LOGIN_RESPONSE = 0x0018, // B error, S token, S url |