add client address verification

This commit is contained in:
Roman Trapeznikov 2022-07-30 16:18:40 +03:00
parent a015563ea5
commit 22cffa39fe
5 changed files with 46 additions and 1 deletions

View File

@ -452,6 +452,7 @@ auto ConnectionSet::UDPConnectionPacket(const std::vector<uint8_t>& data_in,
if (data_size == 2) {
// Client is telling us (host) that it wants to disconnect.
uint8_t client_id = data[1];
if (!VerifyClientAddr(client_id, addr)) break;
// Wipe that client out (if it still exists).
PushClientDisconnectedCall(client_id);
@ -495,6 +496,8 @@ auto ConnectionSet::UDPConnectionPacket(const std::vector<uint8_t>& data_in,
case BA_PACKET_CLIENT_GAMEPACKET_COMPRESSED: {
if (data_size > 2) {
uint8_t client_id = data[1];
if (!VerifyClientAddr(client_id, addr)) break;
auto i = connections_to_clients_.find(client_id);
if (i != connections_to_clients_.end()) {
// FIXME: could change HandleGamePacketCompressed to avoid this
@ -685,6 +688,25 @@ auto ConnectionSet::UDPConnectionPacket(const std::vector<uint8_t>& data_in,
}
}
auto ConnectionSet::VerifyClientAddr(uint8_t client_id, const SockAddr& addr)
-> bool {
auto connection_to_client = connections_to_clients_.find(client_id);
if (connection_to_client != connections_to_clients_.end()) {
auto connection_to_client_udp = connection_to_client->second->GetAsUDP();
if (connection_to_client_udp == nullptr) {
// We can't get client's SockAddr in that case.
return true;
}
if (addr == connection_to_client_udp->addr()) {
return true;
}
return false;
}
return false;
}
void ConnectionSet::SetClientInfoFromMasterServer(
const std::string& client_token, PyObject* info_obj) {
// NOLINTNEXTLINE (python doing bitwise math on signed int)

View File

@ -99,6 +99,8 @@ class ConnectionSet {
auto PushClientDisconnectedCall(int id) -> void;
private:
auto VerifyClientAddr(uint8_t client_id, const SockAddr& addr) -> bool;
// Try to minimize the chance a garbage packet will have this id.
int next_connection_to_client_id_{113};
std::unordered_map<int, Object::Ref<ConnectionToClient> >

View File

@ -49,7 +49,6 @@ class ConnectionToClient : public Connection {
next_kick_vote_allow_time_ = val;
}
auto next_kick_vote_allow_time() const { return next_kick_vote_allow_time_; }
auto public_device_id() const { return public_device_id_; }
// Returns a spec for this client that incorporates their player names
// or their peer name if they have no players.

View File

@ -9,6 +9,7 @@
#include "ballistica/game/connection/connection_to_client.h"
#include "ballistica/networking/networking.h"
#include "ballistica/networking/sockaddr.h"
namespace ballistica {
@ -27,6 +28,7 @@ class ConnectionToClientUDP : public ConnectionToClient {
void SendDisconnectRequest();
auto SendGamePacketCompressed(const std::vector<uint8_t>& data)
-> void override;
auto addr() { return *addr_; }
private:
uint8_t request_id_;

View File

@ -45,6 +45,26 @@ class SockAddr {
throw Exception();
}
}
auto operator==(const SockAddr& other) const -> bool {
if (addr_.ss_family != other.addr_.ss_family) return false;
if (addr_.ss_family == AF_INET) {
return (reinterpret_cast<const sockaddr_in&>(addr_).sin_addr.s_addr
== reinterpret_cast<const sockaddr_in&>(other.addr_)
.sin_addr.s_addr)
&& (reinterpret_cast<const sockaddr_in&>(addr_).sin_port
== reinterpret_cast<const sockaddr_in&>(other.addr_).sin_port);
}
if (addr_.ss_family == AF_INET6) {
return !memcmp(&(reinterpret_cast<const sockaddr_in6&>(addr_).sin6_addr),
&(reinterpret_cast<const sockaddr_in6&>(other.addr_)
.sin6_addr),
sizeof(in6_addr))
&& (reinterpret_cast<const sockaddr_in6&>(addr_).sin6_port
== reinterpret_cast<const sockaddr_in6&>(other.addr_)
.sin6_port);
}
throw Exception();
}
private:
sockaddr_storage addr_{};