Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
option(RAKNET_BUILD_FOR_CLIENT "Build RakNet without server-side functionality" NO)

if(WIN32)
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
Expand Down Expand Up @@ -50,7 +52,11 @@ target_include_directories(raknet
)

if (WIN32)
target_link_libraries(raknet Ws2_32 OMP-SDK)
target_link_libraries(raknet Ws2_32)
endif()

if (RAKNET_BUILD_FOR_CLIENT)
target_compile_definitions(raknet PUBLIC -DBUILD_FOR_CLIENT)
else()
target_link_libraries(raknet OMP-SDK)
endif()
3 changes: 3 additions & 0 deletions Include/raknet/NetworkTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@

#include "RakNetDefines.h"
#include "Export.h"
#ifndef BUILD_FOR_CLIENT
#include "../../SDK/include/types.hpp"
#endif
#include <functional>

/// Forward declaration
namespace RakNet
Expand Down
10 changes: 9 additions & 1 deletion Include/raknet/RakPeer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#ifndef __RAK_PEER_H
#define __RAK_PEER_H

#include <unordered_map>

#include "Export.h"
#include "RakPeerInterface.h"
#include "ReliabilityLayer.h"
Expand Down Expand Up @@ -508,7 +510,9 @@ namespace RakNet
bool setAESKey; /// true if security is enabled.
RPCMap rpcMap; /// Mapping of RPC calls to single byte integers to save transmission bandwidth.
enum ConnectMode {NO_ACTION, DISCONNECT_ASAP, DISCONNECT_ASAP_SILENTLY, DISCONNECT_ON_NO_ACK, REQUESTED_CONNECTION, HANDLING_CONNECTION_REQUEST, UNVERIFIED_SENDER, SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET, CONNECTED} connectMode;
#ifndef BUILD_FOR_CLIENT
SAMPRakNet::RemoteSystemData sampData;
#endif
bool isLogon;
};

Expand All @@ -529,7 +533,9 @@ namespace RakNet
friend void* UpdateNetworkLoop( void* arguments );
#endif

#ifndef BUILD_FOR_CLIENT
friend bool __stdcall ProcessBan(RakPeer* rakPeer, PlayerID playerId, const char* data, const int length);
#endif

// This is done to provide custom RPC handling when in a blocking RPC
Packet* ReceiveIgnoreRPC( void );
Expand All @@ -543,11 +549,13 @@ namespace RakNet
/// \return 0 if none
RemoteSystemStruct *GetRemoteSystemFromPlayerID( const PlayerID playerID, bool calledFromNetworkThread, bool onlyActive) const;
///Parse out a connection request packet
#ifndef BUILD_FOR_CLIENT
void ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, PlayerID playerId, const char *data, int byteSize);
bool ParseConnectionAuthPacket(RakPeer::RemoteSystemStruct* remoteSystem, PlayerID playerId, unsigned char* data, int byteSize);
///When we get a connection request from an ip / port, accept it unless full
void OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, unsigned char *AESKey, bool setAESKey );
void AcceptConnectionRequest(RakPeer::RemoteSystemStruct* remoteSystem);
#endif
///Send a reliable disconnect packet to this player and disconnect them when it is delivered
void NotifyAndFlagForDisconnect( const PlayerID playerId, bool performImmediate, unsigned char orderingChannel );
///Returns how many remote systems initiated a connection to us
Expand Down Expand Up @@ -602,7 +610,7 @@ namespace RakNet

/// open.mp addition:
/// Let's create an array of player indexes using PlayerIDs
FlatHashMap<PlayerID, int> playerIndexes;
std::unordered_map<PlayerID, int> playerIndexes;

/// This is an array of pointers to RemoteSystemStruct
/// This allows us to preallocate the list when starting, so we don't have to allocate or delete at runtime.
Expand Down
2 changes: 2 additions & 0 deletions Include/raknet/RakServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,10 @@ namespace RakNet
/// \sa RakNetStatistics.h
RakNetStatisticsStruct * GetStatistics( const PlayerID playerId ) override;

#ifndef BUILD_FOR_CLIENT
/// Return the SAMPRakNet RemoteSystemData for a player ID
virtual SAMPRakNet::RemoteSystemData GetSAMPDataFromPlayerID(const PlayerID playerId) override;
#endif

/// Get Remote System data for a player from their ID
virtual RakPeer::RemoteSystemStruct* GetRemoteSystemFromPlayerID(const PlayerID playerId) override;
Expand Down
2 changes: 2 additions & 0 deletions Include/raknet/RakServerInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,10 @@ namespace RakNet
/// \sa RakNetStatistics.h
virtual RakNetStatisticsStruct * GetStatistics( const PlayerID playerId )=0;

#ifndef BUILD_FOR_CLIENT
/// Get SAMP data for a player from their ID
virtual SAMPRakNet::RemoteSystemData GetSAMPDataFromPlayerID(const PlayerID playerId) = 0;
#endif

/// Get Remote System data for a player from their ID
virtual RakPeer::RemoteSystemStruct* GetRemoteSystemFromPlayerID(const PlayerID playerId) = 0;
Expand Down
109 changes: 108 additions & 1 deletion SAMPRakNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
#include <PacketEnumerations.h>

uint8_t SAMPRakNet::buffer_[MAXIMUM_MTU_SIZE];
#ifdef BUILD_FOR_CLIENT
char SAMPRakNet::authkeyBuffer_[AUTHKEY_RESPONSE_LEN];
bool SAMPRakNet::connectAsNpc_ = false;
#endif
#ifndef BUILD_FOR_CLIENT
uint32_t SAMPRakNet::token_;
#endif
uint16_t SAMPRakNet::portNumber = 7777;
#ifndef BUILD_FOR_CLIENT
Query* SAMPRakNet::query_ = nullptr;
#endif
unsigned int SAMPRakNet::timeout_ = 10000;
#ifndef BUILD_FOR_CLIENT
unsigned int SAMPRakNet::minConnectionTime_ = 0;
unsigned int SAMPRakNet::messagesLimit_ = 500;
unsigned int SAMPRakNet::messageHoleLimit_ = 3000;
Expand All @@ -22,6 +31,7 @@ bool SAMPRakNet::logCookies_ = false;
ICore* SAMPRakNet::core_ = nullptr;
FlatHashSet<uint32_t> SAMPRakNet::incomingConnections_;
RakNet::RakNetTime SAMPRakNet::gracePeriod_ = 0;
#endif

uint16_t
SAMPRakNet::
Expand Down Expand Up @@ -591,15 +601,111 @@ SAMPRakNet::
// Alternate the mask every byte.
cur = (uint8_t)src[i];
checksum ^= cur & 0xAA;
cur = key[cur];
if (i & 1)
cur ^= port;
cur = key[cur];
buffer_[i + 1] = cur;
}
buffer_[0] = checksum;
return buffer_;
}

#ifdef BUILD_FOR_CLIENT
inline uint8_t transformAuthSha1(const uint8_t value, const uint8_t xorValue)
{
static const uint8_t authHashTransformTable[] = {
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
0x08, 0x06, 0x00, 0x00, 0x00, 0xE4, 0xB5, 0xB7, 0x0A, 0x00, 0x00, 0x00,
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B,
0x13, 0x01, 0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41,
0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8E, 0x7C, 0xFB, 0x51, 0x93, 0x00, 0x00,
0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x25, 0x00, 0x00,
0x80, 0x83, 0x00, 0x00, 0xF9, 0xFF, 0x00, 0x00, 0x80, 0xE9, 0x00, 0x00,
0x75, 0x30, 0x00, 0x00
};

uint8_t result = value;

for (const uint8_t &entry : authHashTransformTable) {
result = result ^ entry ^ xorValue;
}

return result;
}

inline const char * uint8ToHex(const uint8_t num) {
static uint8_t buffer[2];

buffer[0] = (num >> 4) & 0xF;
buffer[1] = num & 0xF;

for (uint8_t &entry : buffer) {
uint8_t result = entry + '0';

if (result > '9')
result = entry + '7';

entry = result;
}

return (char*)buffer;
}

char*
SAMPRakNet::
PrepareAuthkeyResponse(const char* initialKey)
{
static const uint8_t code_from_CAnimManager_AddAnimation[] =
{
0xFF, 0x25, 0x34, 0x39, // gta_sa.exe + 0x4D3AA0
0x4D, 0x00, 0x90, 0x90, // gta_sa.exe + 0x4D3AA4
0x90, 0x90, 0x56, 0x57, // gta_sa.exe + 0x4D3AAC
0x50, 0x8B, 0x44, 0x24, // gta_sa.exe + 0x4D3AA8
0x14, 0x8D, 0x0C, 0x80 // gta_sa.exe + 0x4D3AB0
};

RakNet::CSHA1 sha1;
sha1.Update( (unsigned char*) initialKey, strlen(initialKey) );
sha1.Final();

auto sha1_finalized = (uint32_t*)sha1.GetHash();

uint32_t sha1_digits[5];
for (int i = 0; i < 5; i++) {
uint32_t digit = sha1_finalized[i];
// Flipping bytes order
digit = ((digit & 0xFF) << 24) | ((digit & 0xFF00) << 8) |
((digit >> 8) & 0xFF00) | ((digit >> 24) & 0xFF);
sha1_digits[i] = digit;
}

auto sha1_digits_u8 = (uint8_t*)&sha1_digits;

static const uint8_t xorValues[] = {
0x2F, 0x45, 0x6F, 0xDB
};

for (int i = 0; i < 20; i++) {
uint8_t xorVal = xorValues[i / 5];
sha1_digits_u8[i] = transformAuthSha1(sha1_digits_u8[i], xorVal);
sha1_digits_u8[i] ^= code_from_CAnimManager_AddAnimation[i];
}

for (int i = 0; i < 40;) {
uint8_t hash = sha1_digits_u8[i / 2];
const char* hashHex = uint8ToHex(hash);
authkeyBuffer_[i] = hashHex[0];
i++;
authkeyBuffer_[i] = hashHex[1];
i++;
}

return authkeyBuffer_;
}
#endif

#ifndef BUILD_FOR_CLIENT
void SAMPRakNet::
HandleQuery(SOCKET instance, int outsize, const sockaddr_in& client, char const* buf, int insize)
{
Expand Down Expand Up @@ -967,3 +1073,4 @@ bool SAMPRakNet::OnConnectionRequest(

return true;
}
#endif
33 changes: 31 additions & 2 deletions SAMPRakNet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ typedef int SOCKET;

#define MAX_AUTH_RESPONSE_LEN (64)

#ifdef BUILD_FOR_CLIENT
#define AUTHKEY_RESPONSE_LEN (40)
#endif

#ifndef BUILD_FOR_CLIENT
#include "../../Server/Components/LegacyNetwork/Query/query.hpp"
#endif

#include "Include/raknet/NetworkTypes.h"
#include "Include/raknet/GetTime.h"
Expand All @@ -33,11 +39,10 @@ typedef int SOCKET;

#define LOCALHOST (0x0100007fu)

#include <shared_mutex>

class SAMPRakNet
{
public:
#ifndef BUILD_FOR_CLIENT
enum AuthType {
AuthType_Invalid,
AuthType_Player,
Expand All @@ -57,13 +62,19 @@ class SAMPRakNet
core_ = core;
srand(time(nullptr));
}
#endif

static uint8_t * Decrypt(uint8_t const * src, int len);
static uint8_t * Encrypt(uint8_t const * src, int len);

static uint16_t GetPort();
static void SetPort(uint16_t value);

#ifdef BUILD_FOR_CLIENT
static char * PrepareAuthkeyResponse(const char* initialKey);
#endif

#ifndef BUILD_FOR_CLIENT
static uint32_t GetToken() { return token_; }
static void SeedToken() { token_ = rand(); }

Expand All @@ -74,10 +85,17 @@ class SAMPRakNet

static void SeedCookie();
static uint16_t GetCookie(unsigned int address);
#endif

static void SetTimeout(unsigned int timeout) { timeout_ = timeout; }
static unsigned int GetTimeout() { return timeout_; }

#ifdef BUILD_FOR_CLIENT
static void SetConnectionAsNpc(bool enabled) { connectAsNpc_ = enabled; }
static bool ShouldConnectAsNpc() { return connectAsNpc_; }
#endif

#ifndef BUILD_FOR_CLIENT
static void SetQuery(Query* query) { query_ = query; }

static void SetLogCookies(bool log) { logCookies_ = log; }
Expand Down Expand Up @@ -123,13 +141,23 @@ class SAMPRakNet
RakNet::RakNetTime& minConnectionTick,
RakNet::RakNetTime& minConnectionLogTick
);
#endif

private:
static uint8_t buffer_[MAXIMUM_MTU_SIZE];
#ifdef BUILD_FOR_CLIENT
static char authkeyBuffer_[AUTHKEY_RESPONSE_LEN];
static bool connectAsNpc_;
#endif
#ifndef BUILD_FOR_CLIENT
static uint32_t token_;
#endif
static uint16_t portNumber;
#ifndef BUILD_FOR_CLIENT
static Query *query_;
#endif
static unsigned int timeout_;
#ifndef BUILD_FOR_CLIENT
static bool logCookies_;
static unsigned int minConnectionTime_;
static unsigned int messagesLimit_;
Expand All @@ -139,4 +167,5 @@ class SAMPRakNet
static ICore* core_;
static FlatHashSet<uint32_t> incomingConnections_;
static RakNet::RakNetTime gracePeriod_;
#endif
};
Loading