summaryrefslogtreecommitdiff
path: root/src/account-server/accounthandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/account-server/accounthandler.cpp')
-rw-r--r--src/account-server/accounthandler.cpp186
1 files changed, 158 insertions, 28 deletions
diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp
index 2275e015..b13b4580 100644
--- a/src/account-server/accounthandler.cpp
+++ b/src/account-server/accounthandler.cpp
@@ -40,7 +40,6 @@
#include "utils/tokencollector.h"
#include "utils/tokendispenser.h"
#include "utils/sha256.h"
-#include "utils/string.h"
#include "utils/xml.h"
using namespace ManaServ;
@@ -68,6 +67,10 @@ public:
void deletePendingConnect(int) {}
/**
+ */
+ void handleStellarLogin(const std::string &token, const std::string &pubKey);
+
+ /**
* Token collector for connecting a client coming from a game server
* without having to provide username and password a second time.
*/
@@ -85,6 +88,7 @@ protected:
private:
void handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg);
+ void handleStellarLoginMessage(AccountClient &client, MessageIn &msg);
void handleLoginMessage(AccountClient &client, MessageIn &msg);
void handleLogoutMessage(AccountClient &client);
void handleReconnectMessage(AccountClient &client, MessageIn &msg);
@@ -97,7 +101,10 @@ private:
void handleCharacterSelectMessage(AccountClient &client, MessageIn &msg);
void handleCharacterDeleteMessage(AccountClient &client, MessageIn &msg);
- void addServerInfo(MessageOut *msg);
+ std::unique_ptr<Account> createAccount(const std::string &username,
+ const std::string &password,
+ 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
@@ -239,9 +246,9 @@ void AccountClientHandler::deinitialize()
accountHandler = nullptr;
}
-void AccountClientHandler::process()
+ConnectionHandler *AccountClientHandler::getConnectionHandler()
{
- accountHandler->process(50);
+ return accountHandler;
}
void AccountClientHandler::prepareReconnect(const std::string &token, int id)
@@ -249,6 +256,12 @@ void AccountClientHandler::prepareReconnect(const std::string &token, int id)
accountHandler->mTokenCollector.addPendingConnect(token, id);
}
+void AccountClientHandler::handleStellarLogin(const std::string &token, const std::string &pubKey)
+{
+ accountHandler->handleStellarLogin(token, pubKey);
+}
+
+
NetComputer *AccountHandler::computerConnected(ENetPeer *peer)
{
return new AccountClient(peer);
@@ -306,7 +319,7 @@ static void sendFullCharacterData(AccountClient *client,
client->send(msg);
}
-static std::string getRandomString(int length)
+static std::string getRandomData(int length)
{
std::string s;
s.resize(length);
@@ -318,9 +331,31 @@ static std::string getRandomString(int length)
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 = getRandomString(4);
+ std::string salt = getRandomData(4);
std::string username = msg.readString();
if (auto acc = storage->getAccount(username))
@@ -333,6 +368,34 @@ void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, Messag
client.send(reply);
}
+void AccountHandler::handleStellarLoginMessage(AccountClient &client, MessageIn &msg)
+{
+ client.version = msg.readInt32();
+
+ MessageOut reply(APMSG_STELLAR_LOGIN_RESPONSE);
+
+ if (client.status != CLIENT_LOGIN)
+ {
+ reply.writeInt8(ERRMSG_FAILURE);
+ client.send(reply);
+ return;
+ }
+
+ if (client.version < MIN_PROTOCOL_VERSION)
+ {
+ reply.writeInt8(LOGIN_INVALID_VERSION);
+ client.send(reply);
+ return;
+ }
+
+ client.stellarToken = getRandomString(8);
+
+ reply.writeInt8(ERRMSG_OK);
+ reply.writeString(client.stellarToken);
+
+ client.send(reply);
+}
+
void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg)
{
MessageOut reply(APMSG_LOGIN_RESPONSE);
@@ -425,7 +488,7 @@ void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg)
storage->updateLastLogin(*acc);
reply.writeInt8(ERRMSG_OK);
- addServerInfo(&reply);
+ addServerInfo(reply);
const Characters &chars = acc->getCharacters();
@@ -534,24 +597,14 @@ void AccountHandler::handleRegisterMessage(AccountClient &client,
}
else
{
- std::unique_ptr<Account> acc { new Account };
- acc->setName(username);
- acc->setPassword(sha256(password));
- // We hash email server-side for additional privacy
- // we ask for it again when we need it and verify it
- // through comparing it with the hash.
- acc->setEmail(sha256(email));
- acc->setLevel(AL_PLAYER);
-
- // Set the date and time of the account registration, and the last login
- time_t regdate;
- time(&regdate);
- acc->setRegistrationDate(regdate);
- acc->setLastLogin(regdate);
-
- storage->addAccount(*acc);
+ // We hash email server-side for additional privacy we ask for it again
+ // when we need it and verify it through comparing it with the hash.
+ std::unique_ptr<Account> acc = createAccount(username,
+ sha256(password),
+ sha256(email));
+
reply.writeInt8(ERRMSG_OK);
- addServerInfo(&reply);
+ addServerInfo(reply);
// Associate account with connection
client.setAccount(std::move(acc));
@@ -960,6 +1013,26 @@ void AccountHandler::handleCharacterDeleteMessage(AccountClient &client,
client.send(reply);
}
+std::unique_ptr<Account> AccountHandler::createAccount(const std::string &username,
+ const std::string &password,
+ const std::string &email)
+{
+ std::unique_ptr<Account> acc { new Account };
+ acc->setName(username);
+ acc->setPassword(password);
+ acc->setEmail(email);
+ acc->setLevel(AL_PLAYER);
+
+ // Set the date and time of the account registration, and the last login
+ time_t regdate;
+ time(&regdate);
+ acc->setRegistrationDate(regdate);
+ acc->setLastLogin(regdate);
+
+ storage->addAccount(*acc);
+ return acc;
+}
+
/**
* Adds server specific info to the current message
*
@@ -968,11 +1041,11 @@ void AccountHandler::handleCharacterDeleteMessage(AccountClient &client,
* (String) Client Data URL (or "")
* (Byte) Number of maximum character slots (empty or not)
*/
-void AccountHandler::addServerInfo(MessageOut *msg)
+void AccountHandler::addServerInfo(MessageOut &msg)
{
- msg->writeString(mUpdateHost);
- msg->writeString(mDataUrl);
- msg->writeInt8(mMaxCharacters);
+ msg.writeString(mUpdateHost);
+ msg.writeString(mDataUrl);
+ msg.writeInt8(mMaxCharacters);
}
void AccountHandler::tokenMatched(AccountClient *client, int accountID)
@@ -1001,6 +1074,58 @@ void AccountHandler::deletePendingClient(AccountClient *client)
// The client will be deleted when the disconnect event is processed
}
+void AccountHandler::handleStellarLogin(const std::string &token, const std::string &pubKey)
+{
+ auto it = std::find_if(clients.begin(), clients.end(),
+ [token](NetComputer *client) -> bool
+ {
+ auto c = static_cast<AccountClient *>(client);
+ return c->stellarToken == token;
+ });
+
+ if (it == clients.end())
+ {
+ LOG_DEBUG("Stellar login: No client with token " << token);
+ return;
+ }
+
+ auto client = static_cast<AccountClient*>(*it);
+ auto acc = storage->getAccount(pubKey);
+ if (acc)
+ {
+ // Set lastLogin date of the account.
+ time_t login;
+ time(&login);
+ acc->setLastLogin(login);
+ storage->updateLastLogin(*acc);
+ }
+ else if (!mRegistrationAllowed)
+ {
+ MessageOut reply(APMSG_REGISTER_RESPONSE);
+ reply.writeInt8(ERRMSG_FAILURE);
+ client->send(reply);
+ return;
+ }
+ else
+ {
+ // On-demand account creation for public keys
+ acc = createAccount(pubKey, std::string(), std::string());
+ }
+
+ MessageOut reply(APMSG_LOGIN_RESPONSE);
+ reply.writeInt8(ERRMSG_OK);
+ addServerInfo(reply);
+
+ for (auto &charIt : acc->getCharacters())
+ sendCharacterData(reply, charIt.second);
+
+ client->send(reply);
+
+ // Associate account with connection.
+ client->setAccount(std::move(acc));
+ client->status = CLIENT_CONNECTED;
+}
+
void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
{
AccountClient &client = *static_cast< AccountClient * >(comp);
@@ -1017,6 +1142,11 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
handleLoginMessage(client, message);
break;
+ case PAMSG_STELLAR_LOGIN:
+ LOG_DEBUG("Received msg ... PAMSG_STELLAR_LOGIN");
+ handleStellarLoginMessage(client, message);
+ break;
+
case PAMSG_LOGOUT:
LOG_DEBUG("Received msg ... PAMSG_LOGOUT");
handleLogoutMessage(client);