Changeset 190:22bc1a693c15

Show
Ignore:
Timestamp:
05/28/08 17:17:38 (2 years ago)
Author:
amanieu@…
Branch:
pubkey
Message:

Added public key identification

Files:
17 modified

Legend:

Unmodified
Added
Removed
  • Makefile

    r125 r190  
    9595ifndef USE_OPENAL_DLOPEN 
    9696USE_OPENAL_DLOPEN=0 
     97endif 
     98 
     99ifndef USE_GMP_DLOPEN 
     100USE_GMP_DLOPEN=0 
     101endif 
     102 
     103ifndef USE_NETTLE_DLOPEN 
     104USE_NETTLE_DLOPEN=0 
    97105endif 
    98106 
     
    213221  endif 
    214222 
     223  ifeq ($(USE_NETTLE_DLOPEN),1) 
     224    BASE_CFLAGS += -DUSE_NETTLE_DLOPEN 
     225  else 
     226    USE_GMP_DLOPEN = 0 
     227  endif 
     228  ifeq ($(USE_GMP_DLOPEN),1) 
     229    BASE_CFLAGS += -DUSE_GMP_DLOPEN 
     230  endif 
     231 
    215232  OPTIMIZE = -O2 -funroll-loops -fomit-frame-pointer 
    216233 
     
    264281  endif 
    265282 
     283  ifneq ($(USE_NETTLE_DLOPEN),1) 
     284    LDFLAGS += -lnettle 
     285  endif 
     286  ifneq ($(USE_GMP_DLOPEN),1) 
     287    LDFLAGS += -lgmp 
     288  endif 
     289 
    266290  ifeq ($(ARCH),x86) 
    267291    # linux32 make ... 
     
    397421  endif 
    398422 
     423#  Building nettle as a dll is broken, atm 
     424#  ifeq ($(USE_NETTLE_DLOPEN),1) 
     425#    BASE_CFLAGS += -DUSE_NETTLE_DLOPEN 
     426#  else 
     427#    USE_GMP_DLOPEN = 0 
     428#  endif 
     429#  ifeq ($(USE_GMP_DLOPEN),1) 
     430#    BASE_CFLAGS += -DUSE_GMP_DLOPEN 
     431#  endif 
     432 
    399433  OPTIMIZE = -O2 -march=i586 -fno-omit-frame-pointer  \ 
    400434    -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ 
     
    421455    CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg 
    422456  endif 
     457 
     458#  Building nettle as a dll is broken, atm 
     459  LDFLAGS += -lnettle -lgmp 
     460#  ifneq ($(USE_NETTLE_DLOPEN),1) 
     461#    LDFLAGS += -lnettle 
     462#  endif 
     463#  ifneq ($(USE_GMP_DLOPEN),1) 
     464#    LDFLAGS += -lgmp 
     465#  endif 
    423466 
    424467  ifeq ($(ARCH),x86) 
     
    10721115  $(B)/client/cmd.o \ 
    10731116  $(B)/client/common.o \ 
     1117  $(B)/client/crypto.o \ 
    10741118  $(B)/client/cvar.o \ 
    10751119  $(B)/client/files.o \ 
     
    12641308  $(B)/ded/cmd.o \ 
    12651309  $(B)/ded/common.o \ 
     1310  $(B)/ded/crypto.o \ 
    12661311  $(B)/ded/cvar.o \ 
    12671312  $(B)/ded/files.o \ 
  • src/client/cl_cgame.c

    r125 r190  
    357357                Cbuf_AddText( "wait ; wait ; wait ; wait ; screenshot levelshot\n" ); 
    358358                return qtrue; 
     359        } 
     360 
     361        if ( cl_pubkeyID->integer && !strcmp( cmd, "pubkey_request" ) ) { 
     362                char buffer[ MAX_STRING_CHARS ] = "pubkey "; 
     363                qmpz_get_str( buffer + 7, 16, public_key.n ); 
     364                CL_AddReliableCommand( buffer ); 
     365                return qfalse; 
     366        } 
     367 
     368        if ( cl_pubkeyID->integer && !strcmp( cmd, "pubkey_decrypt" ) && argc > 1 ) { 
     369                char buffer[ MAX_STRING_CHARS ] = "pubkey_identify "; 
     370                unsigned int msg_len = MAX_STRING_CHARS - 16; 
     371                mpz_t message; 
     372                qmpz_init_set_str( message, Cmd_Argv( 1 ), 16 ); 
     373                if ( qrsa_decrypt( &private_key, &msg_len, (unsigned char *) buffer + 16, message ) ) 
     374                { 
     375                        qnettle_mpz_set_str_256_u( message, msg_len, (unsigned char *) buffer + 16 ); 
     376                        qmpz_get_str( buffer + 16, 16, message ); 
     377                        CL_AddReliableCommand( buffer ); 
     378                } 
     379                qmpz_clear( message ); 
     380                return qfalse; 
    359381        } 
    360382 
  • src/client/cl_main.c

    r125 r190  
    7979 
    8080cvar_t  *cl_guidServerUniq; 
     81 
     82cvar_t  *cl_pubkeyID; 
     83 
     84struct rsa_public_key public_key; 
     85struct rsa_private_key private_key; 
    8186 
    8287clientActive_t          cl; 
     
    26022607 
    26032608/* 
     2609=============== 
     2610CL_GeneratePKey 
     2611 
     2612Check if the PKEY file contains a valid RSA keypair 
     2613If not then generate a new keypair 
     2614=============== 
     2615*/ 
     2616static void CL_GeneratePKey(void) 
     2617{ 
     2618        int len; 
     2619        fileHandle_t f; 
     2620        void *buf; 
     2621 
     2622        qrsa_public_key_init( &public_key ); 
     2623        qrsa_private_key_init( &private_key ); 
     2624 
     2625        len = FS_SV_FOpenFileRead( PKEY_FILE, &f ); 
     2626        if ( !f || len < 1 ) 
     2627        { 
     2628                Com_Printf( "PKEY file not found, regenerating\n" ); 
     2629                goto new_key; 
     2630        } 
     2631        buf = Z_TagMalloc( len, TAG_CRYPTO ); 
     2632        FS_Read( buf, len, f ); 
     2633        FS_FCloseFile( f ); 
     2634 
     2635        if ( !qrsa_keypair_from_sexp( &public_key, &private_key, 0 , len, buf ) ) 
     2636        { 
     2637                Com_Printf( "Invalid RSA keypair in PKEY, regenerating\n" ); 
     2638                Z_Free( buf ); 
     2639                goto new_key; 
     2640        } 
     2641 
     2642        Z_Free( buf ); 
     2643        Com_Printf( "PKEY found.\n" ); 
     2644        return; 
     2645 
     2646new_key: 
     2647        qmpz_set_ui(public_key.e, RSA_PUBLIC_EXPONENT); 
     2648        if ( !qrsa_generate_keypair( &public_key, &private_key, NULL, qnettle_random, NULL, NULL, RSA_KEY_LENGTH, 0 ) ) 
     2649                goto keygen_error; 
     2650 
     2651        struct nettle_buffer key_buffer; 
     2652        int key_buffer_len = 0; 
     2653        qnettle_buffer_init(&key_buffer, &key_buffer_len); 
     2654        if ( !qrsa_keypair_to_sexp( &key_buffer, NULL, &public_key, &private_key ) ) 
     2655                goto keygen_error; 
     2656 
     2657        f = FS_SV_FOpenFileWrite( PKEY_FILE ); 
     2658        if( !f ) 
     2659        { 
     2660                Com_Printf( "PKEY could not open %s for write, RSA support will be disabled\n", PKEY_FILE ); 
     2661                Cvar_Set( "cl_pubkeyID", "0" ); 
     2662                CRYPTO_Shutdown(); 
     2663                return; 
     2664        } 
     2665        FS_Write( key_buffer.contents, key_buffer.size, f ); 
     2666        qnettle_buffer_clear( &key_buffer ); 
     2667        FS_FCloseFile( f ); 
     2668        Com_Printf( "PKEY generated\n" ); 
     2669        return; 
     2670 
     2671keygen_error: 
     2672        Com_Printf( "Error generating RSA keypair, RSA support will be disabled\n" ); 
     2673        Cvar_Set( "cl_pubkeyID", "0" ); 
     2674        CRYPTO_Shutdown(); 
     2675}  
     2676 
     2677/* 
    26042678==================== 
    26052679CL_Init 
     
    26972771 
    26982772        cl_guidServerUniq = Cvar_Get ("cl_guidServerUniq", "1", CVAR_ARCHIVE); 
     2773 
     2774        cl_pubkeyID = Cvar_Get ("cl_pubkeyID", "1", CVAR_ARCHIVE | CVAR_USERINFO); 
    26992775 
    27002776        // userinfo 
     
    27502826 
    27512827        CL_GenerateQKey();       
     2828        if (cl_pubkeyID->integer) 
     2829                CL_GeneratePKey(); 
    27522830        Cvar_Get( "cl_guid", "", CVAR_USERINFO | CVAR_ROM ); 
    27532831        CL_UpdateGUID( NULL, 0 ); 
  • src/client/client.h

    r123 r190  
    379379extern  cvar_t  *cl_autoRecordDemo; 
    380380 
     381extern  cvar_t  *cl_pubkeyID; 
     382 
     383extern  struct rsa_public_key public_key; 
     384extern  struct rsa_private_key private_key; 
     385 
    381386//================================================= 
    382387 
  • src/game/g_admin.c

    r175 r190  
    454454} 
    455455 
    456 static void admin_writeconfig( void ) 
     456void G_admin_writeconfig( void ) 
    457457{ 
    458458  fileHandle_t f; 
     
    471471  if( len < 0 ) 
    472472  { 
    473     G_Printf( "admin_writeconfig: could not open g_admin file \"%s\"\n", 
     473    G_Printf( "G_admin_writeconfig: could not open g_admin file \"%s\"\n", 
    474474              g_admin.string ); 
    475475    return; 
     
    501501    trap_FS_Write( "flags   = ", 10, f ); 
    502502    admin_writeconfig_string( g_admin_admins[ i ]->flags, f ); 
     503    trap_FS_Write( "pubkey  = ", 10, f ); 
     504    admin_writeconfig_string( g_admin_admins[ i ]->pubkey, f ); 
     505    trap_FS_Write( "msg     = ", 10, f ); 
     506    admin_writeconfig_string( g_admin_admins[ i ]->msg, f ); 
     507    trap_FS_Write( "msg2    = ", 10, f ); 
     508    admin_writeconfig_string( g_admin_admins[ i ]->msg2, f ); 
     509    trap_FS_Write( "counter = ", 10, f ); 
     510    admin_writeconfig_int( g_admin_admins[ i ]->counter, f ); 
    503511    trap_FS_Write( "\n", 1, f ); 
    504512  } 
     
    649657} 
    650658 
    651 //  return a level for a player entity. 
    652 int G_admin_level( gentity_t *ent ) 
     659// return the admin struct for a player entity. 
     660g_admin_admin_t *G_admin_admin( gentity_t *ent ) 
    653661{ 
    654662  int i; 
     
    657665  if( !ent ) 
    658666  { 
    659     return MAX_ADMIN_LEVELS; 
     667    return NULL; 
    660668  } 
    661669 
     
    672680  if( found ) 
    673681  { 
    674     return g_admin_admins[ i ]->level; 
    675   } 
    676  
    677   return 0; 
     682    return g_admin_admins[i]; 
     683  } 
     684 
     685  return NULL; 
    678686} 
    679687 
     
    11521160} 
    11531161 
     1162void G_admin_pubkey( void ) 
     1163{ 
     1164  int i; 
     1165  g_admin_admin_t *highest = NULL; 
     1166 
     1167  // Uncomment this if your server lags (shouldn't happen unless you are on a *very* old computer) 
     1168  // Will only regenrate messages when there are no active client (When they are all loading the map) 
     1169#if 0 
     1170  for( i = 0; i < level.maxclients; i++ ) 
     1171  { 
     1172    if( g_entities[ i ].client && g_entities[ i ].client->pers.connected == CON_CONNECTED ) 
     1173      return; 
     1174  } 
     1175#endif 
     1176 
     1177  // Only do 1 encryption per frame to avoid lag 
     1178  for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ ) 
     1179  { 
     1180    if ( g_admin_admins[ i ]->counter == -1 && g_admin_admins[ i ]->pubkey[ 0 ] ) 
     1181    { 
     1182      highest = g_admin_admins[ i ]; 
     1183      break; 
     1184    } 
     1185    else if ( g_admin_admins[ i ]->counter == 0 || !g_admin_admins[ i ]->pubkey[ 0 ] ) 
     1186      continue; 
     1187    else if ( !highest ) 
     1188    { 
     1189      highest = g_admin_admins[ i ]; 
     1190      continue; 
     1191    } 
     1192    else if ( highest->counter < g_admin_admins[ i ]->counter ) 
     1193      highest = g_admin_admins[ i ]; 
     1194  } 
     1195  if ( highest ) 
     1196  { 
     1197    if ( trap_RSA_GenerateMessage( highest->pubkey, highest->msg, highest->msg2 ) ) 
     1198      highest->counter = 0; 
     1199    else 
     1200    { 
     1201      // If the key generation failed it can only be because of a bad pubkey 
     1202      // so we clear the pubkey and ask the client for a new one when he reconnects 
     1203      highest->pubkey[ 0 ] = '\0'; 
     1204      highest->msg[ 0 ] = '\0'; 
     1205      highest->msg2[ 0 ] = '\0'; 
     1206      highest->counter = -1; 
     1207    } 
     1208    G_admin_writeconfig( ); 
     1209  } 
     1210} 
     1211 
    11541212qboolean G_admin_readconfig( gentity_t *ent, int skiparg ) 
    11551213{ 
     
    12511309      { 
    12521310        admin_readconfig_string( &cnf, a->flags, sizeof( a->flags ) ); 
     1311      } 
     1312      else if( !Q_stricmp( t, "pubkey" ) ) 
     1313      { 
     1314        admin_readconfig_string( &cnf, a->pubkey, sizeof( a->pubkey ) ); 
     1315      } 
     1316      else if( !Q_stricmp( t, "msg" ) ) 
     1317      { 
     1318        admin_readconfig_string( &cnf, a->msg, sizeof( a->msg ) ); 
     1319      } 
     1320      else if( !Q_stricmp( t, "msg2" ) ) 
     1321      { 
     1322        admin_readconfig_string( &cnf, a->msg2, sizeof( a->msg2 ) ); 
     1323      } 
     1324      else if( !Q_stricmp( t, "counter" ) ) 
     1325      { 
     1326        admin_readconfig_int( &cnf, &a->counter ); 
    12531327      } 
    12541328      else 
     
    13621436      a->level = 0; 
    13631437      *a->flags = '\0'; 
     1438      *a->pubkey = '\0'; 
     1439      *a->msg = '\0'; 
     1440      *a->msg2 = '\0'; 
     1441      a->counter = -1; 
    13641442      admin_open = qtrue; 
    13651443    } 
     
    14181496  for( i = 0; i < level.maxclients; i++ ) 
    14191497    if( level.clients[ i ].pers.connected != CON_DISCONNECTED ) 
    1420       level.clients[ i ].pers.adminLevel = G_admin_level( &g_entities[ i ] ); 
     1498    { 
     1499      level.clients[ i ].pers.admin = G_admin_admin( &g_entities[ i ] ); 
     1500      level.clients[ i ].pers.adminLevel = ( level.clients[ i ].pers.pubkey_authenticated ? level.clients[ i ].pers.admin->level : 0 ); 
     1501    } 
    14211502  return qtrue; 
    14221503} 
     
    15761657    if( !Q_stricmp( g_admin_admins[ i ]->guid, guid ) ) 
    15771658    { 
    1578       g_admin_admins[ i ]->level = l; 
    1579       Q_strncpyz( g_admin_admins[ i ]->name, adminname, 
    1580                   sizeof( g_admin_admins[ i ]->name ) ); 
     1659      a = g_admin_admins[ i ]; 
     1660      a->level = l; 
     1661      Q_strncpyz( a->name, adminname, 
     1662                  sizeof( a->name ) ); 
    15811663      updated = qtrue; 
    15821664    } 
     
    15941676    Q_strncpyz( a->guid, guid, sizeof( a->guid ) ); 
    15951677    *a->flags = '\0'; 
     1678    *a->pubkey = '\0'; 
     1679    *a->msg = '\0'; 
     1680    *a->msg2 = '\0'; 
     1681    a->counter = -1; 
    15961682    g_admin_admins[ i ] = a; 
    15971683  } 
     
    16011687    adminname, l, ( ent ) ? ent->client->pers.netname : "console" ) ); 
    16021688  if( vic ) 
     1689  { 
     1690    vic->client->pers.admin = ( l ? a : NULL ); 
    16031691    vic->client->pers.adminLevel = l; 
     1692    if ( l && l >= g_adminPubkeyID.integer && !a->pubkey[0] && vic->client->pers.cl_pubkeyID ) 
     1693      trap_SendServerCommand( vic - g_entities, "pubkey_request" ); 
     1694  } 
    16041695 
    16051696  if( !g_admin.string[ 0 ] ) 
     
    16071698      "to a file\n" ); 
    16081699  else 
    1609     admin_writeconfig(); 
     1700    G_admin_writeconfig(); 
    16101701  return qtrue; 
    16111702} 
     
    18271918      ADM_NEW_BAN ); 
    18281919    if( g_admin.string[ 0 ] ) 
    1829       admin_writeconfig(); 
     1920      G_admin_writeconfig(); 
    18301921  } 
    18311922 
     
    20552146       ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 
    20562147    else 
    2057        admin_writeconfig(); 
     2148       G_admin_writeconfig(); 
    20582149 
    20592150    AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 
     
    20952186      ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 
    20962187    else 
    2097       admin_writeconfig(); 
     2188      G_admin_writeconfig(); 
    20982189 
    20992190    if( g_admin_namelog[ logmatch ]->slot == -1 ) 
     
    21542245          ( ent ) ? ent->client->pers.netname : "console" ) ); 
    21552246  if( g_admin.string[ 0 ] ) 
    2156     admin_writeconfig(); 
     2247    G_admin_writeconfig(); 
    21572248  return qtrue; 
    21582249} 
     
    32173308  } 
    32183309 
    3219   level = G_admin_level(ent); 
     3310  level = ent->client->pers.adminLevel; 
    32203311         
    32213312  if( level == 0 ) 
     
    32563347  level = 0; 
    32573348   
    3258   level = G_admin_level(ent); 
     3349  level = ent->client->pers.adminLevel; 
    32593350  if( level == 0 ) 
    32603351    level = 1; 
  • src/game/g_admin.h

    r143 r190  
    109109  int level; 
    110110  char flags[ MAX_ADMIN_FLAGS ]; 
     111  char pubkey[ RSA_STRING_LENGTH ]; 
     112  char msg[ RSA_STRING_LENGTH ]; 
     113  char msg2[ RSA_STRING_LENGTH ]; 
     114  int counter; 
    111115} 
    112116g_admin_admin_t; 
     
    147151qboolean G_admin_cmd_check( gentity_t *ent, qboolean say ); 
    148152qboolean G_admin_readconfig( gentity_t *ent, int skiparg ); 
     153void G_admin_writeconfig( void ); 
    149154qboolean G_admin_permission( gentity_t *ent, char flag ); 
    150155qboolean G_admin_guid_permission( char *guid, char flag ); 
    151156qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len ); 
    152157void G_admin_namelog_update( gclient_t *ent, qboolean disconnect ); 
    153 int G_admin_level( gentity_t *ent ); 
     158g_admin_admin_t *G_admin_admin( gentity_t *ent ); 
     159void G_admin_pubkey( void ); 
    154160 
    155161// ! command functions 
  • src/game/g_client.c

    r143 r190  
    12641264  int       used_privateSlots; 
    12651265  int       privateClients; 
     1266  g_admin_admin_t *admin; 
    12661267 
    12671268  ent = &g_entities[ clientNum ]; 
     
    13401341  } 
    13411342  Q_strncpyz( client->pers.ip, ip, sizeof( client->pers.ip ) ); 
    1342   client->pers.adminLevel = G_admin_level( ent ); 
    1343    
     1343  admin = G_admin_admin( ent ); 
     1344  client->pers.admin = admin; 
     1345  client->pers.adminLevel = admin->level; 
     1346  client->pers.pubkey_authenticated = -1; 
     1347  client->pers.cl_pubkeyID = atoi( Info_ValueForKey( userinfo, "cl_pubkeyID" ) ); 
     1348 
     1349  if ( g_adminPubkeyID.integer && admin ) 
     1350  { 
     1351    if ( admin->pubkey[0] && admin->counter != -1 && admin->level >= g_adminPubkeyID.integer ) 
     1352    { 
     1353      // remove admin from client 
     1354      client->pers.pubkey_authenticated = 0; 
     1355      client->pers.adminLevel = 0; 
     1356      Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", sizeof( client->pers.guid ) ); 
     1357      // save name before we get renamed to UnamedPlayer 
     1358      Q_strncpyz( client->pers.connect_name, Info_ValueForKey( userinfo, "name" ), sizeof( client->pers.connect_name ) ); 
     1359    } 
     1360  } 
     1361 
    13441362  // do autoghost now so that there won't be any name conflicts later on 
    13451363  if ( g_autoGhost.integer ) 
     
    13831401  gclient_t *client; 
    13841402  int       flags; 
     1403  g_admin_admin_t *admin; 
    13851404 
    13861405  ent = g_entities + clientNum; 
     
    14241443  // request the clients PTR code 
    14251444  trap_SendServerCommand( ent - g_entities, "ptrcrequest" ); 
     1445 
     1446  // ask for identification 
     1447  admin = client->pers.admin; 
     1448  if ( g_adminPubkeyID.integer && admin && client->pers.cl_pubkeyID ) 
     1449  { 
     1450    if ( admin->level >= g_adminPubkeyID.integer && !admin->pubkey[0] ) 
     1451      trap_SendServerCommand( ent - g_entities, "pubkey_request" ); 
     1452    else if ( client->pers.pubkey_authenticated == 0 ) 
     1453    { 
     1454      trap_SendServerCommand( ent - g_entities, va( "pubkey_decrypt %s", admin->msg2 ) ); 
     1455      admin->counter++; 
     1456      // copy the decrypted message because generating a new message will overwrite it 
     1457      Q_strncpyz( client->pers.pubkey_msg, admin->msg, sizeof( client->pers.pubkey_msg ) ); 
     1458      G_admin_writeconfig( ); 
     1459    } 
     1460  } 
    14261461 
    14271462  G_LogPrintf( "ClientBegin: %i\n", clientNum ); 
  • src/game/g_cmds.c

    r185 r190  
    888888    default: 
    889889    case SAY_ALL: 
    890       if(ent->client->pers.teamSelection == TEAM_NONE && G_admin_level(ent)<g_minLevelToSpecMM1.integer) 
     890      if(ent->client->pers.teamSelection == TEAM_NONE && ent->client->pers.adminLevel<g_minLevelToSpecMM1.integer) 
    891891      { 
    892892        trap_SendServerCommand( ent-g_entities,va( "print \"Sorry, but your admin level is not permitted to speak to all while spectating.\n\"") );  
     
    35293529} 
    35303530 
     3531static void Cmd_Pubkey_f( gentity_t *ent ) 
     3532{ 
     3533  char buffer[ RSA_STRING_LENGTH ]; 
     3534  g_admin_admin_t *admin = ent->client->pers.admin; 
     3535  if ( !g_adminPubkeyID.integer || ent->client->pers.adminLevel < g_adminPubkeyID.integer || trap_Argc() != 2 ) 
     3536    return; 
     3537  if ( admin->pubkey[0] ) 
     3538    return; 
     3539  trap_Argv( 1, buffer, sizeof( buffer ) ); 
     3540  Q_strncpyz( admin->pubkey, buffer, sizeof( admin->pubkey ) ); 
     3541  admin->counter = -1; 
     3542  G_admin_writeconfig( ); 
     3543} 
     3544 
     3545static void Cmd_Pubkey_Identify_f( gentity_t *ent ) 
     3546{ 
     3547  char buffer[ MAX_STRING_CHARS ]; 
     3548  char userinfo[ MAX_INFO_STRING ]; 
     3549  g_admin_admin_t *admin = ent->client->pers.admin; 
     3550  if ( !g_adminPubkeyID.integer || ent->client->pers.admin->level < g_adminPubkeyID.integer || trap_Argc() != 2 ) 
     3551    return; 
     3552  if ( ent->client->pers.pubkey_authenticated != 0 || !admin->pubkey[0] || admin->counter == -1 || !ent->client->pers.pubkey_msg[0] ) 
     3553    return; 
     3554  trap_Argv( 1, buffer, sizeof( buffer ) ); 
     3555  if ( Q_strncmp( buffer, ent->client->pers.pubkey_msg, MAX_STRING_CHARS ) ) 
     3556    return; 
     3557  ent->client->pers.pubkey_authenticated = 1; 
     3558  ent->client->pers.pubkey_msg[0] = '\0'; 
     3559  ent->client->pers.adminLevel = admin->level; 
     3560  trap_GetUserinfo( ent - g_entities, userinfo, sizeof( userinfo ) ); 
     3561  Q_strncpyz( ent->client->pers.guid, Info_ValueForKey( userinfo, "cl_guid" ), sizeof( ent->client->pers.guid ) ); 
     3562  Info_SetValueForKey( userinfo, "name", ent->client->pers.connect_name ); 
     3563  trap_SetUserinfo( ent - g_entities, userinfo ); 
     3564  ClientUserinfoChanged( ent - g_entities ); 
     3565} 
     3566 
    35313567commands_t cmds[ ] = { 
    35323568  // normal commands 
     
    35713607  { "donate", CMD_TEAM, Cmd_Donate_f }, 
    35723608 
     3609  { "pubkey", CMD_INTERMISSION, Cmd_Pubkey_f }, 
     3610  { "pubkey_identify", CMD_INTERMISSION, Cmd_Pubkey_Identify_f }, 
     3611 
    35733612  { "follow", CMD_NOTEAM, Cmd_Follow_f }, 
    35743613  { "follownext", CMD_NOTEAM, Cmd_FollowCycle_f }, 
  • src/game/g_local.h

    r182 r190  
    324324  int                 specExpires;          // level.time at which a player can join a team again after !spec 
    325325  char                voice[ MAX_VOICE_NAME_LEN ]; 
     326  g_admin_admin_t     *admin; 
     327  int                 pubkey_authenticated; // -1 = does not have pubkey, 0 = not authenticated, 1 = authenticated 
     328  int                 cl_pubkeyID; 
     329  char                pubkey_msg[ RSA_STRING_LENGTH ]; 
     330  char                connect_name[ MAX_NAME_LENGTH ]; // Name of client before admin was removed with pubkey 
    326331} clientPersistant_t; 
    327332 
     
    12231228extern  vmCvar_t  g_adminNameProtect; 
    12241229extern  vmCvar_t  g_adminTempBan; 
     1230extern  vmCvar_t  g_adminPubkeyID; 
    12251231extern  vmCvar_t  g_adminTempSpec; 
    12261232extern  vmCvar_t  g_minLevelToSpecMM1; 
     
    13011307void      trap_SnapVector( float *v ); 
    13021308void      trap_SendGameStat( const char *data ); 
     1309int       trap_RSA_GenerateMessage( const char *public_key, char *cleartext, char *encrypted ); 
    13031310 
    13041311void      do_health( gentity_t *ent, int quantity ); 
  • src/game/g_main.c

    r185 r190  
    149149vmCvar_t  g_autoRegister; 
    150150vmCvar_t  g_adminTempBan; 
     151vmCvar_t  g_adminPubkeyID; 
    151152vmCvar_t  g_adminTempSpec; 
    152153vmCvar_t  g_minLevelToSpecMM1; 
     
    329330  { &g_adminNameProtect, "g_adminNameProtect", "1", CVAR_ARCHIVE, 0, qfalse  }, 
    330331  { &g_adminTempBan, "g_adminTempBan", "120", CVAR_ARCHIVE, 0, qfalse  }, 
     332  { &g_adminPubkeyID, "g_adminPubkeyID", "2", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse  }, 
    331333  { &g_adminTempSpec, "g_adminTempSpec", "120", CVAR_ARCHIVE, 0, qfalse  }, 
    332334  { &g_adminWarnMessage, "g_adminWarnMessage", "You have been warned by an administrator.\n Cease imeediately or face admin action!\n", CVAR_ARCHIVE, 0, qfalse }, 
     
    27352737  CheckTeamVote( TEAM_ALIENS ); 
    27362738 
     2739  // generate public-key messages 
     2740  if ( g_adminPubkeyID.integer ) 
     2741    G_admin_pubkey(); 
     2742 
    27372743  // for tracking changes 
    27382744  CheckCvars( ); 
  • src/game/g_public.h

    r156 r190  
    221221  G_PARSE_SOURCE_FILE_AND_LINE, 
    222222 
    223   G_SEND_GAMESTAT 
     223  G_SEND_GAMESTAT, 
     224   
     225  G_RSA_GENMSG // ( const char *public_key, char *cleartext, char *encrypted ) 
    224226} gameImport_t; 
    225227 
  • src/game/g_syscalls.asm

    r125 r190  
    5151 
    5252equ trap_SendGameStat               -48 
     53equ trap_RSA_GenerateMessage            -49 
    5354 
    5455 
  • src/game/g_syscalls.c

    r156 r190  
    258258} 
    259259 
     260int trap_RSA_GenerateMessage( const char *public_key, char *cleartext, char *encrypted ) 
     261{ 
     262        return syscall( G_RSA_GENMSG, public_key, cleartext, encrypted ); 
     263} 
     264 
    260265int trap_Parse_AddGlobalDefine( char *define ) 
    261266{ 
  • src/qcommon/common.c

    r125 r190  
    8383cvar_t  *com_unfocused; 
    8484cvar_t  *com_minimized; 
     85cvar_t  *com_gmpLibName; 
     86cvar_t  *com_nettleLibName; 
    8587 
    8688// com_speeds times 
     
    24712473        com_minimized = Cvar_Get( "com_minimized", "0", CVAR_ROM ); 
    24722474 
     2475        com_gmpLibName = Cvar_Get( "com_gmpLibName", DEFAULT_GMP_LIB, CVAR_ARCHIVE ); 
     2476        com_nettleLibName = Cvar_Get( "com_nettleLibName", DEFAULT_NETTLE_LIB, CVAR_ARCHIVE ); 
     2477 
    24732478        if ( com_developer && com_developer->integer ) { 
    24742479                Cmd_AddCommand ("error", Com_Error_f); 
     
    24862491        VM_Init(); 
    24872492        SV_Init(); 
     2493        if (!CRYPTO_Init()) 
     2494        { 
     2495                // Disable all crypto functions 
     2496                Cvar_Get("g_adminPubkeyID", "0", CVAR_ROM); 
     2497#ifndef DEDICATED 
     2498                Cvar_Get("cl_pubkeyID", "0", CVAR_ROM); 
     2499#endif 
     2500        } 
    24882501 
    24892502        com_dedicated->modified = qfalse; 
  • src/qcommon/q_shared.h

    r174 r190  
    13321332#define MAX_EMOTICONS 64 
    13331333 
     1334/* This should not be changed because this value is 
     1335 * expected to be the same on the client and on the server */ 
     1336#define RSA_KEY_LENGTH 2048 
     1337#define RSA_STRING_LENGTH (RSA_KEY_LENGTH / 4 + 1) 
     1338 
    13341339#endif  // __Q_SHARED_H 
  • src/qcommon/qcommon.h

    r125 r190  
    2626 
    2727#include "../qcommon/cm_public.h" 
     28 
     29#include "../qcommon/crypto.h" 
    2830 
    2931//Ignore __attribute__ on non-gcc platforms 
     
    785787extern  cvar_t  *com_minimized; 
    786788extern  cvar_t  *com_altivec; 
     789extern  cvar_t  *com_gmpLibName; 
     790extern  cvar_t  *com_nettleLibName; 
    787791 
    788792// both client and server must agree to pause 
     
    811815        TAG_BOTLIB, 
    812816        TAG_RENDERER, 
     817        TAG_CRYPTO, 
    813818        TAG_SMALL, 
    814819        TAG_STATIC 
  • src/server/sv_game.c

    r0 r190  
    435435                SV_MasterGameStat( VMA(1) ); 
    436436                return 0; 
     437        case G_RSA_GENMSG: 
     438                { 
     439                        struct rsa_public_key public_key; 
     440                        mpz_t message; 
     441                        unsigned char buffer[ RSA_KEY_LENGTH / 8 - 11 ]; 
     442                        int retval; 
     443                        Com_RandomBytes( buffer, RSA_KEY_LENGTH / 8 - 11 ); 
     444                        qnettle_mpz_init_set_str_256_u( message, RSA_KEY_LENGTH / 8 - 11, buffer ); 
     445                        qmpz_get_str( VMA(2), 16, message ); 
     446                        qrsa_public_key_init( &public_key ); 
     447                        qmpz_set_ui( public_key.e, RSA_PUBLIC_EXPONENT ); 
     448                        retval = qmpz_set_str( public_key.n, VMA(1), 16 ) + 1; 
     449                        if ( retval ) 
     450                        { 
     451                                qrsa_public_key_prepare( &public_key ); 
     452                                retval = qrsa_encrypt( &public_key, NULL, qnettle_random, RSA_KEY_LENGTH / 8 - 11, buffer, message ); 
     453                        } 
     454                        qrsa_public_key_clear( &public_key ); 
     455                        qmpz_get_str( VMA(3), 16, message ); 
     456                        qmpz_clear( message ); 
     457                        return retval; 
     458                } 
    437459 
    438460        //====================================