|
32 | 32 | #include <boost/asio/ip/address_v6.hpp> |
33 | 33 | #include <boost/asio/ip/v6_only.hpp> |
34 | 34 | #include <cstring> |
| 35 | +#include <openssl/err.h> |
| 36 | +#include <openssl/rand.h> |
35 | 37 | #include <zlib.h> |
36 | 38 |
|
37 | 39 | typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option; |
@@ -146,23 +148,30 @@ void TNetwork::UDPServerMain() { |
146 | 148 | } |
147 | 149 |
|
148 | 150 | if (Client->GetID() == ID) { |
149 | | - // not initialized yet |
150 | | - if (Client->GetUDPAddr() == ip::udp::endpoint {} || !Client->IsUDPConnected()) { |
151 | | - // same IP (just a sanity check) |
152 | | - if (remote_client_ep.address() == Client->GetTCPSock().remote_endpoint().address()) { |
153 | | - Client->SetUDPAddr(remote_client_ep); |
154 | | - Client->SetIsUDPConnected(true); |
155 | | - beammp_debugf("UDP connected for client {}", ID); |
156 | | - } else { |
157 | | - beammp_debugf("Denied initial UDP packet due to IP mismatch"); |
| 151 | + if (Client->GetUDPAddr() == ip::udp::endpoint {} && !Client->IsUDPConnected() && !Client->GetMagic().empty()) { |
| 152 | + if (Data.size() != 66) { |
| 153 | + beammp_debugf("Invalid size for UDP value. IP: {} ID: {}", remote_client_ep.address().to_string(), ID); |
| 154 | + return false; |
| 155 | + } |
| 156 | + |
| 157 | + const std::vector Magic(Data.begin() + 2, Data.end()); |
| 158 | + |
| 159 | + if (Magic != Client->GetMagic()) { |
| 160 | + beammp_debugf("Invalid value for UDP IP: {} ID: {}", remote_client_ep.address().to_string(), ID); |
158 | 161 | return false; |
159 | 162 | } |
| 163 | + |
| 164 | + Client->SetMagic({}); |
| 165 | + Client->SetUDPAddr(remote_client_ep); |
| 166 | + Client->SetIsUDPConnected(true); |
| 167 | + return false; |
160 | 168 | } |
| 169 | + |
161 | 170 | if (Client->GetUDPAddr() == remote_client_ep) { |
162 | 171 | Data.erase(Data.begin(), Data.begin() + 2); |
163 | | - mServer.GlobalParser(ClientPtr, std::move(Data), mPPSMonitor, *this); |
| 172 | + mServer.GlobalParser(ClientPtr, std::move(Data), mPPSMonitor, *this, true); |
164 | 173 | } else { |
165 | | - beammp_debugf("Ignored UDP packet due to remote address mismatch"); |
| 174 | + beammp_debugf("Ignored UDP packet for Client {} due to remote address mismatch. Source: {}, Client: {}", ID, remote_client_ep.address().to_string(), Client->GetUDPAddr().address().to_string()); |
166 | 175 | return false; |
167 | 176 | } |
168 | 177 | } |
@@ -660,7 +669,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) { |
660 | 669 | Client->Disconnect("TCPRcv failed"); |
661 | 670 | break; |
662 | 671 | } |
663 | | - mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this); |
| 672 | + mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false); |
664 | 673 | } |
665 | 674 |
|
666 | 675 | if (QueueSync.joinable()) |
@@ -751,6 +760,18 @@ void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) { |
751 | 760 | SyncResources(*LockedClient); |
752 | 761 | if (LockedClient->IsDisconnected()) |
753 | 762 | return; |
| 763 | + std::vector<unsigned char> buf(64); |
| 764 | + int ret = RAND_bytes(buf.data(), buf.size()); |
| 765 | + if (ret != 1) { |
| 766 | + unsigned long error = ERR_get_error(); |
| 767 | + beammp_errorf("RAND_bytes failed with error code {}", error); |
| 768 | + beammp_assert(ret != 1); |
| 769 | + return; |
| 770 | + } |
| 771 | + |
| 772 | + LockedClient->SetMagic(buf); |
| 773 | + buf.insert(buf.begin(), 'U'); |
| 774 | + (void)Respond(*LockedClient, buf, true); |
754 | 775 | (void)Respond(*LockedClient, StringToVector("M" + Application::Settings.getAsString(Settings::Key::General_Map)), true); // Send the Map on connect |
755 | 776 | beammp_info(LockedClient->GetName() + " : Connected"); |
756 | 777 | LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", "", LockedClient->GetID())); |
|
0 commit comments