diff --git a/key.pem b/key.pem new file mode 100644 index 0000000..ec19bb4 --- /dev/null +++ b/key.pem @@ -0,0 +1,13 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCbZGkDtFsHrJVlaNhzU71xZROd15QHA7A+bdB5OZZhtKg3qmBWHXzLlFL6AIBZ +SQmIKrW8pYoaGzX4sQWbcrEhJhHGFSrT27PPvuetwUKnXT11lxUJwyHFwkpb1R/UYPAbThW+sN4Z +MFKKXT8VwePL9cQB1nd+EKyqsz2+jVt/9QIDAQABAoGAQovTtTRtr3GnYRBvcaQxAvjIV9ZUnFRm +C7Y3i1KwJhOZ3ozmSLrEEOLqTgoc7R+sJ1YzEiDKbbete11EC3gohlhW56ptj0WDf+7ptKOgqiEy +Kh4qt1sYJeeGz4GiiooJoeKFGdtk/5uvMR6FDCv6H7ewigVswzf330Q3Ya7+jYECQQERBxsga6+5 +x6IofXyNF6QuMqvuiN/pUgaStUOdlnWBf/T4yUpKvNS1+I4iDzqGWOOSR6RsaYPYVhj9iRABoKyx +AkEAkbNzB6vhLAWht4dUdGzaREF3p4SwNcu5bJRa/9wCLSHaS9JaTq4lljgVPp1zyXyJCSCWpFnl +0WvK3Qf6nVBIhQJBANS7rK8+ONWQbxENdZaZ7Rrx8HUTwSOS/fwhsGWBbl1Qzhdq/6/sIfEHkfeH +1hoH+IlpuPuf21MdAqvJt+cMwoECQF1LyBOYduYGcSgg6u5mKVldhm3pJCA+ZGxnjuGZEnet3qeA +eb05++112fyvO85ABUun524z9lokKNFh45NKLjUCQGshzV43P+RioiBhtEpB/QFzijiS4L2HKNu1 +tdhudnUjWkaf6jJmQS/ppln0hhRMHlk9Vus/bPx7LtuDuo6VQDo= +-----END RSA PRIVATE KEY----- diff --git a/src/connection.cpp b/src/connection.cpp index 859066c..56a3861 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -182,45 +182,66 @@ void Connection::parsePacket(const boost::system::error_code& error) if (error) { close(FORCE_CLOSE); return; - } else if (connectionState != CONNECTION_STATE_OPEN) { + } + else if (connectionState != CONNECTION_STATE_OPEN) { return; } + //Check packet checksum + uint32_t checksum; + int32_t len = msg.getLength() - msg.getBufferPosition() - NetworkMessage::CHECKSUM_LENGTH; + if (len > 0) { + checksum = adlerChecksum(msg.getBuffer() + msg.getBufferPosition() + NetworkMessage::CHECKSUM_LENGTH, len); + } + else { + checksum = 0; + } + + uint32_t recvChecksum = msg.get(); + if (recvChecksum != checksum) { + // it might not have been the checksum, step back + msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH); + } + if (!receivedFirst) { // First message received receivedFirst = true; if (!protocol) { // Game protocol has already been created at this point - protocol = service_port->make_protocol(msg, shared_from_this()); + protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this()); if (!protocol) { close(FORCE_CLOSE); return; } - } else { + } + else { msg.skipBytes(1); // Skip protocol ID } protocol->onRecvFirstMessage(msg); - } else { + } + else { protocol->onRecvMessage(msg); // Send the packet to the current protocol } try { readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), - std::placeholders::_1)); + std::placeholders::_1)); // Wait to the next packet boost::asio::async_read(socket, - boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), - std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); - } catch (boost::system::system_error& e) { + boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), + std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); + } + catch (boost::system::system_error& e) { std::cout << "[Network error - Connection::parsePacket] " << e.what() << std::endl; close(FORCE_CLOSE); } } + void Connection::send(const OutputMessage_ptr& msg) { std::lock_guard lockClass(connectionLock); diff --git a/src/const.h b/src/const.h index 8490b1f..f596521 100644 --- a/src/const.h +++ b/src/const.h @@ -335,4 +335,12 @@ static constexpr int32_t CHANNEL_PARTY = 0x01; static constexpr int32_t CHANNEL_RULE_REP = 0x02; static constexpr int32_t CHANNEL_PRIVATE = 0xFFFF; +//Reserved player storage key ranges; +//[10000000 - 20000000]; +static constexpr int32_t PSTRG_RESERVED_RANGE_START = 10000000; +static constexpr int32_t PSTRG_RESERVED_RANGE_SIZE = 10000000; +//[1000 - 1500]; +static constexpr int32_t PSTRG_OUTFITS_RANGE_START = (PSTRG_RESERVED_RANGE_START + 1000); +static constexpr int32_t PSTRG_OUTFITS_RANGE_SIZE = 500; + #endif diff --git a/src/definitions.h b/src/definitions.h index 4ab6c38..cec245e 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -22,12 +22,15 @@ static constexpr auto STATUS_SERVER_NAME = "Sabrehaven"; static constexpr auto STATUS_SERVER_VERSION = "1.0"; -static constexpr auto STATUS_SERVER_DEVELOPERS = "Sabrehaven Developers Team"; +static constexpr auto STATUS_SERVER_DEVELOPERS = "OTLand community & Sabrehaven Developers Team"; static constexpr auto CLIENT_VERSION_MIN = 772; static constexpr auto CLIENT_VERSION_MAX = 772; static constexpr auto CLIENT_VERSION_STR = "7.72"; +static constexpr auto AUTHENTICATOR_DIGITS = 6U; +static constexpr auto AUTHENTICATOR_PERIOD = 30U; + #ifndef __FUNCTION__ #define __FUNCTION__ __func__ #endif diff --git a/src/networkmessage.h b/src/networkmessage.h index 7d11153..b588f5a 100644 --- a/src/networkmessage.h +++ b/src/networkmessage.h @@ -37,6 +37,7 @@ class NetworkMessage // 2 bytes for encrypted message size static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 4; enum { HEADER_LENGTH = 2 }; + enum { CHECKSUM_LENGTH = 4 }; enum { XTEA_MULTIPLE = 8 }; enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - XTEA_MULTIPLE }; enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 }; diff --git a/src/otserv.cpp b/src/otserv.cpp index c6ee693..e6762a4 100644 --- a/src/otserv.cpp +++ b/src/otserv.cpp @@ -163,9 +163,13 @@ void mainLoader(int, char*[], ServiceManager* services) #endif //set RSA key - const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); - const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); - g_RSA.setKey(p, q); + try { + g_RSA.loadPEM("key.pem"); + } + catch (const std::exception& e) { + startupErrorMessage(e.what()); + return; + } std::cout << ">> Establishing database connection..." << std::flush; diff --git a/src/outputmessage.h b/src/outputmessage.h index 01897ff..92c690d 100644 --- a/src/outputmessage.h +++ b/src/outputmessage.h @@ -43,7 +43,11 @@ class OutputMessage : public NetworkMessage add_header(info.length); } - void addCryptoHeader() { + void addCryptoHeader(bool addChecksum) { + if (addChecksum) { + add_header(adlerChecksum(buffer + outputBufferStart, info.length)); + } + writeMessageLength(); } diff --git a/src/party.cpp b/src/party.cpp index 9ac0bed..e0d80a4 100644 --- a/src/party.cpp +++ b/src/party.cpp @@ -473,3 +473,11 @@ void Party::clearPlayerPoints(Player* player) updateSharedExperience(); } } + +bool Party::canOpenCorpse(uint32_t ownerId) const +{ + if (Player* player = g_game.getPlayerByID(ownerId)) { + return leader->getID() == ownerId || player->getParty() == this; + } + return false; +} diff --git a/src/party.h b/src/party.h index 58c72ec..96fce94 100644 --- a/src/party.h +++ b/src/party.h @@ -65,6 +65,7 @@ class Party bool empty() const { return memberList.empty() && inviteList.empty(); } + bool canOpenCorpse(uint32_t ownerId) const; void shareExperience(uint64_t experience, Creature* source/* = nullptr*/); bool setSharedExperience(Player* player, bool sharedExpActive); diff --git a/src/protocollogin.cpp b/src/protocollogin.cpp index fb2602b..fad7a98 100644 --- a/src/protocollogin.cpp +++ b/src/protocollogin.cpp @@ -198,13 +198,13 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg) uint32_t accountNumber = msg.get(); if (!accountNumber) { - disconnectClient("Invalid account number."); + disconnectClient("Invalid account number.", version); return; } std::string password = msg.getString(); if (password.empty()) { - disconnectClient("Invalid password."); + disconnectClient("Invalid password.", version); return; } @@ -218,5 +218,5 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg) std::string authToken = msg.getString(); auto thisPtr = std::static_pointer_cast(shared_from_this()); - g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, version))); + g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, authToken, version))); } diff --git a/src/spells.cpp b/src/spells.cpp index a79f0b8..b08a048 100644 --- a/src/spells.cpp +++ b/src/spells.cpp @@ -1801,47 +1801,46 @@ ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& to return RETURNVALUE_NOERROR; } -bool RuneSpell::executeUse(Player* player, Item* item, const Position&, Thing* target, const Position& toPosition) +bool RuneSpell::executeUse(Player* player, Item* item, const Position&, Thing* target, const Position& toPosition, bool isHotkey) { if (!playerRuneSpellCheck(player, toPosition)) { return false; } - bool result = false; - if (scripted) { - LuaVariant var; - - if (needTarget) { - var.type = VARIANT_NUMBER; - - if (target == nullptr) { - Tile* toTile = g_game.map.getTile(toPosition); - if (toTile) { - const Creature* visibleCreature = toTile->getTopCreature(); - if (visibleCreature) { - var.number = visibleCreature->getID(); - } - } - } else { - var.number = target->getCreature()->getID(); - } - } else { - var.type = VARIANT_POSITION; - var.pos = toPosition; - } - - result = internalCastSpell(player, var); - } else if (runeFunction) { - result = runeFunction(this, player, toPosition); + if (!scripted) { + return false; } - if (!result) { + LuaVariant var; + + if (needTarget) { + var.type = VARIANT_NUMBER; + + if (target == nullptr) { + Tile* toTile = g_game.map.getTile(toPosition); + if (toTile) { + const Creature* visibleCreature = toTile->getBottomVisibleCreature(player); + if (visibleCreature) { + var.number = visibleCreature->getID(); + } + } + } + else { + var.number = target->getCreature()->getID(); + } + } + else { + var.type = VARIANT_POSITION; + var.pos = toPosition; + } + + if (!internalCastSpell(player, var, isHotkey)) { return false; } postCastSpell(player); if (hasCharges && item && g_config.getBoolean(ConfigManager::REMOVE_RUNE_CHARGES)) { - int32_t newCount = std::max(0, item->getCharges() - 1); + int32_t newCount = std::max(0, item->getItemCount() - 1); g_game.transformItem(item, item->getID(), newCount); } return true; @@ -1852,7 +1851,7 @@ bool RuneSpell::castSpell(Creature* creature) LuaVariant var; var.type = VARIANT_NUMBER; var.number = creature->getID(); - return internalCastSpell(creature, var); + return internalCastSpell(creature, var, false); } bool RuneSpell::castSpell(Creature* creature, Creature* target) @@ -1860,23 +1859,24 @@ bool RuneSpell::castSpell(Creature* creature, Creature* target) LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); - return internalCastSpell(creature, var); + return internalCastSpell(creature, var, false); } -bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var) +bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey) { bool result; if (scripted) { - result = executeCastSpell(creature, var); - } else { + result = executeCastSpell(creature, var, isHotkey); + } + else { result = false; } return result; } -bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var) +bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey) { - //onCastSpell(creature, var) + //onCastSpell(creature, var, isHotkey) if (!scriptInterface->reserveScriptEnv()) { std::cout << "[Error - RuneSpell::executeCastSpell] Call stack overflow" << std::endl; return false; @@ -1894,5 +1894,7 @@ bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var) LuaScriptInterface::pushVariant(L, var); - return scriptInterface->callFunction(2); + LuaScriptInterface::pushBoolean(L, isHotkey); + + return scriptInterface->callFunction(3); } diff --git a/src/spells.h b/src/spells.h index 24ddab3..d0907fe 100644 --- a/src/spells.h +++ b/src/spells.h @@ -56,7 +56,7 @@ class Spells final : public BaseEvents TalkActionResult_t playerSaySpell(Player* player, std::string& words); static Position getCasterPosition(Creature* creature, Direction dir); - std::string getScriptBaseName() const final; + std::string getScriptBaseName() const override; protected: void clear() final; @@ -94,9 +94,9 @@ class CombatSpell final : public Event, public BaseSpell CombatSpell(const CombatSpell&) = delete; CombatSpell& operator=(const CombatSpell&) = delete; - bool castSpell(Creature* creature) final; - bool castSpell(Creature* creature, Creature* target) final; - bool configureEvent(const pugi::xml_node&) final { + bool castSpell(Creature* creature) override; + bool castSpell(Creature* creature, Creature* target) override; + bool configureEvent(const pugi::xml_node&) override { return true; } @@ -109,7 +109,7 @@ class CombatSpell final : public Event, public BaseSpell } protected: - std::string getScriptEventName() const final { + std::string getScriptEventName() const override { return "onCastSpell"; } @@ -209,7 +209,7 @@ class InstantSpell : public TalkAction, public Spell //scripting bool executeCastSpell(Creature* creature, const LuaVariant& var); - bool isInstant() const final { + bool isInstant() const override { return true; } bool getHasParam() const { @@ -291,13 +291,13 @@ class RuneSpell final : public Action, public Spell return targetCreature; } - bool executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition) final; + bool executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition, bool isHotkey) override; bool castSpell(Creature* creature) final; bool castSpell(Creature* creature, Creature* target) final; //scripting - bool executeCastSpell(Creature* creature, const LuaVariant& var); + bool executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey); bool isInstant() const final { return false; @@ -312,7 +312,7 @@ class RuneSpell final : public Action, public Spell static RuneSpellFunction Illusion; static RuneSpellFunction Convince; - bool internalCastSpell(Creature* creature, const LuaVariant& var); + bool internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey); RuneSpellFunction* runeFunction = nullptr; uint16_t runeId = 0;