diff options
Diffstat (limited to 'src/account-server/accounthandler.cpp')
-rw-r--r-- | src/account-server/accounthandler.cpp | 186 |
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(®date); - 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(®date); + 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); |