Advertisement
Guest User

protocollogin.cpp

a guest
Sep 29th, 2017
664
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.07 KB | None | 0 0
  1. /**
  2.  * The Forgotten Server - a free and open-source MMORPG server emulator
  3.  * Copyright (C) 2016  Mark Samman <mark.samman@gmail.com>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  */
  19.  
  20. #include "otpch.h"
  21.  
  22. #include "protocollogin.h"
  23.  
  24. #include "outputmessage.h"
  25. #include "tasks.h"
  26.  
  27. #include "configmanager.h"
  28. #include "iologindata.h"
  29. #include "ban.h"
  30. #include "game.h"
  31.  
  32. extern ConfigManager g_config;
  33. extern Game g_game;
  34.  
  35. void ProtocolLogin::disconnectClient(const std::string& message, uint16_t version)
  36. {
  37.     auto output = OutputMessagePool::getOutputMessage();
  38.  
  39.     output->addByte(version >= 1076 ? 0x0B : 0x0A);
  40.     output->addString(message);
  41.     send(output);
  42.  
  43.     disconnect();
  44. }
  45.  
  46. void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, const std::string& token, uint16_t version)
  47. {
  48.     Account account;
  49.     if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
  50.         disconnectClient("Account name or password is not correct.", version);
  51.         return;
  52.     }
  53.  
  54.     auto output = OutputMessagePool::getOutputMessage();
  55.     if (!account.key.empty()) {
  56.         int32_t ticks = static_cast<int32_t>(time(nullptr) / AUTHENTICATOR_PERIOD);
  57.         if (token.empty() || !(token == generateToken(account.key, ticks) || token == generateToken(account.key, ticks - 1) || token == generateToken(account.key, ticks + 1))) {
  58.             output->addByte(0x0D);
  59.             output->addByte(0);
  60.             send(output);
  61.             disconnect();
  62.             return;
  63.         }
  64.         output->addByte(0x0C);
  65.         output->addByte(0);
  66.     }
  67.  
  68.     //Update premium days
  69.     Game::updatePremium(account);
  70.  
  71.     const std::string& motd = g_config.getString(ConfigManager::MOTD);
  72.     if (!motd.empty()) {
  73.         //Add MOTD
  74.         output->addByte(0x14);
  75.  
  76.         std::ostringstream ss;
  77.         ss << g_game.getMotdNum() << "\n" << motd;
  78.         output->addString(ss.str());
  79.     }
  80.  
  81.     //Add session key
  82.     output->addByte(0x28);
  83.     output->addString(accountName + "\n" + password);
  84.  
  85.     //Add char list
  86.     output->addByte(0x64);
  87.  
  88.     output->addByte(1); // number of worlds
  89.  
  90.     output->addByte(0); // world id
  91.     output->addString(g_config.getString(ConfigManager::SERVER_NAME));
  92.     output->addString(g_config.getString(ConfigManager::IP));
  93.     output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
  94.     output->addByte(0);
  95.  
  96.     uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
  97.     output->addByte(size);
  98.     for (uint8_t i = 0; i < size; i++) {
  99.         output->addByte(0);
  100.         output->addString(account.characters[i]);
  101.     }
  102.  
  103.     //Add premium days
  104.     output->addByte(0);
  105.     if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  106.         output->addByte(1);
  107.         output->add<uint32_t>(0);
  108.     } else {
  109.         output->addByte(0);
  110.         output->add<uint32_t>(time(nullptr) + (account.premiumDays * 86400));
  111.     }
  112.  
  113.     send(output);
  114.  
  115.     disconnect();
  116. }
  117.  
  118. void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
  119. {
  120.     if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
  121.         disconnect();
  122.         return;
  123.     }
  124.  
  125.     msg.skipBytes(2); // client OS
  126.  
  127.     uint16_t version = msg.get<uint16_t>();
  128.     if (version >= 971) {
  129.         msg.skipBytes(17);
  130.     } else {
  131.         msg.skipBytes(12);
  132.     }
  133.     /*
  134.      * Skipped bytes:
  135.      * 4 bytes: protocolVersion
  136.      * 12 bytes: dat, spr, pic signatures (4 bytes each)
  137.      * 1 byte: 0
  138.      */
  139.  
  140.     if (version <= 760) {
  141.         std::ostringstream ss;
  142.         ss << "Only clients with protocol " << CLIENT_VERSION_STR << " allowed!";
  143.         disconnectClient(ss.str(), version);
  144.         return;
  145.     }
  146.  
  147.     if (!Protocol::RSA_decrypt(msg)) {
  148.         disconnect();
  149.         return;
  150.     }
  151.  
  152.     uint32_t key[4];
  153.     key[0] = msg.get<uint32_t>();
  154.     key[1] = msg.get<uint32_t>();
  155.     key[2] = msg.get<uint32_t>();
  156.     key[3] = msg.get<uint32_t>();
  157.     enableXTEAEncryption();
  158.     setXTEAKey(key);
  159.  
  160.     if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
  161.         std::ostringstream ss;
  162.         ss << "Only clients with protocol " << CLIENT_VERSION_STR << " allowed!";
  163.         disconnectClient(ss.str(), version);
  164.         return;
  165.     }
  166.  
  167.     if (g_game.getGameState() == GAME_STATE_STARTUP) {
  168.         disconnectClient("Gameworld is starting up. Please wait.", version);
  169.         return;
  170.     }
  171.  
  172.     if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
  173.         disconnectClient("Gameworld is under maintenance.\nPlease re-connect in a while.", version);
  174.         return;
  175.     }
  176.  
  177.     BanInfo banInfo;
  178.     auto connection = getConnection();
  179.     if (!connection) {
  180.         return;
  181.     }
  182.  
  183.     if (IOBan::isIpBanned(connection->getIP(), banInfo)) {
  184.         if (banInfo.reason.empty()) {
  185.             banInfo.reason = "(none)";
  186.         }
  187.  
  188.         std::ostringstream ss;
  189.         ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
  190.         disconnectClient(ss.str(), version);
  191.         return;
  192.     }
  193.  
  194.     std::string accountName = msg.getString();
  195.     if (accountName.empty()) {
  196.         disconnectClient("Invalid account name.", version);
  197.         return;
  198.     }
  199.  
  200.     std::string password = msg.getString();
  201.     if (password.empty()) {
  202.         disconnectClient("Invalid password.", version);
  203.         return;
  204.     }
  205.  
  206.     // read authenticator token and stay logged in flag from last 128 bytes
  207.     msg.skipBytes((msg.getLength() - 128) - msg.getBufferPosition());
  208.     if (!Protocol::RSA_decrypt(msg)) {
  209.         disconnectClient("Invalid authentification token.", version);
  210.         return;
  211.     }
  212.  
  213.     std::string authToken = msg.getString();
  214.  
  215.     auto thisPtr = std::static_pointer_cast<ProtocolLogin>(shared_from_this());
  216.     g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountName, password, authToken, version)));
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement