summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2023-05-26 13:03:23 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2023-05-26 13:03:26 +0200
commit98dd12a2ccf16d9889b9a97b8ddf6ad64011f9c4 (patch)
treefdfb2f681212ccbb97074baa5f512b9127529046
parent1f7c7fa192907d90a0ef6bbfbfe770a1e2fffa08 (diff)
downloadmanaserv-master.tar.gz
manaserv-master.tar.bz2
manaserv-master.tar.xz
manaserv-master.zip
Fixed login in case an account gets two pending tokens assignedHEADmaster
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.
-rw-r--r--src/account-server/account.h20
-rw-r--r--src/account-server/accountclient.cpp25
-rw-r--r--src/account-server/accountclient.h2
-rw-r--r--src/account-server/accounthandler.cpp73
-rw-r--r--src/common/manaserv_protocol.h2
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