summaryrefslogtreecommitdiffstats
path: root/src/account-server
diff options
context:
space:
mode:
authorStefan Beller <stefanbeller@googlemail.com>2011-08-06 03:24:45 +0200
committerStefan Beller <stefanbeller@googlemail.com>2011-08-10 21:37:24 +0200
commit0820d6632b0ce5887c49d16929ac7903aa185fe4 (patch)
tree9e1d0b608b115371b6911a1a5b239a61c1ef7f50 /src/account-server
parente10c05a77923093aa2be00b9ca6e5976ca9951e6 (diff)
downloadmanaserv-0820d6632b0ce5887c49d16929ac7903aa185fe4.tar.gz
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
Diffstat (limited to 'src/account-server')
-rw-r--r--src/account-server/account.h20
-rw-r--r--src/account-server/accounthandler.cpp47
2 files changed, 64 insertions, 3 deletions
diff --git a/src/account-server/account.h b/src/account-server/account.h
index 189e3b5..98794fb 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 7bd2a0a..f577908 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);