diff --git a/code/client/cl_main.c b/code/client/cl_main.c index b460919b..bb8d635f 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -74,6 +74,8 @@ cvar_t *cl_trn; cvar_t *cl_lanForcePackets; +cvar_t *cl_guidServerUniq; + clientActive_t cl; clientConnection_t clc; clientStatic_t cls; @@ -713,6 +715,28 @@ void CL_ClearState (void) { Com_Memset( &cl, 0, sizeof( cl ) ); } +/* +==================== +CL_UpdateGUID + +update cl_guid using QKEY_FILE and optional prefix +==================== +*/ +static void CL_UpdateGUID( char *prefix, int prefix_len ) +{ + fileHandle_t f; + int len; + + len = FS_SV_FOpenFileRead( QKEY_FILE, &f ); + FS_FCloseFile( f ); + + if( len != QKEY_SIZE ) + Cvar_Set( "cl_guid", "" ); + else + Cvar_Set( "cl_guid", Com_MD5File( QKEY_FILE, QKEY_SIZE, + prefix, prefix_len ) ); +} + /* ===================== @@ -781,6 +805,7 @@ void CL_Disconnect( qboolean showMainMenu ) { if( CL_VideoRecording( ) ) { CL_CloseAVI( ); } + CL_UpdateGUID( NULL, 0 ); } @@ -1036,6 +1061,7 @@ CL_Connect_f */ void CL_Connect_f( void ) { char *server; + char serverString[ 22 ]; if ( Cmd_Argc() != 2 ) { Com_Printf( "usage: connect [server]\n"); @@ -1078,10 +1104,17 @@ void CL_Connect_f( void ) { if (clc.serverAddress.port == 0) { clc.serverAddress.port = BigShort( PORT_SERVER ); } - Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", cls.servername, - clc.serverAddress.ip[0], clc.serverAddress.ip[1], - clc.serverAddress.ip[2], clc.serverAddress.ip[3], - BigShort( clc.serverAddress.port ) ); + Com_sprintf( serverString, sizeof( serverString ), "%i.%i.%i.%i:%i", + clc.serverAddress.ip[0], clc.serverAddress.ip[1], + clc.serverAddress.ip[2], clc.serverAddress.ip[3], + BigShort( clc.serverAddress.port ) ); + + Com_Printf( "%s resolved to %s\n", cls.servername, serverString ); + + if( cl_guidServerUniq->integer ) + CL_UpdateGUID( serverString, strlen( serverString ) ); + else + CL_UpdateGUID( NULL, 0 ); // if we aren't playing on a lan, we need to authenticate // with the cd key @@ -2480,25 +2513,48 @@ void CL_StopVideo_f( void ) CL_CloseAVI( ); } +/* +=============== +CL_GenerateQKey + +test to see if a valid QKEY_FILE exists. If one does not, try to generate +it by filling it with 2048 bytes of random data. +=============== +*/ static void CL_GenerateQKey(void) { int len = 0; - unsigned char buff[2048]; + unsigned char buff[ QKEY_SIZE ]; + fileHandle_t f; - len = FS_ReadFile(QKEY_FILE, NULL); - if(len >= (int)sizeof(buff)) { - Com_Printf("QKEY found.\n"); + len = FS_SV_FOpenFileRead( QKEY_FILE, &f ); + FS_FCloseFile( f ); + if( len == QKEY_SIZE ) { + Com_Printf( "QKEY found.\n" ); return; } else { int i; + + if( len > 0 ) { + Com_Printf( "QKEY file size != %d, regenerating\n", + QKEY_SIZE ); + } + srand(time(0)); for(i = 0; i < sizeof(buff) - 1; i++) { buff[i] = (unsigned char)(rand() % 255); } buff[i] = 0; - Com_Printf("QKEY generated\n"); - FS_WriteFile(QKEY_FILE, buff, sizeof(buff)); + f = FS_SV_FOpenFileWrite( QKEY_FILE ); + if( !f ) { + Com_Printf( "QKEY could not open %s for write\n", + QKEY_FILE ); + return; + } + FS_Write( buff, sizeof(buff), f ); + FS_FCloseFile( f ); + Com_Printf( "QKEY generated\n" ); } } @@ -2595,6 +2651,8 @@ void CL_Init( void ) { cl_lanForcePackets = Cvar_Get ("cl_lanForcePackets", "1", CVAR_ARCHIVE); + cl_guidServerUniq = Cvar_Get ("cl_guidServerUniq", "1", CVAR_ARCHIVE); + // userinfo Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("rate", "3000", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -2655,7 +2713,8 @@ void CL_Init( void ) { Cvar_Set( "cl_running", "1" ); CL_GenerateQKey(); - Cvar_Get("cl_guid", Com_MD5File(QKEY_FILE, 0), CVAR_USERINFO | CVAR_ROM); + Cvar_Get( "cl_guid", "", CVAR_USERINFO | CVAR_ROM ); + CL_UpdateGUID( NULL, 0 ); Com_Printf( "----- Client Initialization Complete -----\n" ); } diff --git a/code/client/client.h b/code/client/client.h index 17b6d218..df6fe6f9 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -34,8 +34,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_curl.h" #endif /* USE_CURL */ -// tjw: file full of random crap that gets used to create cl_guid +// file full of random crap that gets used to create cl_guid #define QKEY_FILE "qkey" +#define QKEY_SIZE 2048 #define RETRANSMIT_TIMEOUT 3000 // time between connection packet retransmits diff --git a/code/qcommon/md5.c b/code/qcommon/md5.c index ffe77527..dcb4e447 100644 --- a/code/qcommon/md5.c +++ b/code/qcommon/md5.c @@ -257,9 +257,9 @@ static void MD5Final(struct MD5Context *ctx, unsigned char *digest) } -char *Com_MD5File(const char *fn, int length) +char *Com_MD5File( const char *fn, int length, const char *prefix, int prefix_len ) { - static char final[33] = {"unknown"}; + static char final[33] = {""}; unsigned char digest[16] = {""}; fileHandle_t f; MD5_CTX md5; @@ -269,8 +269,15 @@ char *Com_MD5File(const char *fn, int length) int r = 0; int total = 0; - filelen = FS_FOpenFileRead(fn, &f, qtrue); - if(filelen < 1) { + Q_strncpyz( final, "", sizeof( final ) ); + + filelen = FS_SV_FOpenFileRead( fn, &f ); + + if( !f ) { + return final; + } + if( filelen < 1 ) { + FS_FCloseFile( f ); return final; } if(filelen < length || !length) { @@ -278,6 +285,10 @@ char *Com_MD5File(const char *fn, int length) } MD5Init(&md5); + + if( prefix_len && *prefix ) + MD5Update(&md5 , (unsigned char *)prefix, prefix_len); + for(;;) { r = FS_Read2(buffer, sizeof(buffer), f); if(r < 1) diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index b07d77e0..8bde0281 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -732,7 +732,7 @@ void Com_Quit_f( void ); int Com_EventLoop( void ); int Com_Milliseconds( void ); // will be journaled properly unsigned Com_BlockChecksum( const void *buffer, int length ); -char *Com_MD5File(const char *filename, int length); +char *Com_MD5File(const char *filename, int length, const char *prefix, int prefix_len); int Com_HashKey(char *string, int maxlen); int Com_Filter(char *filter, char *name, int casesensitive); int Com_FilterPath(char *filter, char *name, int casesensitive);