void ProtocolAdmin::adminCommandKickPlayer(const std::string& name) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output) { TRACK_MESSAGE(output); Player* player = g_game.getPlayerByName(name); if(player) { player->kickPlayer(false); addLogLine(this, LOGTYPE_EVENT, 1, "kicked player " + name); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not kick player (not online): " + name); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("player is not online"); } OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandSendMail(const std::string& xmlData) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); std::string name; uint32_t depotId; Item* mailItem = createMail(xmlData, name, depotId); if(mailItem){ if(Mailbox::sendItemTo(name, depotId, mailItem)){ output->AddByte(AP_MSG_COMMAND_OK); } else{ output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("Could not mail item"); } } else{ output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("Could not mail item"); } OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandSetOwner(const std::string& param) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { boost::char_separator<char> sep(", "); tokenizer cmdtokens(param, sep); tokenizer::iterator cmdit = cmdtokens.begin(); std::string _house, name; _house = parseParams(cmdit, cmdtokens.end()); name = parseParams(cmdit, cmdtokens.end()); trimString(_house); trimString(name); if (House* house = Houses::getInstance().getHouse(atoi(_house.c_str()))) { uint32_t _guid; if (IOLoginData::getInstance()->getGuidByName(_guid, name)) { house->setHouseOwner(_guid); addLogLine(this, LOGTYPE_EVENT, 1, "set " + name + " as new owner of house with id " + _house); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not find player with name: " + name); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("such player does not exists"); } } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not find house with id: " + _house); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("such house does not exists"); } OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandPayHouses() { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { if (Houses::getInstance().payHouses()) { addLogLine(this, LOGTYPE_EVENT, 1, "pay houses ok"); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "pay houses fail"); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString(" "); } OutputMessagePool::getInstance()->send(output); } }
void ProtocolLogin::disconnectClient(uint8_t error, const char* message) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->AddByte(error); output->AddString(message); OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); }
void ProtocolLogin::disconnectClient(const std::string& message) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->AddByte(0x0A); output->AddString(message); OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); }
void ProtocolAdmin::adminCommandSaveServer(bool shallow) { g_game.saveServer(false, shallow); addLogLine(this, LOGTYPE_EVENT, 1, "save server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandPayHouses() { Houses::getInstance().payHouses(); addLogLine(this, LOGTYPE_EVENT, 1, "pay houses ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandShutdownServer() { g_game.setGameState(GAME_STATE_SHUTDOWN); addLogLine(this, LOGTYPE_EVENT, 1, "start server shutdown"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandOpenServer() { g_game.setGameState(GAME_STATE_NORMAL); addLogLine(this, LOGTYPE_EVENT, 1, "open server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandRelationalSaveServer() { std::string old_type = g_config.getString(ConfigManager::MAP_STORAGE_TYPE); g_config.setString(ConfigManager::MAP_STORAGE_TYPE, "relational"); g_game.saveServer(false); g_config.setString(ConfigManager::MAP_STORAGE_TYPE, old_type); addLogLine(this, LOGTYPE_EVENT, 1, "relational save server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password) { Account account; if (!IOLoginData::loginserverAuthentication(accountName, password, account)) { disconnectClient("Account name or password is not correct."); return; } OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { //Update premium days Game::updatePremium(account); //Add MOTD output->AddByte(0x14); std::ostringstream ss; ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD); output->AddString(ss.str()); //Add char list output->AddByte(0x64); output->AddByte(1); // number of worlds output->AddByte(0); // world id output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); output->AddString(g_config.getString(ConfigManager::IP)); output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT)); output->AddByte(0); output->AddByte(static_cast<uint8_t>(account.charList.size())); for (const std::string& characterName : account.charList) { output->AddByte(0); output->AddString(characterName); } //Add premium days if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { output->add<uint16_t>(0xFFFF); //client displays free premium } else { output->add<uint16_t>(account.premiumDays); } OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); }
void ProtocolAdmin::onRecvFirstMessage(NetworkMessage& msg) { //is the remote admin protocol enabled? if(!g_adminConfig->isEnabled()) { getConnection()->closeConnection(); return; } m_state = NO_CONNECTED; //is allowed this ip? if(!g_adminConfig->allowIP(getIP())) { addLogLine(this, LOGTYPE_EVENT, 1, "ip not allowed"); getConnection()->closeConnection(); return; } //max connections limit if(!g_adminConfig->addConnection()) { addLogLine(this, LOGTYPE_EVENT, 1, "cannot add new connection"); getConnection()->closeConnection(); return; } addLogLine(this, LOGTYPE_EVENT, 1, "sending HELLO"); //send hello OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output) { TRACK_MESSAGE(output); output->AddByte(AP_MSG_HELLO); output->AddU32(1); //version output->AddString("OTADMIN"); output->AddU16(g_adminConfig->getProtocolPolicy()); //security policy output->AddU32(g_adminConfig->getProtocolOptions()); //protocol options(encryption, ...) OutputMessagePool::getInstance()->send(output); } m_lastCommand = time(NULL); m_state = ENCRYPTION_NO_SET; }
void ProtocolAdmin::adminCommandCloseServer() { g_game.setGameState(GAME_STATE_CLOSED); addLogLine(this, LOGTYPE_EVENT, 1, "close server ok"); AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); while(it != Player::listPlayer.list.end()){ if(!(*it).second->hasFlag(PlayerFlag_CanAlwaysLogin)){ (*it).second->kickPlayer(); it = Player::listPlayer.list.begin(); } else{ ++it; } } OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg) { if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->closeConnection(); return false; } uint32_t clientip = getConnection()->getIP(); /*uint16_t clientos = */ msg.get<uint16_t>(); uint16_t version = msg.get<uint16_t>(); if (version >= 971) { msg.SkipBytes(17); } else { msg.SkipBytes(12); } /* * Skipped bytes: * 4 bytes: protocolVersion (only 971+) * 12 bytes: dat, spr, pic signatures (4 bytes each) * 1 byte: 0 (only 971+) */ if (version <= 760) { disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return false; } if (!RSA_decrypt(msg)) { getConnection()->closeConnection(); return false; } uint32_t key[4]; key[0] = msg.get<uint32_t>(); key[1] = msg.get<uint32_t>(); key[2] = msg.get<uint32_t>(); key[3] = msg.get<uint32_t>(); enableXTEAEncryption(); setXTEAKey(key); std::string accountName = msg.GetString(); std::string password = msg.GetString(); if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { if (version >= 1076) disconnectClient(0x0B, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); else disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return false; } if (g_game.getGameState() == GAME_STATE_STARTUP) { disconnectClient(0x0B, "Gameworld is starting up. Please wait."); return false; } if (g_game.getGameState() == GAME_STATE_MAINTAIN) { disconnectClient(0x0B, "Gameworld is under maintenance. Please re-connect in a while."); return false; } BanInfo banInfo; if (IOBan::isIpBanned(clientip, banInfo)) { if (banInfo.reason.empty()) { banInfo.reason = "(none)"; } std::ostringstream ss; ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; disconnectClient(0x0B, ss.str().c_str()); return false; } //IF THE PASSWORD FIELDS AND ACCOUNT FIELD ARE EMPTY THEN THE USER WAN'T TO USE CAST SYSTEM bool cast_login = false; if ((accountName.empty() && password.empty()) || (accountName.empty() && !password.empty())) { cast_login = true; } if (!cast_login && accountName.empty()) { disconnectClient(0x0B, "Invalid account name."); return false; } Account account; if (!cast_login && !IOLoginData::loginserverAuthentication(accountName, password, account)) { disconnectClient(0x0B, "Account name or password is not correct."); return false; } OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { //Update premium days g_game.updatePremium(account); //Add MOTD output->AddByte(0x14); std::ostringstream ss; ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD); output->AddString(ss.str()); //SessionKey if (!cast_login) { output->AddByte(0x28); output->AddString(accountName + "\n" + password); } //Add char list output->AddByte(0x64); if (cast_login) { int cz = 0; std::vector<std::string> names; std::vector<uint32_t> counts; cast_login = false; uint8_t size = 0; g_game.lockPlayers(); for (const auto& it : g_game.getPlayers()) { if (it.second->cast.isCasting && (it.second->cast.password == "" || it.second->cast.password == password)) { names.push_back(it.second->getName()); counts.push_back(it.second->getCastViewerCount()); it.second->getCastViewerCount(); cast_login = true; size++; } } g_game.unlockPlayers(); if (cast_login) { output->AddByte(size); // number of worlds for (auto it = counts.begin(); it != counts.end(); it++) { output->AddByte(cz); // world id std::ostringstream os; os << (*it); output->AddString(os.str() + std::string(" viewers")); output->AddString(g_config.getString(ConfigManager::IP)); output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT)); output->AddByte(0); cz++; } output->AddByte((uint8_t)cz); int world = 0; for (auto it : names) { output->AddByte(world); output->AddString(it); world++; } } } if (!cast_login) { output->AddByte(1); // number of worlds output->AddByte(0); // world id output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); output->AddString(g_config.getString(ConfigManager::IP)); output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT)); output->AddByte(0); output->AddByte((uint8_t)account.charList.size()); for (const std::string& characterName : account.charList) { output->AddByte(0); output->AddString(characterName); } } //Add premium days if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { output->add<uint16_t>(0xFFFF); //client displays free premium } else { output->add<uint16_t>(account.premiumDays); } OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); return true; }
void ProtocolAdmin::parsePacket(NetworkMessage& msg) { if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->closeConnection(); return; } uint8_t recvbyte = msg.GetByte(); OutputMessagePool* outputPool = OutputMessagePool::getInstance(); OutputMessage_ptr output = outputPool->getOutputMessage(this, false); if (!output) { return; } switch (m_state) { case ENCRYPTION_NO_SET: { if (g_adminConfig->requireEncryption()) { if ((time(NULL) - m_startTime) > 30000) { getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "encryption timeout"); return; } if (recvbyte != AP_MSG_ENCRYPTION && recvbyte != AP_MSG_KEY_EXCHANGE) { output->AddByte(AP_MSG_ERROR); output->AddString("encryption needed"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while ENCRYPTION_NO_SET"); return; } break; } else { m_state = NO_LOGGED_IN; } } case NO_LOGGED_IN: { if (g_adminConfig->requireLogin()) { if ((time(NULL) - m_startTime) > 30000) { //login timeout getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "login timeout"); return; } if (m_loginTries > 3) { output->AddByte(AP_MSG_ERROR); output->AddString("too many login tries"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "too many login tries"); return; } if (recvbyte != AP_MSG_LOGIN) { output->AddByte(AP_MSG_ERROR); output->AddString("you are not logged in"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while NO_LOGGED_IN"); return; } break; } else { m_state = LOGGED_IN; } } case LOGGED_IN: { //can execute commands break; } default: { getConnection()->closeConnection(); return; } } m_lastCommand = time(NULL); switch (recvbyte) { case AP_MSG_LOGIN: { if (m_state == NO_LOGGED_IN && g_adminConfig->requireLogin()) { std::string password = msg.GetString(); if (g_adminConfig->passwordMatch(password)) { m_state = LOGGED_IN; output->AddByte(AP_MSG_LOGIN_OK); addLogLine(this, LOGTYPE_EVENT, 1, "login ok"); } else { m_loginTries++; output->AddByte(AP_MSG_LOGIN_FAILED); output->AddString("wrong password"); addLogLine(this, LOGTYPE_WARNING, 1, "login failed.(" + password + ")"); } } else { output->AddByte(AP_MSG_LOGIN_FAILED); output->AddString("can not login"); addLogLine(this, LOGTYPE_WARNING, 1, "wrong state at login"); } break; } case AP_MSG_ENCRYPTION: { if (m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption()) { uint8_t keyType = msg.GetByte(); if (keyType == ENCRYPTION_RSA1024XTEA) { RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA); if (!rsa) { output->AddByte(AP_MSG_ENCRYPTION_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid server key type"); break; } if (RSA_decrypt(rsa, msg)) { m_state = NO_LOGGED_IN; uint32_t k[4]; k[0] = msg.GetU32(); k[1] = msg.GetU32(); k[2] = msg.GetU32(); k[3] = msg.GetU32(); //use for in/out the new key we have enableXTEAEncryption(); setXTEAKey(k); output->AddByte(AP_MSG_ENCRYPTION_OK); addLogLine(this, LOGTYPE_EVENT, 1, "encryption ok"); } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("wrong encrypted packet"); addLogLine(this, LOGTYPE_WARNING, 1, "wrong encrypted packet"); } } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("no valid key type"); addLogLine(this, LOGTYPE_WARNING, 1, "no valid client key type"); } } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("can not set encryption"); addLogLine(this, LOGTYPE_EVENT, 1, "can not set encryption"); } break; } case AP_MSG_KEY_EXCHANGE: { if (m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption()) { uint8_t keyType = msg.GetByte(); if (keyType == ENCRYPTION_RSA1024XTEA) { RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA); if (!rsa) { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid server key type"); break; } output->AddByte(AP_MSG_KEY_EXCHANGE_OK); output->AddByte(ENCRYPTION_RSA1024XTEA); char RSAPublicKey[128]; rsa->getPublicKey(RSAPublicKey); output->AddBytes(RSAPublicKey, 128); } else { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid client key type"); } } else { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); output->AddString("can not get public key"); addLogLine(this, LOGTYPE_WARNING, 1, "can not get public key"); } break; } case AP_MSG_COMMAND: { if (m_state != LOGGED_IN) { addLogLine(this, LOGTYPE_ERROR, 1, "recvbyte == AP_MSG_COMMAND && m_state != LOGGED_IN !!!"); // We should never reach this point break; } uint8_t command = msg.GetByte(); switch (command) { case CMD_BROADCAST: { const std::string message = msg.GetString(); addLogLine(this, LOGTYPE_EVENT, 1, "broadcast: " + message); g_dispatcher.addTask(createTask(boost::bind(&Game::broadcastMessage, &g_game, message, MSG_STATUS_WARNING))); output->AddByte(AP_MSG_COMMAND_OK); break; } case CMD_CLOSE_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandCloseServer, this))); break; } case CMD_PAY_HOUSES: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandPayHouses, this))); break; } case CMD_OPEN_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandOpenServer, this))); break; } case CMD_SHUTDOWN_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandShutdownServer, this))); getConnection()->closeConnection(); return; } case CMD_KICK: { const std::string name = msg.GetString(); g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandKickPlayer, this, name))); break; } case CMD_SETOWNER: { const std::string param = msg.GetString(); g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandSetOwner, this, param))); break; } default: { output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("not known server command"); addLogLine(this, LOGTYPE_WARNING, 1, "not known server command"); break; } } break; } case AP_MSG_PING: { output->AddByte(AP_MSG_PING_OK); break; } default: { output->AddByte(AP_MSG_ERROR); output->AddString("not known command byte"); addLogLine(this, LOGTYPE_WARNING, 1, "not known command byte"); break; } } if (output->getMessageLength() > 0) { outputPool->send(output); } }
bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg) { if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->closeConnection(); return false; } uint32_t clientip = getConnection()->getIP(); /*uint16_t clientos = */ msg.GetU16(); uint16_t version = msg.GetU16(); msg.SkipBytes(12); /* * Skipped bytes: * 12 bytes: dat, spr, pic signatures (4 bytes each) */ #ifdef __PROTOCOL_77__ if (!RSA_decrypt(msg)) { getConnection()->closeConnection(); return false; } uint32_t key[4]; key[0] = msg.GetU32(); key[1] = msg.GetU32(); key[2] = msg.GetU32(); key[3] = msg.GetU32(); enableXTEAEncryption(); setXTEAKey(key); #endif uint32_t accountName = msg.GetU32(); std::string password = msg.GetString(); if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return false; } if (g_game.getGameState() == GAME_STATE_STARTUP) { disconnectClient(0x0A, "Gameworld is starting up. Please wait."); return false; } if (g_game.getGameState() == GAME_STATE_MAINTAIN) { disconnectClient(0x0A, "Gameworld is under maintenance. Please re-connect in a while."); return false; } BanInfo banInfo; if (IOBan::getInstance()->isIpBanned(clientip, banInfo)) { if (banInfo.reason.empty()) { banInfo.reason = "(none)"; } std::ostringstream ss; ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; disconnectClient(0x0A, ss.str().c_str()); return false; } uint32_t serverip = serverIPs[0].first; for (uint32_t i = 0; i < serverIPs.size(); i++) { if ((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)) { serverip = serverIPs[i].first; break; } } if (!accountName) { disconnectClient(0x0A, "Invalid account id."); return false; } Account account; if (!IOLoginData::getInstance()->loginserverAuthentication(accountName, password, account)) { disconnectClient(0x0A, "Account id or password is not correct."); return false; } OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { //Update premium days g_game.updatePremium(account); //Add MOTD output->AddByte(0x14); std::ostringstream ss; ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD); output->AddString(ss.str()); //Add char list output->AddByte(0x64); output->AddByte((uint8_t)account.charList.size()); for (const std::string& characterName : account.charList) { output->AddString(characterName); if (g_config.getBoolean(ConfigManager::ON_OR_OFF_CHARLIST)) { if (g_game.getPlayerByName(characterName)) { output->AddString("Online"); } else { output->AddString("Offline"); } } else { output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); } output->AddU32(serverip); output->AddU16(g_config.getNumber(ConfigManager::GAME_PORT)); } //Add premium days if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { output->AddU16(0xFFFF); //client displays free premium } else { output->AddU16(account.premiumDays); } OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); return true; }
bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg) { if( #ifndef _CONSOLE !GUI::getInstance()->m_connections || #endif g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->closeConnection(); return false; } uint32_t clientip = getConnection()->getIP(); /*uint16_t clientos = */msg.GetU16(); uint16_t version = msg.GetU16(); msg.SkipBytes(12); if(version <= 760) { disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return false; } if(!RSA_decrypt(msg)) { getConnection()->closeConnection(); return false; } uint32_t key[4]; key[0] = msg.GetU32(); key[1] = msg.GetU32(); key[2] = msg.GetU32(); key[3] = msg.GetU32(); enableXTEAEncryption(); setXTEAKey(key); std::string accountName = msg.GetString(); std::string password = msg.GetString(); if(accountName.empty()) { if(g_config.getBoolean(ConfigManager::ACCOUNT_MANAGER)) { accountName = "1"; password = "******"; } else { disconnectClient(0x0A, "Invalid Account Name."); return false; } } if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return false; } if(g_game.getGameState() == GAME_STATE_STARTUP) { disconnectClient(0x0A, "Gameworld is starting up. Please wait."); return false; } if(g_game.getGameState() == GAME_STATE_MAINTAIN) { disconnectClient(0x0A, "Gameworld is under maintenance. Please re-connect in a while."); return false; } if(g_bans.isIpDisabled(clientip)) { disconnectClient(0x0A, "Too many connections attempts from this IP. Try again later."); return false; } if(IOBan::getInstance()->isIpBanished(clientip)) { disconnectClient(0x0A, "Your IP is banished!"); return false; } uint32_t serverip = serverIPs[0].first; for(uint32_t i = 0; i < serverIPs.size(); i++) { if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)) { serverip = serverIPs[i].first; break; } } Account account = IOLoginData::getInstance()->loadAccount(accountName); if(account.id == 0 || !passwordTest(password, account.password)) { g_bans.addLoginAttempt(clientip, false); disconnectClient(0x0A, "Account name or password is not correct."); return false; } g_bans.addLoginAttempt(clientip, true); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output) { TRACK_MESSAGE(output); //Update premium days g_game.updatePremium(account); //Add MOTD output->AddByte(0x14); std::ostringstream ss; ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD); output->AddString(ss.str()); //Add char list output->AddByte(0x64); if(g_config.getBoolean(ConfigManager::ACCOUNT_MANAGER) && account.id != 1) { output->AddByte((uint8_t)account.charList.size() + 1); output->AddString("Account Manager"); output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); output->AddU32(serverip); output->AddU16(g_config.getNumber(ConfigManager::GAME_PORT)); } else output->AddByte((uint8_t)account.charList.size()); std::list<std::string>::iterator it, end; for(it = account.charList.begin(), end = account.charList.end(); it != end; ++it) { output->AddString(*it); if(g_config.getBoolean(ConfigManager::ON_OR_OFF_CHARLIST)) { if(g_game.getPlayerByName((*it))) output->AddString("Online"); else output->AddString("Offline"); } else output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); output->AddU32(serverip); output->AddU16(g_config.getNumber(ConfigManager::GAME_PORT)); } //Add premium days if(g_config.getBoolean(ConfigManager::FREE_PREMIUM)) output->AddU16(0xFFFF); //client displays free premium else output->AddU16(account.premiumDays); OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); return true; }
void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& characterName) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (!output) { getConnection()->closeConnection(); return; } if (requestedInfo & REQUEST_BASIC_SERVER_INFO) { output->AddByte(0x10); output->AddString(g_config.getString(ConfigManager::SERVER_NAME)); output->AddString(g_config.getString(ConfigManager::IP)); output->AddString(std::to_string((uint32_t)g_config.getNumber(ConfigManager::LOGIN_PORT))); } if (requestedInfo & REQUEST_OWNER_SERVER_INFO) { output->AddByte(0x11); output->AddString(g_config.getString(ConfigManager::OWNER_NAME)); output->AddString(g_config.getString(ConfigManager::OWNER_EMAIL)); } if (requestedInfo & REQUEST_MISC_SERVER_INFO) { output->AddByte(0x12); output->AddString(g_config.getString(ConfigManager::MOTD)); output->AddString(g_config.getString(ConfigManager::LOCATION)); output->AddString(g_config.getString(ConfigManager::URL)); output->add<uint64_t>((OTSYS_TIME() - ProtocolStatus::start) / 1000); } if (requestedInfo & REQUEST_PLAYERS_INFO) { output->AddByte(0x20); output->add<uint32_t>(g_game.getPlayersOnline()); output->add<uint32_t>((uint32_t)g_config.getNumber(ConfigManager::MAX_PLAYERS)); output->add<uint32_t>(g_game.getPlayersRecord()); } if (requestedInfo & REQUEST_MAP_INFO) { output->AddByte(0x30); output->AddString(g_config.getString(ConfigManager::MAP_NAME)); output->AddString(g_config.getString(ConfigManager::MAP_AUTHOR)); uint32_t mapWidth, mapHeight; g_game.getMapDimensions(mapWidth, mapHeight); output->add<uint16_t>(mapWidth); output->add<uint16_t>(mapHeight); } if (requestedInfo & REQUEST_EXT_PLAYERS_INFO) { output->AddByte(0x21); // players info - online players list const auto& players = g_game.getPlayers(); output->add<uint32_t>(players.size()); for (const auto& it : players) { output->AddString(it.second->getName()); output->add<uint32_t>(it.second->getLevel()); } } if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { output->AddByte(0x22); // players info - online status info of a player if (g_game.getPlayerByName(characterName) != nullptr) { output->AddByte(0x01); } else { output->AddByte(0x00); } } if (requestedInfo & REQUEST_SERVER_SOFTWARE_INFO) { output->AddByte(0x23); // server software info output->AddString(STATUS_SERVER_NAME); output->AddString(STATUS_SERVER_VERSION); output->AddString(CLIENT_VERSION_STR); } OutputMessagePool::getInstance()->send(output); getConnection()->closeConnection(); }
bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg) { if(g_game.getGameState() == GAME_STATE_SHUTDOWN){ getConnection()->closeConnection(); return false; } uint32_t clientip = getConnection()->getIP(); /*uint16_t clientos =*/ msg.GetU16(); uint16_t version = msg.GetU16(); msg.SkipBytes(12); if(version <= 760){ disconnectClient(0x0A, "This server requires client version " CLIENT_VERSION_STRING "."); } if(!RSA_decrypt(msg)){ getConnection()->closeConnection(); return false; } uint32_t key[4]; key[0] = msg.GetU32(); key[1] = msg.GetU32(); key[2] = msg.GetU32(); key[3] = msg.GetU32(); enableXTEAEncryption(); setXTEAKey(key); std::string accname = msg.GetString(); std::string password = msg.GetString(); if(!accname.length()){ //Tibia sends this message if the account name length is < 5 //We will send it only if account name is BLANK disconnectClient(0x0A, "Invalid Account Name."); return false; } if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX){ disconnectClient(0x0A, "This server requires client version " CLIENT_VERSION_STRING "."); return false; } if(g_game.getGameState() == GAME_STATE_STARTUP){ disconnectClient(0x0A, "Gameworld is starting up. Please wait."); return false; } if(g_bans.isIpDisabled(clientip)){ disconnectClient(0x0A, "Too many connections attempts from this IP. Try again later."); return false; } if(g_bans.isIpBanished(clientip)){ disconnectClient(0x0A, "Your IP is banished!"); return false; } /* uint32_t serverip = serverIPs[0].first; for(uint32_t i = 0; i < serverIPs.size(); i++){ if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)){ serverip = serverIPs[i].first; break; } } */ Account account = IOAccount::instance()->loadAccount(accname); if(!(asLowerCaseString(account.name) == asLowerCaseString(accname) && passwordTest(password, account.password))){ g_bans.addLoginAttempt(clientip, false); disconnectClient(0x0A, "Account name or password is not correct."); return false; } g_bans.addLoginAttempt(clientip, true); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); //Add MOTD std::stringstream motd; output->AddByte(0x14); motd << g_config.getNumber(ConfigManager::MOTD_NUM) << "\n"; motd << g_config.getString(ConfigManager::MOTD); output->AddString(motd.str()); //Add char list output->AddByte(0x64); output->AddByte((uint8_t)account.charList.size()); std::list<AccountCharacter>::iterator it; for(it = account.charList.begin(); it != account.charList.end(); it++){ const AccountCharacter& character = *it; output->AddString(character.name); output->AddString(character.world_name); output->AddU32(character.ip); output->AddU16(character.port); } output->AddU16(IOAccount::getPremiumDaysLeft(account.premiumEnd)); OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); return true; }