From 33683e04c65ec118595d310fd587a84fb38272b7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 5 Sep 2021 17:56:16 +0100 Subject: [PATCH] Improve connection challenge further --- source/netfilter/baseserver.h | 2 +- source/netfilter/core.cpp | 51 ++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/source/netfilter/baseserver.h b/source/netfilter/baseserver.h index 2e90b6d..5140ecc 100644 --- a/source/netfilter/baseserver.h +++ b/source/netfilter/baseserver.h @@ -27,7 +27,7 @@ enum server_state_t }; // time a challenge nonce is valid for, in seconds -#define CHALLENGE_NONCE_LIFETIME 6.0f +#define CHALLENGE_NONCE_LIFETIME 6 class CBaseServer : public IServer { diff --git a/source/netfilter/core.cpp b/source/netfilter/core.cpp index 37ebe92..3bd2892 100644 --- a/source/netfilter/core.cpp +++ b/source/netfilter/core.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #if defined SYSTEM_WINDOWS @@ -217,6 +218,8 @@ namespace netfilter static constexpr int32_t PROTOCOL_STEAM = 0x03; // Steam certificates static constexpr int32_t PROTOCOL_LASTVALID = 0x03; // Last valid protocol + static constexpr int32_t MAX_RANDOM_RANGE = 0x7FFFFFFFUL; + inline const char *IPToString( const in_addr &addr ) { static char buffer[16] = { }; @@ -914,8 +917,6 @@ namespace netfilter public: virtual bool CheckChallengeNr( netadr_t &adr, int nChallengeValue ) { - TargetClass *self = This( ); - // See if the challenge is valid // Don't care if it is a local address. if( adr.IsLoopback( ) ) @@ -925,9 +926,12 @@ namespace netfilter if( IsX360( ) ) return true; - uint64 challenge = ( static_cast( adr.GetIPNetworkByteOrder( ) ) << 32 ) + self->m_CurrentRandomNonce; + UpdateChallengeIfNeeded( ); + + m_challenge[4] = adr.GetIPNetworkByteOrder( ); + CSHA1 hasher; - hasher.Update( reinterpret_cast( &challenge ), sizeof( challenge ) ); + hasher.Update( reinterpret_cast( &m_challenge[0] ), sizeof( uint32_t ) * m_challenge.size( ) ); hasher.Final( ); SHADigest_t hash = { 0 }; hasher.GetHash( hash ); @@ -935,10 +939,10 @@ namespace netfilter return true; // try with the old random nonce - challenge &= 0xffffffff00000000ull; - challenge += self->m_LastRandomNonce; + m_previous_challenge[4] = adr.GetIPNetworkByteOrder( ); + hasher.Reset( ); - hasher.Update( reinterpret_cast( &challenge ), sizeof( challenge ) ); + hasher.Update( reinterpret_cast( &m_previous_challenge[0] ), sizeof( uint32_t ) * m_previous_challenge.size( ) ); hasher.Final( ); hasher.GetHash( hash ); if( reinterpret_cast( hash )[0] == nChallengeValue ) @@ -949,19 +953,46 @@ namespace netfilter virtual int GetChallengeNr( netadr_t &adr ) { - TargetClass *self = This( ); - uint64 challenge = ( static_cast( adr.GetIPNetworkByteOrder( ) ) << 32 ) + self->m_CurrentRandomNonce; + UpdateChallengeIfNeeded( ); + + m_challenge[4] = adr.GetIPNetworkByteOrder( ); + CSHA1 hasher; - hasher.Update( reinterpret_cast( &challenge ), sizeof( challenge ) ); + hasher.Update( reinterpret_cast( &m_challenge[0] ), sizeof( uint32_t ) * m_challenge.size( ) ); hasher.Final( ); SHADigest_t hash = { 0 }; hasher.GetHash( hash ); return reinterpret_cast( hash )[0]; } + void UpdateChallengeIfNeeded( ) + { + const double current_time = Plat_FloatTime( ); + if( m_challenge_gen_time >= 0 && current_time < m_challenge_gen_time + CHALLENGE_NONCE_LIFETIME ) + return; + + m_challenge_gen_time = current_time; + m_previous_challenge.swap( m_challenge ); + + // RandomInt maps a uniform distribution on the interval [0,INT_MAX]. + // RandomInt will always return the minimum value if the difference in min and max is greater than or equal to INT_MAX. + m_challenge[0] = static_cast( RandomInt( 0, MAX_RANDOM_RANGE ) ); + m_challenge[1] = static_cast( RandomInt( 0, MAX_RANDOM_RANGE ) ); + m_challenge[2] = static_cast( RandomInt( 0, MAX_RANDOM_RANGE ) ); + m_challenge[3] = static_cast( RandomInt( 0, MAX_RANDOM_RANGE ) ); + } + + static double m_challenge_gen_time; + static std::array m_previous_challenge; + static std::array m_challenge; + static CBaseServerProxy Singleton; }; + double CBaseServerProxy::m_challenge_gen_time = -1; + std::array CBaseServerProxy::m_previous_challenge; + std::array CBaseServerProxy::m_challenge; + CBaseServerProxy CBaseServerProxy::Singleton; void Initialize( GarrysMod::Lua::ILuaBase *LUA )