diff --git a/modules/gamelib/game.lua b/modules/gamelib/game.lua index 70531054..7d83797d 100644 --- a/modules/gamelib/game.lua +++ b/modules/gamelib/game.lua @@ -1,4 +1,4 @@ -local currentRsa = OTSERV_RSA +local currentRsa function g_game.getRsa() return currentRsa @@ -6,14 +6,17 @@ end function g_game.chooseRsa(host) if host:match('.*\.tibia\.com') or host:match('.*\.cipsoft\.com') then - currentRsa = CIPSOFT_RSA + g_game.setRsa(CIPSOFT_RSA) else - currentRsa = OTSERV_RSA + g_game.setRsa(OTSERV_RSA) end end function g_game.setRsa(rsa) - currentRsa = rsa + if currentRsa ~= rsa then + currentRsa = rsa + g_crypt.rsaSetPublicKey(currentRsa, '65537') + end end function g_game.isOfficialTibia() @@ -45,3 +48,4 @@ function g_game.getSupportedProtocols() } end +g_game.setRsa(OTSERV_RSA) diff --git a/modules/gamelib/protocollogin.lua b/modules/gamelib/protocollogin.lua index 535a52d9..7a2cd6ba 100644 --- a/modules/gamelib/protocollogin.lua +++ b/modules/gamelib/protocollogin.lua @@ -65,7 +65,7 @@ function ProtocolLogin:sendLoginPacket() end msg:addPaddingBytes(paddingBytes, 0) - msg:encryptRsa(128, g_game.getRsa()) + msg:encryptRsa(128) self:send(msg) self:enableXteaEncryption() diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 8b2047fb..51eb2890 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -29,8 +29,6 @@ set(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/util/matrix.h ${CMAKE_CURRENT_LIST_DIR}/util/point.h ${CMAKE_CURRENT_LIST_DIR}/util/rect.h - ${CMAKE_CURRENT_LIST_DIR}/util/rsa.cpp - ${CMAKE_CURRENT_LIST_DIR}/util/rsa.h ${CMAKE_CURRENT_LIST_DIR}/util/size.h # stdext diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index d291d91e..98ec767f 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -83,10 +83,13 @@ void Application::registerLuaFunctions() // Crypt g_lua.registerSingletonClass("g_crypt"); - g_lua.bindClassStaticFunction("g_crypt", "encrypt", Crypt::encrypt); - g_lua.bindClassStaticFunction("g_crypt", "decrypt", Crypt::decrypt); - g_lua.bindClassStaticFunction("g_crypt", "sha1Encode", Crypt::sha1Encode); - g_lua.bindClassStaticFunction("g_crypt", "md5Encode", Crypt::md5Encode); + g_lua.bindSingletonFunction("g_crypt", "encrypt", &Crypt::encrypt, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "decrypt", &Crypt::decrypt, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "sha1Encode", &Crypt::sha1Encode, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "md5Encode", &Crypt::md5Encode, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "rsaSetPublicKey", &Crypt::rsaSetPublicKey, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "rsaSetPrivateKey", &Crypt::rsaSetPrivateKey, &g_crypt); + g_lua.bindSingletonFunction("g_crypt", "rsaCheckKey", &Crypt::rsaCheckKey, &g_crypt); // Clock g_lua.registerSingletonClass("g_clock"); @@ -635,6 +638,8 @@ void Application::registerLuaFunctions() // Server g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &Server::create); + g_lua.bindClassMemberFunction("close", &Server::close); + g_lua.bindClassMemberFunction("isOpen", &Server::isOpen); g_lua.bindClassMemberFunction("acceptNext", &Server::acceptNext); // Connection diff --git a/src/framework/net/inputmessage.cpp b/src/framework/net/inputmessage.cpp index 334edec8..51a1a46c 100644 --- a/src/framework/net/inputmessage.cpp +++ b/src/framework/net/inputmessage.cpp @@ -21,7 +21,7 @@ */ #include "inputmessage.h" -#include +#include InputMessage::InputMessage() { @@ -86,13 +86,10 @@ std::string InputMessage::getString() return std::string(v, stringLength); } -bool InputMessage::decryptRsa(int size, const std::string& key, const std::string& p, const std::string& q, const std::string& d) +bool InputMessage::decryptRsa(int size) { checkRead(size); - g_rsa.setPublic(key.c_str(), "65537"); - g_rsa.setPrivate(p.c_str(), q.c_str(), d.c_str()); - g_rsa.check(); - g_rsa.decrypt((unsigned char*)m_buffer + m_readPos, size); + g_crypt.rsaDecrypt((unsigned char*)m_buffer + m_readPos, size); return (getU8() == 0x00); } diff --git a/src/framework/net/inputmessage.h b/src/framework/net/inputmessage.h index 7daf3ee2..2a224a2c 100644 --- a/src/framework/net/inputmessage.h +++ b/src/framework/net/inputmessage.h @@ -52,7 +52,7 @@ public: uint32 peekU32() { uint32 v = getU32(); m_readPos-=4; return v; } uint64 peekU64() { uint64 v = getU64(); m_readPos-=8; return v; } - bool decryptRsa(int size, const std::string& key, const std::string& p, const std::string& q, const std::string& d); + bool decryptRsa(int size); int getReadSize() { return m_readPos - m_headerPos; } int getReadPos() { return m_readPos; } diff --git a/src/framework/net/outputmessage.cpp b/src/framework/net/outputmessage.cpp index ca0432f2..3b076812 100644 --- a/src/framework/net/outputmessage.cpp +++ b/src/framework/net/outputmessage.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include OutputMessage::OutputMessage() { @@ -89,13 +89,12 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte) m_messageSize += bytes; } -void OutputMessage::encryptRsa(int size, const std::string& key) +void OutputMessage::encryptRsa(int size) { if(m_messageSize < size) throw stdext::exception("insufficient bytes in buffer to encrypt"); - g_rsa.setPublic(key.c_str(), "65537"); - g_rsa.encrypt((unsigned char*)m_buffer + m_writePos - size, size); + g_crypt.rsaEncrypt((unsigned char*)m_buffer + m_writePos - size, size); } void OutputMessage::writeChecksum() diff --git a/src/framework/net/outputmessage.h b/src/framework/net/outputmessage.h index 4e33f30e..2240f706 100644 --- a/src/framework/net/outputmessage.h +++ b/src/framework/net/outputmessage.h @@ -49,7 +49,7 @@ public: void addString(const std::string& buffer); void addPaddingBytes(int bytes, uint8 byte = 0); - void encryptRsa(int size, const std::string& key); + void encryptRsa(int size); uint16 getMessageSize() { return m_messageSize; } diff --git a/src/framework/net/server.cpp b/src/framework/net/server.cpp index e7bd8879..c7ccc1a0 100644 --- a/src/framework/net/server.cpp +++ b/src/framework/net/server.cpp @@ -35,15 +35,23 @@ ServerPtr Server::create(int port) return ServerPtr(new Server(port)); } +void Server::close() +{ + m_isOpen = false; + m_acceptor.cancel(); + m_acceptor.close(); +} + void Server::acceptNext() { ConnectionPtr connection = ConnectionPtr(new Connection); connection->m_connecting = true; + auto self = static_self_cast(); m_acceptor.async_accept(connection->m_socket, [=](const boost::system::error_code& error) { if(!error) { connection->m_connected = true; connection->m_connecting = false; } - callLuaField("onAccept", connection, error.message(), error.value()); + self->callLuaField("onAccept", connection, error.message(), error.value()); }); } diff --git a/src/framework/net/server.h b/src/framework/net/server.h index 48ca347e..d3f1bcea 100644 --- a/src/framework/net/server.h +++ b/src/framework/net/server.h @@ -28,15 +28,16 @@ class Server : public LuaObject { - typedef std::function AcceptCallback; - public: Server(int port); static ServerPtr create(int port); + bool isOpen() { return m_isOpen; } + void close(); void acceptNext(); private: + stdext::boolean m_isOpen; asio::ip::tcp::acceptor m_acceptor; }; diff --git a/src/framework/util/crypt.cpp b/src/framework/util/crypt.cpp index 73ec1522..cc01e3fc 100644 --- a/src/framework/util/crypt.cpp +++ b/src/framework/util/crypt.cpp @@ -22,16 +22,31 @@ #include "crypt.h" #include +#include #include #include #include #include +#include +#include static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } +Crypt g_crypt; + +Crypt::Crypt() +{ + m_rsa = RSA_new(); +} + +Crypt::~Crypt() +{ + RSA_free(m_rsa); +} + std::string Crypt::base64Encode(const std::string& decoded_string) { std::string ret; @@ -204,3 +219,49 @@ std::string Crypt::sha1Encode(std::string decoded_string, bool upperCase) std::transform(result.begin(), result.end(), result.begin(), tolower); return result; } + +void Crypt::rsaSetPublicKey(const std::string& n, const std::string& e) +{ + BN_dec2bn(&m_rsa->n, n.c_str()); + BN_dec2bn(&m_rsa->e, e.c_str()); +} + +void Crypt::rsaSetPrivateKey(const std::string& p, const std::string& q, const std::string& d) +{ + BN_dec2bn(&m_rsa->p, p.c_str()); + BN_dec2bn(&m_rsa->q, q.c_str()); + BN_dec2bn(&m_rsa->d, d.c_str()); +} + +bool Crypt::rsaCheckKey() +{ + // only used by server, that sets both public and private + if(RSA_check_key(m_rsa)) { + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_start(ctx); + + BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx); + BN_mod(m_rsa->dmp1, m_rsa->d, r1, ctx); + BN_mod(m_rsa->dmq1, m_rsa->d, r2, ctx); + + BN_mod_inverse(m_rsa->iqmp, m_rsa->q, m_rsa->p, ctx); + return true; + } + else { + ERR_load_crypto_strings(); + g_logger.error(stdext::format("RSA check failed - %s", ERR_error_string(ERR_get_error(), NULL))); + return false; + } +} + +bool Crypt::rsaEncrypt(unsigned char *msg, int size) +{ + assert(size <= 128); + return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; +} + +bool Crypt::rsaDecrypt(unsigned char *msg, int size) +{ + assert(size <= 128); + return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; +} diff --git a/src/framework/util/crypt.h b/src/framework/util/crypt.h index 0902320c..cfa72647 100644 --- a/src/framework/util/crypt.h +++ b/src/framework/util/crypt.h @@ -26,7 +26,14 @@ #include "../stdext/types.h" #include -namespace Crypt { +#include + +class Crypt +{ +public: + Crypt(); + ~Crypt(); + std::string base64Encode(const std::string& decoded_string); std::string base64Decode(const std::string& encoded_string); std::string xorCrypt(const std::string& buffer, const std::string& key); @@ -35,6 +42,17 @@ namespace Crypt { std::string decrypt(const std::string& encrypted_string); std::string md5Encode(std::string decoded_string, bool upperCase); std::string sha1Encode(std::string decoded_string, bool upperCase); -} + + void rsaSetPublicKey(const std::string& n, const std::string& e); + void rsaSetPrivateKey(const std::string &p, const std::string &q, const std::string &d); + bool rsaCheckKey(); + bool rsaEncrypt(unsigned char *msg, int size); + bool rsaDecrypt(unsigned char *msg, int size); + +private: + RSA *m_rsa; +}; + +extern Crypt g_crypt; #endif diff --git a/src/framework/util/rsa.cpp b/src/framework/util/rsa.cpp deleted file mode 100644 index 65e87fb0..00000000 --- a/src/framework/util/rsa.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "rsa.h" -#include -#include - -Rsa g_rsa; - -Rsa::Rsa() -{ - m_rsa = RSA_new(); -} - -Rsa::~Rsa() -{ - RSA_free(m_rsa); -} - -void Rsa::setPublic(const char *n, const char *e) -{ - BN_dec2bn(&m_rsa->n, n); - BN_dec2bn(&m_rsa->e, e); -} - -void Rsa::setPrivate(const char *p, const char *q, const char *d) -{ - BN_dec2bn(&m_rsa->p, p); - BN_dec2bn(&m_rsa->q, q); - BN_dec2bn(&m_rsa->d, d); -} - -bool Rsa::check() // only used by server, that sets both public and private -{ - if(RSA_check_key(m_rsa)) { - BN_CTX *ctx = BN_CTX_new(); - BN_CTX_start(ctx); - - BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx); - BN_mod(m_rsa->dmp1, m_rsa->d, r1, ctx); - BN_mod(m_rsa->dmq1, m_rsa->d, r2, ctx); - - BN_mod_inverse(m_rsa->iqmp, m_rsa->q, m_rsa->p, ctx); - return true; - } - else { - ERR_load_crypto_strings(); - g_logger.error(stdext::format("RSA check failed - %s", ERR_error_string(ERR_get_error(), NULL))); - return false; - } -} - -bool Rsa::encrypt(unsigned char *msg, int size) -{ - assert(size <= 128); - return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; -} - -bool Rsa::decrypt(unsigned char *msg, int size) -{ - assert(size <= 128); - return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; -} diff --git a/src/framework/util/rsa.h b/src/framework/util/rsa.h deleted file mode 100644 index cae4bac2..00000000 --- a/src/framework/util/rsa.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RSA_H -#define RSA_H - -#include -#include - -class Rsa -{ -public: - Rsa(); - ~Rsa(); - - void setPublic(const char *n, const char *e); - void setPrivate(const char *p, const char *q, const char *d); - bool check(); - - bool encrypt(unsigned char *msg, int size); - bool decrypt(unsigned char *msg, int size); - -private: - RSA *m_rsa; -}; - -extern Rsa g_rsa; - -#endif diff --git a/src/otclient/protocolgamesend.cpp b/src/otclient/protocolgamesend.cpp index a19f91cf..6c8d1870 100644 --- a/src/otclient/protocolgamesend.cpp +++ b/src/otclient/protocolgamesend.cpp @@ -91,7 +91,7 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando msg->addPaddingBytes(paddingBytes); // encrypt with RSA - msg->encryptRsa(128, g_lua.callGlobalField("g_game", "getRsa")); + msg->encryptRsa(128); send(msg);