From df11916ad53e6b2f64cd1af5d5296ba188f3e486 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 7 Aug 2014 19:02:08 +0200 Subject: Core/NetworkIO: Allow receiving packets bigger than buffer size and properly handle situations where not entire packet was read in one go Core/Authserver: Restored authenticator functionality --- src/server/authserver/Server/AuthSession.cpp | 76 ++++++++++++---------------- 1 file changed, 31 insertions(+), 45 deletions(-) (limited to 'src/server/authserver/Server/AuthSession.cpp') diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index cdd8298174f..e6a775e93ee 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -21,6 +21,7 @@ #include "AuthCodes.h" #include "Database/DatabaseEnv.h" #include "SHA1.h" +#include "TOTP.h" #include "openssl/crypto.h" #include "Configuration/Config.h" #include "RealmList.h" @@ -52,7 +53,6 @@ enum eStatus typedef struct AUTH_LOGON_CHALLENGE_C { - uint8 cmd; uint8 error; uint16 size; uint8 gamename[4]; @@ -71,7 +71,6 @@ typedef struct AUTH_LOGON_CHALLENGE_C typedef struct AUTH_LOGON_PROOF_C { - uint8 cmd; uint8 A[32]; uint8 M1[20]; uint8 crc_hash[20]; @@ -99,7 +98,6 @@ typedef struct AUTH_LOGON_PROOF_S_OLD typedef struct AUTH_RECONNECT_PROOF_C { - uint8 cmd; uint8 R1[16]; uint8 R2[20]; uint8 R3[20]; @@ -114,10 +112,10 @@ enum class BufferSizes : uint32 SRP_6_S = 0x20, }; -#define REALM_LIST_PACKET_SIZE 5 -#define XFER_ACCEPT_SIZE 1 -#define XFER_RESUME_SIZE 9 -#define XFER_CANCEL_SIZE 1 +#define REALM_LIST_PACKET_SIZE 4 +#define XFER_ACCEPT_SIZE 0 +#define XFER_RESUME_SIZE 8 +#define XFER_CANCEL_SIZE 0 std::unordered_map AuthSession::InitHandlers() { @@ -137,44 +135,36 @@ std::unordered_map AuthSession::InitHandlers() std::unordered_map const Handlers = AuthSession::InitHandlers(); -void AuthSession::ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) +void AuthSession::ReadHeaderHandler() { - if (!error && transferedBytes == 1) + uint8 cmd = GetHeaderBuffer()[0]; + auto itr = Handlers.find(cmd); + if (itr != Handlers.end()) { - uint8 cmd = GetReadBuffer()[0]; - auto itr = Handlers.find(cmd); - if (itr != Handlers.end()) + // Handle dynamic size packet + if (cmd == AUTH_LOGON_CHALLENGE || cmd == AUTH_RECONNECT_CHALLENGE) { - // Handle dynamic size packet - if (cmd == AUTH_LOGON_CHALLENGE || cmd == AUTH_RECONNECT_CHALLENGE) - { - ReadData(sizeof(uint8) + sizeof(uint16), sizeof(cmd)); //error + size - sAuthLogonChallenge_C* challenge = reinterpret_cast(GetReadBuffer()); + ReadData(sizeof(uint8) + sizeof(uint16)); //error + size + sAuthLogonChallenge_C* challenge = reinterpret_cast(GetDataBuffer()); - AsyncReadData(challenge->size, sizeof(uint8) + sizeof(uint8) + sizeof(uint16)); // cmd + error + size - } - else - AsyncReadData(itr->second.packetSize, sizeof(uint8)); + AsyncReadData(challenge->size); } + else + AsyncReadData(itr->second.packetSize); } else CloseSocket(); } -void AuthSession::ReadDataHandler(boost::system::error_code error, size_t transferedBytes) +void AuthSession::ReadDataHandler() { - if (!error && transferedBytes > 0) + if (!(*this.*Handlers.at(GetHeaderBuffer()[0]).handler)()) { - if (!(*this.*Handlers.at(GetReadBuffer()[0]).handler)()) - { - CloseSocket(); - return; - } - - AsyncReadHeader(); - } - else CloseSocket(); + return; + } + + AsyncReadHeader(); } void AuthSession::AsyncWrite(ByteBuffer& packet) @@ -191,7 +181,7 @@ void AuthSession::AsyncWrite(ByteBuffer& packet) bool AuthSession::HandleLogonChallenge() { - sAuthLogonChallenge_C* challenge = reinterpret_cast(GetReadBuffer()); + sAuthLogonChallenge_C* challenge = reinterpret_cast(GetDataBuffer()); //TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got full packet, %#04x bytes", challenge->size); TC_LOG_DEBUG("server.authserver", "[AuthChallenge] name(%d): '%s'", challenge->I_len, challenge->I); @@ -410,7 +400,7 @@ bool AuthSession::HandleLogonProof() TC_LOG_DEBUG("server.authserver", "Entering _HandleLogonProof"); // Read the packet - sAuthLogonProof_C *logonProof = reinterpret_cast(GetReadBuffer()); + sAuthLogonProof_C *logonProof = reinterpret_cast(GetDataBuffer()); // If the client has no valid version if (_expversion == NO_VALID_EXP_FLAG) @@ -522,17 +512,13 @@ bool AuthSession::HandleLogonProof() // Check auth token if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty()) { - // TODO To be fixed - - /* - uint8 size; - socket().recv((char*)&size, 1); - char* token = new char[size + 1]; + ReadData(1); + uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C)); + ReadData(size); + char* token = reinterpret_cast(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)); token[size] = '\0'; - socket().recv(token, size); unsigned int validToken = TOTP::GenerateToken(_tokenKey.c_str()); unsigned int incomingToken = atoi(token); - delete[] token; if (validToken != incomingToken) { ByteBuffer packet; @@ -542,7 +528,7 @@ bool AuthSession::HandleLogonProof() packet << uint8(0); AsyncWrite(packet); return false; - }*/ + } } ByteBuffer packet; @@ -650,7 +636,7 @@ bool AuthSession::HandleLogonProof() bool AuthSession::HandleReconnectChallenge() { TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectChallenge"); - sAuthLogonChallenge_C* challenge = reinterpret_cast(GetReadBuffer()); + sAuthLogonChallenge_C* challenge = reinterpret_cast(GetDataBuffer()); //TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got full packet, %#04x bytes", challenge->size); TC_LOG_DEBUG("server.authserver", "[AuthChallenge] name(%d): '%s'", challenge->I_len, challenge->I); @@ -701,7 +687,7 @@ bool AuthSession::HandleReconnectChallenge() bool AuthSession::HandleReconnectProof() { TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectProof"); - sAuthReconnectProof_C *reconnectProof = reinterpret_cast(GetReadBuffer()); + sAuthReconnectProof_C *reconnectProof = reinterpret_cast(GetDataBuffer()); if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) return false; -- cgit v1.2.3 From 39d3480172f8a26af1f2ce3961b3ff3ee89f1a97 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 10 Aug 2014 11:48:43 +0200 Subject: Core/Authserver: Fixed writing to invalid memory address --- src/server/authserver/Server/AuthSession.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/server/authserver/Server/AuthSession.cpp') diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index e6a775e93ee..76f8b8c27b0 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -515,10 +515,9 @@ bool AuthSession::HandleLogonProof() ReadData(1); uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C)); ReadData(size); - char* token = reinterpret_cast(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)); - token[size] = '\0'; - unsigned int validToken = TOTP::GenerateToken(_tokenKey.c_str()); - unsigned int incomingToken = atoi(token); + std::string token(reinterpret_cast(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size); + uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str()); + uint32 incomingToken = atoi(token.c_str()); if (validToken != incomingToken) { ByteBuffer packet; -- cgit v1.2.3 From c741d2682a1835b0e9a775d1aba9f795db348450 Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 11 Aug 2014 20:43:07 +0200 Subject: Core/NetworkIO: Prevent queueing more async operations when socket is already closed --- src/server/authserver/Server/AuthSession.cpp | 3 +++ src/server/game/Server/WorldSocket.cpp | 3 +++ src/server/shared/Networking/Socket.h | 31 +++++++++++++++++++++------- 3 files changed, 29 insertions(+), 8 deletions(-) (limited to 'src/server/authserver/Server/AuthSession.cpp') diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 76f8b8c27b0..9931595e860 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -169,6 +169,9 @@ void AuthSession::ReadDataHandler() void AuthSession::AsyncWrite(ByteBuffer& packet) { + if (!IsOpen()) + return; + std::lock_guard guard(_writeLock); bool needsWriteStart = _writeQueue.empty(); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 1b134ecbe91..d2602e83944 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -124,6 +124,9 @@ void WorldSocket::ReadDataHandler() void WorldSocket::AsyncWrite(WorldPacket& packet) { + if (!IsOpen()) + return; + if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort()); diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index b04d24b79cc..c8bd5a1dd81 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -20,7 +20,7 @@ #include "MessageBuffer.h" #include "Log.h" -#include +#include #include #include #include @@ -47,6 +47,18 @@ public: _readHeaderBuffer.Grow(headerSize); } + virtual ~Socket() + { + boost::system::error_code error; + _socket.close(error); + + while (!_writeQueue.empty()) + { + DeletePacket(_writeQueue.front()); + _writeQueue.pop(); + } + } + virtual void Start() = 0; boost::asio::ip::address GetRemoteIpAddress() const @@ -61,6 +73,9 @@ public: void AsyncReadHeader() { + if (!IsOpen()) + return; + _readHeaderBuffer.ResetWritePointer(); _readDataBuffer.Reset(); @@ -69,6 +84,9 @@ public: void AsyncReadData(std::size_t size) { + if (!IsOpen()) + return; + if (!size) { // if this is a packet with 0 length body just invoke handler directly @@ -82,6 +100,9 @@ public: void ReadData(std::size_t size) { + if (!IsOpen()) + return; + boost::system::error_code error; _readDataBuffer.Grow(size); @@ -113,16 +134,10 @@ public: return; boost::system::error_code shutdownError; - _socket.shutdown(boost::asio::socket_base::shutdown_both, shutdownError); + _socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError); if (shutdownError) TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when shutting down socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), shutdownError.value(), shutdownError.message().c_str()); - - boost::system::error_code error; - _socket.close(error); - if (error) - TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when closing socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), - error.value(), error.message().c_str()); } virtual bool IsHeaderReady() const { return _readHeaderBuffer.IsMessageReady(); } -- cgit v1.2.3