summaryrefslogtreecommitdiff
path: root/src
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
parente10c05a77923093aa2be00b9ca6e5976ca9951e6 (diff)
downloadmanaserv-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
Diffstat (limited to 'src')
-rw-r--r--src/account-server/account.h20
-rw-r--r--src/account-server/accounthandler.cpp47
-rw-r--r--src/common/manaserv_protocol.h2
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