Don't authenticate loopback
This commit is contained in:
parent
9e9967b9d1
commit
4fc7de502a
@ -63,86 +63,93 @@ namespace Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
if (address.IsLoopback()
|
||||||
// Simply connect, if we're in debug mode, we ignore all security checks
|
// Simply connect, if we're in debug mode, we ignore all security checks
|
||||||
if (!connectData.infostring().empty())
|
#ifdef DEBUG
|
||||||
|
|| true
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Game::SV_Cmd_EndTokenizedString();
|
if (!connectData.infostring().empty())
|
||||||
Game::SV_Cmd_TokenizeString(connectData.infostring().data());
|
{
|
||||||
Game::SV_DirectConnect(*address.Get());
|
Game::SV_Cmd_EndTokenizedString();
|
||||||
|
Game::SV_Cmd_TokenizeString(connectData.infostring().data());
|
||||||
|
Game::SV_DirectConnect(*address.Get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nInvalid infostring data!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Network::Send(address, "error\nInvalid infostring data!");
|
// Validate proto data
|
||||||
|
if (connectData.signature().empty() || connectData.publickey().empty() || connectData.token().empty() || connectData.infostring().empty())
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nInvalid connect data!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup new cmd params
|
||||||
|
Game::SV_Cmd_EndTokenizedString();
|
||||||
|
Game::SV_Cmd_TokenizeString(connectData.infostring().data());
|
||||||
|
|
||||||
|
// Access the params
|
||||||
|
Command::Params params(true);
|
||||||
|
|
||||||
|
// Ensure there are enough params
|
||||||
|
if (params.Length() < 3)
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nInvalid connect string!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the infostring
|
||||||
|
Utils::InfoString infostr(params[2]);
|
||||||
|
|
||||||
|
// Read the required data
|
||||||
|
std::string steamId = infostr.Get("xuid");
|
||||||
|
std::string challenge = infostr.Get("challenge");
|
||||||
|
|
||||||
|
if (steamId.empty() || challenge.empty())
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nInvalid connect data!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the id
|
||||||
|
unsigned __int64 xuid = strtoull(steamId.data(), nullptr, 16);
|
||||||
|
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & xuid);
|
||||||
|
|
||||||
|
if ((xuid & 0xFFFFFFFF00000000) != 0x110000100000000 || id != (Utils::Cryptography::JenkinsOneAtATime::Compute(connectData.publickey()) & ~0x80000000))
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nXUID doesn't match the certificate!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
Utils::Cryptography::ECC::Key key;
|
||||||
|
key.Set(connectData.publickey());
|
||||||
|
|
||||||
|
if (!key.IsValid() || !Utils::Cryptography::ECC::VerifyMessage(key, challenge, connectData.signature()))
|
||||||
|
{
|
||||||
|
Network::Send(address, "error\nChallenge signature was invalid!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the security level
|
||||||
|
uint32_t ourLevel = static_cast<uint32_t>(Dvar::Var("sv_securityLevel").Get<int>());
|
||||||
|
uint32_t userLevel = Auth::GetZeroBits(connectData.token(), connectData.publickey());
|
||||||
|
|
||||||
|
if (userLevel < ourLevel)
|
||||||
|
{
|
||||||
|
Network::Send(address, fmt::sprintf("error\nYour security level (%d) is lower than the server's security level (%d)", userLevel, ourLevel));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::Print("Verified XUID %llX (%d) from %s\n", xuid, userLevel, address.GetCString());
|
||||||
|
Game::SV_DirectConnect(*address.Get());
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// Validate proto data
|
|
||||||
if (connectData.signature().empty() || connectData.publickey().empty() || connectData.token().empty() || connectData.infostring().empty())
|
|
||||||
{
|
|
||||||
Network::Send(address, "error\nInvalid connect data!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup new cmd params
|
|
||||||
Game::SV_Cmd_EndTokenizedString();
|
|
||||||
Game::SV_Cmd_TokenizeString(connectData.infostring().data());
|
|
||||||
|
|
||||||
// Access the params
|
|
||||||
Command::Params params(true);
|
|
||||||
|
|
||||||
// Ensure there are enough params
|
|
||||||
if (params.Length() < 3)
|
|
||||||
{
|
|
||||||
Network::Send(address, "error\nInvalid connect string!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the infostring
|
|
||||||
Utils::InfoString infostr(params[2]);
|
|
||||||
|
|
||||||
// Read the required data
|
|
||||||
std::string steamId = infostr.Get("xuid");
|
|
||||||
std::string challenge = infostr.Get("challenge");
|
|
||||||
|
|
||||||
if (steamId.empty() || challenge.empty())
|
|
||||||
{
|
|
||||||
Network::Send(address, "error\nInvalid connect data!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the id
|
|
||||||
unsigned __int64 xuid = strtoull(steamId.data(), nullptr, 16);
|
|
||||||
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & xuid);
|
|
||||||
|
|
||||||
if ((xuid & 0xFFFFFFFF00000000) != 0x110000100000000 || id != (Utils::Cryptography::JenkinsOneAtATime::Compute(connectData.publickey()) & ~0x80000000))
|
|
||||||
{
|
|
||||||
Network::Send(address, "error\nXUID doesn't match the certificate!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the signature
|
|
||||||
Utils::Cryptography::ECC::Key key;
|
|
||||||
key.Set(connectData.publickey());
|
|
||||||
|
|
||||||
if (!key.IsValid() || !Utils::Cryptography::ECC::VerifyMessage(key, challenge, connectData.signature()))
|
|
||||||
{
|
|
||||||
Network::Send(address, "error\nChallenge signature was invalid!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the security level
|
|
||||||
uint32_t ourLevel = static_cast<uint32_t>(Dvar::Var("sv_securityLevel").Get<int>());
|
|
||||||
uint32_t userLevel = Auth::GetZeroBits(connectData.token(), connectData.publickey());
|
|
||||||
|
|
||||||
if (userLevel < ourLevel)
|
|
||||||
{
|
|
||||||
Network::Send(address, fmt::sprintf("error\nYour security level (%d) is lower than the server's security level (%d)", userLevel, ourLevel));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::Print("Verified XUID %llX (%d) from %s\n", xuid, userLevel, address.GetCString());
|
|
||||||
Game::SV_DirectConnect(*address.Get());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __declspec(naked) Auth::DirectConnectStub()
|
void __declspec(naked) Auth::DirectConnectStub()
|
||||||
|
@ -107,6 +107,10 @@ namespace Components
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool Network::Address::IsLoopback()
|
||||||
|
{
|
||||||
|
return Game::NET_IsLocalAddress(this->address);
|
||||||
|
}
|
||||||
bool Network::Address::IsValid()
|
bool Network::Address::IsValid()
|
||||||
{
|
{
|
||||||
return (this->GetType() != Game::netadrtype_t::NA_BAD);
|
return (this->GetType() != Game::netadrtype_t::NA_BAD);
|
||||||
|
@ -1,91 +1,92 @@
|
|||||||
#define NETWORK_MAX_PACKETS_PER_SECOND 100'000
|
#define NETWORK_MAX_PACKETS_PER_SECOND 100'000
|
||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
class Network : public Component
|
class Network : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Address
|
class Address
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Address() { this->SetType(Game::netadrtype_t::NA_BAD); };
|
Address() { this->SetType(Game::netadrtype_t::NA_BAD); };
|
||||||
Address(std::string addrString);
|
Address(std::string addrString);
|
||||||
Address(sockaddr* addr);
|
Address(sockaddr* addr);
|
||||||
Address(sockaddr addr) : Address(&addr) {}
|
Address(sockaddr addr) : Address(&addr) {}
|
||||||
Address(sockaddr_in addr) : Address(&addr) {}
|
Address(sockaddr_in addr) : Address(&addr) {}
|
||||||
Address(sockaddr_in* addr) : Address(reinterpret_cast<sockaddr*>(addr)) {}
|
Address(sockaddr_in* addr) : Address(reinterpret_cast<sockaddr*>(addr)) {}
|
||||||
Address(Game::netadr_t addr) : address(addr) {}
|
Address(Game::netadr_t addr) : address(addr) {}
|
||||||
Address(Game::netadr_t* addr) : Address(*addr) {}
|
Address(Game::netadr_t* addr) : Address(*addr) {}
|
||||||
Address(const Address& obj) : address(obj.address) {};
|
Address(const Address& obj) : address(obj.address) {};
|
||||||
Address(const Proto::Network::Address& addr) { this->Deserialize(addr); };
|
Address(const Proto::Network::Address& addr) { this->Deserialize(addr); };
|
||||||
bool operator!=(const Address &obj) { return !(*this == obj); };
|
bool operator!=(const Address &obj) { return !(*this == obj); };
|
||||||
bool operator==(const Address &obj);
|
bool operator==(const Address &obj);
|
||||||
|
|
||||||
void SetPort(unsigned short port);
|
void SetPort(unsigned short port);
|
||||||
unsigned short GetPort();
|
unsigned short GetPort();
|
||||||
|
|
||||||
void SetIP(DWORD ip);
|
void SetIP(DWORD ip);
|
||||||
void SetIP(Game::netIP_t ip);
|
void SetIP(Game::netIP_t ip);
|
||||||
Game::netIP_t GetIP();
|
Game::netIP_t GetIP();
|
||||||
|
|
||||||
void SetType(Game::netadrtype_t type);
|
void SetType(Game::netadrtype_t type);
|
||||||
Game::netadrtype_t GetType();
|
Game::netadrtype_t GetType();
|
||||||
|
|
||||||
sockaddr GetSockAddr();
|
sockaddr GetSockAddr();
|
||||||
void ToSockAddr(sockaddr* addr);
|
void ToSockAddr(sockaddr* addr);
|
||||||
void ToSockAddr(sockaddr_in* addr);
|
void ToSockAddr(sockaddr_in* addr);
|
||||||
Game::netadr_t* Get();
|
Game::netadr_t* Get();
|
||||||
const char* GetCString();
|
const char* GetCString();
|
||||||
std::string GetString();
|
std::string GetString();
|
||||||
|
|
||||||
bool IsLocal();
|
bool IsLocal();
|
||||||
bool IsSelf();
|
bool IsSelf();
|
||||||
bool IsValid();
|
bool IsValid();
|
||||||
|
bool IsLoopback();
|
||||||
void Serialize(Proto::Network::Address* protoAddress);
|
|
||||||
void Deserialize(const Proto::Network::Address& protoAddress);
|
void Serialize(Proto::Network::Address* protoAddress);
|
||||||
|
void Deserialize(const Proto::Network::Address& protoAddress);
|
||||||
private:
|
|
||||||
Game::netadr_t address;
|
private:
|
||||||
};
|
Game::netadr_t address;
|
||||||
|
};
|
||||||
typedef void(Callback)(Address address, std::string data);
|
|
||||||
typedef void(CallbackRaw)();
|
typedef void(Callback)(Address address, std::string data);
|
||||||
|
typedef void(CallbackRaw)();
|
||||||
Network();
|
|
||||||
~Network();
|
Network();
|
||||||
const char* GetName() { return "Network"; };
|
~Network();
|
||||||
|
const char* GetName() { return "Network"; };
|
||||||
static void Handle(std::string packet, Callback* callback);
|
|
||||||
static void OnStart(CallbackRaw* callback);
|
static void Handle(std::string packet, Callback* callback);
|
||||||
|
static void OnStart(CallbackRaw* callback);
|
||||||
// Send quake-styled binary data
|
|
||||||
static void Send(Address target, std::string data);
|
// Send quake-styled binary data
|
||||||
static void Send(Game::netsrc_t type, Address target, std::string data);
|
static void Send(Address target, std::string data);
|
||||||
|
static void Send(Game::netsrc_t type, Address target, std::string data);
|
||||||
// Allows sending raw data without quake header
|
|
||||||
static void SendRaw(Address target, std::string data);
|
// Allows sending raw data without quake header
|
||||||
static void SendRaw(Game::netsrc_t type, Address target, std::string data);
|
static void SendRaw(Address target, std::string data);
|
||||||
|
static void SendRaw(Game::netsrc_t type, Address target, std::string data);
|
||||||
// Send quake-style command using binary data
|
|
||||||
static void SendCommand(Address target, std::string command, std::string data = "");
|
// Send quake-style command using binary data
|
||||||
static void SendCommand(Game::netsrc_t type, Address target, std::string command, std::string data = "");
|
static void SendCommand(Address target, std::string command, std::string data = "");
|
||||||
|
static void SendCommand(Game::netsrc_t type, Address target, std::string command, std::string data = "");
|
||||||
static void Broadcast(unsigned short port, std::string data);
|
|
||||||
static void BroadcastRange(unsigned int min, unsigned int max, std::string data);
|
static void Broadcast(unsigned short port, std::string data);
|
||||||
static void BroadcastAll(std::string data);
|
static void BroadcastRange(unsigned int min, unsigned int max, std::string data);
|
||||||
|
static void BroadcastAll(std::string data);
|
||||||
private:
|
|
||||||
static SOCKET TcpSocket;
|
private:
|
||||||
static std::string SelectedPacket;
|
static SOCKET TcpSocket;
|
||||||
static wink::signal<wink::slot<CallbackRaw>> StartupSignal;
|
static std::string SelectedPacket;
|
||||||
static std::map<std::string, wink::slot<Callback>> PacketHandlers;
|
static wink::signal<wink::slot<CallbackRaw>> StartupSignal;
|
||||||
|
static std::map<std::string, wink::slot<Callback>> PacketHandlers;
|
||||||
static int PacketInterceptionHandler(const char* packet);
|
|
||||||
static void DeployPacket(Game::netadr_t* from, Game::msg_t* msg);
|
static int PacketInterceptionHandler(const char* packet);
|
||||||
static void DeployPacketStub();
|
static void DeployPacket(Game::netadr_t* from, Game::msg_t* msg);
|
||||||
|
static void DeployPacketStub();
|
||||||
static void NetworkStart();
|
|
||||||
static void NetworkStartStub();
|
static void NetworkStart();
|
||||||
};
|
static void NetworkStartStub();
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user