Index: code/client/cl_main.c =================================================================== --- code/client/cl_main.c (revision 1045) +++ code/client/cl_main.c (working copy) @@ -2534,18 +2534,14 @@ 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 building random string\n" ); + Com_RandomBytes( buff, sizeof(buff) ); + f = FS_SV_FOpenFileWrite( QKEY_FILE ); if( !f ) { Com_Printf( "QKEY could not open %s for write\n", Index: code/qcommon/common.c =================================================================== --- code/qcommon/common.c (revision 1045) +++ code/qcommon/common.c (working copy) @@ -3217,3 +3217,28 @@ Field_CompleteCommand( completionField->buffer, qtrue, qtrue ); } + +/* +================== +Com_RandomBytes + +generate a NULL-terminated random string +================== +*/ +void Com_RandomBytes( byte *string, int len ) +{ + int i; + + if( Sys_RandomBytes( string, ( len - 1 ) ) ) { + string[ len - 1 ] = 0; + return; + } + + Com_Printf( "Com_RandomBytes: using weak randomization\n" ); + srand( time( 0 ) ); + for( i = 0; i < len - 1; i++ ) { + string[i] = (unsigned char)( rand() % 255 ); + } + string[i] = 0; +} + Index: code/qcommon/q_shared.h =================================================================== --- code/qcommon/q_shared.h (revision 1045) +++ code/qcommon/q_shared.h (working copy) @@ -640,6 +640,8 @@ char *Com_SkipTokens( char *s, int numTokens, char *sep ); char *Com_SkipCharset( char *s, char *sep ); +void Com_RandomBytes( byte *string, int len ); + // mode parm for FS_FOpenFile typedef enum { FS_READ, Index: code/qcommon/qcommon.h =================================================================== --- code/qcommon/qcommon.h (revision 1045) +++ code/qcommon/qcommon.h (working copy) @@ -1001,6 +1001,8 @@ void Sys_SnapVector( float *v ); +qboolean Sys_RandomBytes( byte *string, int len ); + // the system console is shown when a dedicated server is running void Sys_DisplaySystemConsole( qboolean show ); Index: code/unix/unix_shared.c =================================================================== --- code/unix/unix_shared.c (revision 1045) +++ code/unix/unix_shared.c (working copy) @@ -174,6 +174,22 @@ return s; // bk001204 - duh } +qboolean Sys_RandomBytes( byte *string, int len ) +{ + FILE *fp; + + fp = fopen( "/dev/urandom", "r" ); + if( !fp ) + return qfalse; + + if( !fread( string, sizeof( byte ), len, fp ) ) { + fclose( fp ); + return qfalse; + } + fclose( fp ); + return qtrue; +} + //============================================ #define MAX_FOUND_FILES 0x1000 Index: code/win32/win_shared.c =================================================================== --- code/win32/win_shared.c (revision 1045) +++ code/win32/win_shared.c (working copy) @@ -32,6 +32,7 @@ #include #include #include +#include /* ================ @@ -81,7 +82,25 @@ } #endif +qboolean Sys_RandomBytes( byte *string, int len ) +{ + HCRYPTPROV prov; + if( !CryptAcquireContext( &prov, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) ) { + + return qfalse; + } + + if( !CryptGenRandom( prov, len, (BYTE *)string ) ) { + CryptReleaseContext( prov, 0 ); + return qfalse; + } + CryptReleaseContext( prov, 0 ); + return qtrue; +} + + /* ** ** Disable all optimizations temporarily so this code works correctly!