2626#include < cstring>
2727#include < queue>
2828#include < string>
29+ #include < array>
2930
3031#if defined SYSTEM_WINDOWS
3132
@@ -217,6 +218,8 @@ namespace netfilter
217218 static constexpr int32_t PROTOCOL_STEAM = 0x03 ; // Steam certificates
218219 static constexpr int32_t PROTOCOL_LASTVALID = 0x03 ; // Last valid protocol
219220
221+ static constexpr int32_t MAX_RANDOM_RANGE = 0x7FFFFFFFUL ;
222+
220223 inline const char *IPToString ( const in_addr &addr )
221224 {
222225 static char buffer[16 ] = { };
@@ -914,8 +917,6 @@ namespace netfilter
914917 public:
915918 virtual bool CheckChallengeNr ( netadr_t &adr, int nChallengeValue )
916919 {
917- TargetClass *self = This ( );
918-
919920 // See if the challenge is valid
920921 // Don't care if it is a local address.
921922 if ( adr.IsLoopback ( ) )
@@ -925,20 +926,23 @@ namespace netfilter
925926 if ( IsX360 ( ) )
926927 return true ;
927928
928- uint64 challenge = ( static_cast <uint64>( adr.GetIPNetworkByteOrder ( ) ) << 32 ) + self->m_CurrentRandomNonce ;
929+ UpdateChallengeIfNeeded ( );
930+
931+ m_challenge[4 ] = adr.GetIPNetworkByteOrder ( );
932+
929933 CSHA1 hasher;
930- hasher.Update ( reinterpret_cast <uint8_t *>( &challenge ), sizeof ( challenge ) );
934+ hasher.Update ( reinterpret_cast <uint8_t *>( &m_challenge[ 0 ] ), sizeof ( uint32_t ) * m_challenge. size ( ) );
931935 hasher.Final ( );
932936 SHADigest_t hash = { 0 };
933937 hasher.GetHash ( hash );
934938 if ( reinterpret_cast <int *>( hash )[0 ] == nChallengeValue )
935939 return true ;
936940
937941 // try with the old random nonce
938- challenge &= 0xffffffff00000000ull ;
939- challenge += self-> m_LastRandomNonce ;
942+ m_previous_challenge[ 4 ] = adr. GetIPNetworkByteOrder ( ) ;
943+
940944 hasher.Reset ( );
941- hasher.Update ( reinterpret_cast <uint8_t *>( &challenge ), sizeof ( challenge ) );
945+ hasher.Update ( reinterpret_cast <uint8_t *>( &m_previous_challenge[ 0 ] ), sizeof ( uint32_t ) * m_previous_challenge. size ( ) );
942946 hasher.Final ( );
943947 hasher.GetHash ( hash );
944948 if ( reinterpret_cast <int *>( hash )[0 ] == nChallengeValue )
@@ -949,19 +953,46 @@ namespace netfilter
949953
950954 virtual int GetChallengeNr ( netadr_t &adr )
951955 {
952- TargetClass *self = This ( );
953- uint64 challenge = ( static_cast <uint64>( adr.GetIPNetworkByteOrder ( ) ) << 32 ) + self->m_CurrentRandomNonce ;
956+ UpdateChallengeIfNeeded ( );
957+
958+ m_challenge[4 ] = adr.GetIPNetworkByteOrder ( );
959+
954960 CSHA1 hasher;
955- hasher.Update ( reinterpret_cast <uint8_t *>( &challenge ), sizeof ( challenge ) );
961+ hasher.Update ( reinterpret_cast <uint8_t *>( &m_challenge[ 0 ] ), sizeof ( uint32_t ) * m_challenge. size ( ) );
956962 hasher.Final ( );
957963 SHADigest_t hash = { 0 };
958964 hasher.GetHash ( hash );
959965 return reinterpret_cast <int *>( hash )[0 ];
960966 }
961967
968+ void UpdateChallengeIfNeeded ( )
969+ {
970+ const double current_time = Plat_FloatTime ( );
971+ if ( m_challenge_gen_time >= 0 && current_time < m_challenge_gen_time + CHALLENGE_NONCE_LIFETIME )
972+ return ;
973+
974+ m_challenge_gen_time = current_time;
975+ m_previous_challenge.swap ( m_challenge );
976+
977+ // RandomInt maps a uniform distribution on the interval [0,INT_MAX].
978+ // RandomInt will always return the minimum value if the difference in min and max is greater than or equal to INT_MAX.
979+ m_challenge[0 ] = static_cast <uint32>( RandomInt ( 0 , MAX_RANDOM_RANGE ) );
980+ m_challenge[1 ] = static_cast <uint32>( RandomInt ( 0 , MAX_RANDOM_RANGE ) );
981+ m_challenge[2 ] = static_cast <uint32>( RandomInt ( 0 , MAX_RANDOM_RANGE ) );
982+ m_challenge[3 ] = static_cast <uint32>( RandomInt ( 0 , MAX_RANDOM_RANGE ) );
983+ }
984+
985+ static double m_challenge_gen_time;
986+ static std::array<uint32_t , 5 > m_previous_challenge;
987+ static std::array<uint32_t , 5 > m_challenge;
988+
962989 static CBaseServerProxy Singleton;
963990 };
964991
992+ double CBaseServerProxy::m_challenge_gen_time = -1 ;
993+ std::array<uint32_t , 5 > CBaseServerProxy::m_previous_challenge;
994+ std::array<uint32_t , 5 > CBaseServerProxy::m_challenge;
995+
965996 CBaseServerProxy CBaseServerProxy::Singleton;
966997
967998 void Initialize ( GarrysMod::Lua::ILuaBase *LUA )
0 commit comments