diff options
author | Machiavelli <machiavelli.trinity@gmail.com> | 2011-08-01 04:01:10 +0200 |
---|---|---|
committer | Machiavelli <machiavelli.trinity@gmail.com> | 2011-08-01 04:02:08 +0200 |
commit | acc2e88c31b6aa027da4bd90ac8889b45b1b27f7 (patch) | |
tree | 5317959c0d4f518fc7f37dd34f20bf8382832241 /src | |
parent | 67ee5a46c35acfe1ab1b6e715c5c56b1cc73e4f7 (diff) |
Core/RA: Fix RA usage, properly filter out RFC 854 / 855 subnegotiate data
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/worldserver/RemoteAccess/RASocket.cpp | 78 | ||||
-rwxr-xr-x | src/server/worldserver/RemoteAccess/RASocket.h | 1 |
2 files changed, 79 insertions, 0 deletions
diff --git a/src/server/worldserver/RemoteAccess/RASocket.cpp b/src/server/worldserver/RemoteAccess/RASocket.cpp index 4344bfea048..c813c2497f1 100755 --- a/src/server/worldserver/RemoteAccess/RASocket.cpp +++ b/src/server/worldserver/RemoteAccess/RASocket.cpp @@ -257,8 +257,86 @@ int RASocket::authenticate() return 0; } + +int RASocket::subnegotiate() +{ + char buf[1024]; + + ACE_Data_Block db(sizeof (buf), + ACE_Message_Block::MB_DATA, + buf, + 0, + 0, + ACE_Message_Block::DONT_DELETE, + 0); + + ACE_Message_Block message_block(&db, + ACE_Message_Block::DONT_DELETE, + 0); + + const size_t recv_size = message_block.space(); + + const ssize_t n = peer().recv(message_block.wr_ptr(), + recv_size); + + if (n <= 0) + return int(n); + + if (n >= 1024) + { + sLog->outRemote("RASocket::subnegotiate: allocated buffer 1024 bytes was too small for negotiation packet, size: %u", n); + return -1; + } + + buf[n] = '\0'; + + #ifdef _DEBUG + for (uint8 i = 0; i < n; ) + { + uint8 iac = buf[i]; + if (iac == 0xFF) // "Interpret as Command" (IAC) + { + uint8 command = buf[++i]; + std::stringstream ss; + switch (command) + { + case 0xFB: // WILL + ss << "WILL "; + break; + case 0xFC: // WON'T + ss << "WON'T "; + break; + case 0xFD: // DO + ss << "DO "; + break; + case 0xFE: // DON'T + ss << "DON'T "; + break; + default: + return -1; // not allowed + } + + uint8 param = buf[++i]; + ss << uint32(param); + sLog->outRemote(ss.str().c_str()); + } + ++i; + } + #endif + + //! Just send back end of subnegotiation packet + uint8 const reply[2] = {0xFF, 0xF0}; + return peer().send(reply, 2); +} + int RASocket::svc(void) { + if (subnegotiate() == -1) + { + sLog->outRemote("Subnegotiation failed!"); + return -1; + } + if (send("Authentication required\r\n") == -1) return -1; diff --git a/src/server/worldserver/RemoteAccess/RASocket.h b/src/server/worldserver/RemoteAccess/RASocket.h index f55f53f0280..0c626d5840e 100755 --- a/src/server/worldserver/RemoteAccess/RASocket.h +++ b/src/server/worldserver/RemoteAccess/RASocket.h @@ -46,6 +46,7 @@ class RASocket: public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> int recv_line(ACE_Message_Block& buffer); int process_command(const std::string& command); int authenticate(); + int subnegotiate(); //! Used by telnet protocol RFC 854 / 855 int check_access_level(const std::string& user); int check_password(const std::string& user, const std::string& pass); int send(const std::string& line); |