/* =========== ClientConnect Called when a player begins connecting to the server. Called again for every map change or tournement restart. The session information will be valid after exit. Return NULL if the client should be allowed, otherwise return a string with the reason for denial. Otherwise, the client will be sent the current gamestate and will eventually get to ClientBegin. firstTime will be qtrue the very first time a client connects to the server machine, but qfalse on map changes and tournement restarts. ============ */ char *ClientConnect( int clientNum, qboolean firstTime ) { char *value; gclient_t *client; char userinfo[ MAX_INFO_STRING ]; gentity_t *ent; char guid[ 33 ]; char reason[ MAX_STRING_CHARS ] = {""}; ent = &g_entities[ clientNum ]; client = &level.clients[ clientNum ]; ent->client = client; memset( client, 0, sizeof( *client ) ); trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) ); value = Info_ValueForKey( userinfo, "cl_guid" ); Q_strncpyz( guid, value, sizeof( guid ) ); // check for admin ban if( G_admin_ban_check( userinfo, reason, sizeof( reason ) ) ) { return va( "%s", reason ); } // IP filtering // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500 // recommanding PB based IP / GUID banning, the builtin system is pretty limited // check to see if they are on the banned IP list value = Info_ValueForKey( userinfo, "ip" ); Q_strncpyz( client->pers.ip, value, sizeof( client->pers.ip ) ); if( G_FilterPacket( value ) ) return "You are banned from this server."; // check for a password value = Info_ValueForKey( userinfo, "password" ); if( g_password.string[ 0 ] && Q_stricmp( g_password.string, "none" ) && strcmp( g_password.string, value ) != 0 ) return "Invalid password"; // add guid to session so we don't have to keep parsing userinfo everywhere if( !guid[0] ) { Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", sizeof( client->pers.guid ) ); } else { Q_strncpyz( client->pers.guid, guid, sizeof( client->pers.guid ) ); } // check for local client if( !strcmp( client->pers.ip, "localhost" ) ) client->pers.localClient = qtrue; client->pers.adminLevel = G_admin_level( ent ); client->pers.connected = CON_CONNECTING; // read or initialize the session data if( firstTime || level.newSession ) G_InitSessionData( client, userinfo ); G_ReadSessionData( client ); // get and distribute relevent paramters ClientUserinfoChanged( clientNum ); G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s\"\n", clientNum, client->pers.ip, client->pers.guid, client->pers.netname ); // don't do the "xxx connected" messages if they were caried over from previous level if( firstTime ) trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname ) ); // count current clients and rank for scoreboard CalculateRanks( ); G_admin_namelog_update( client, qfalse ); return NULL; }
/* =========== ClientConnect Called when a player begins connecting to the server. Called again for every map change or tournement restart. The session information will be valid after exit. Return NULL if the client should be allowed, otherwise return a string with the reason for denial. Otherwise, the client will be sent the current gamestate and will eventually get to ClientBegin. firstTime will be qtrue the very first time a client connects to the server machine, but qfalse on map changes and tournement restarts. ============ */ char *ClientConnect( int clientNum, qboolean firstTime ) { char *value; gclient_t *client; char userinfo[ MAX_INFO_STRING ]; gentity_t *ent; char guid[ 33 ]; char ip[ 16 ] = {""}; char reason[ MAX_STRING_CHARS ] = {""}; int i; int retval = 0; ent = &g_entities[ clientNum ]; trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) ); value = Info_ValueForKey( userinfo, "cl_guid" ); Q_strncpyz( guid, value, sizeof( guid ) ); // check for admin ban if( G_admin_ban_check( userinfo, reason, sizeof( reason ) ) ) { return va( "%s", reason ); } // IP filtering // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500 // recommanding PB based IP / GUID banning, the builtin system is pretty limited // check to see if they are on the banned IP list value = Info_ValueForKey( userinfo, "ip" ); i = 0; while( *value && i < sizeof( ip ) - 2 ) { if( *value != '.' && ( *value < '0' || *value > '9' ) ) break; ip[ i++ ] = *value; value++; } ip[ i ] = '\0'; if( G_FilterPacket( value ) ) return "You are banned from this server."; // check for a password value = Info_ValueForKey( userinfo, "password" ); if( g_password.string[ 0 ] && Q_stricmp( g_password.string, "none" ) && strcmp( g_password.string, value ) != 0 ) return "Invalid password"; // they can connect ent->client = level.clients + clientNum; client = ent->client; memset( client, 0, sizeof(*client) ); // add guid to session so we don't have to keep parsing userinfo everywhere if( !guid[0] ) { Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", sizeof( client->pers.guid ) ); } else { Q_strncpyz( client->pers.guid, guid, sizeof( client->pers.guid ) ); } Q_strncpyz( client->pers.ip, ip, sizeof( client->pers.ip ) ); client->pers.adminLevel = G_admin_level( ent ); client->pers.connected = CON_CONNECTING; // read or initialize the session data if( firstTime || level.newSession ) G_InitSessionData( client, userinfo ); G_ReadSessionData( client ); if( firstTime ) client->pers.firstConnect = qtrue; else client->pers.firstConnect = qfalse; // get and distribute relevent paramters ClientUserinfoChanged( clientNum ); G_admin_set_adminname( ent ); if( g_decolourLogfiles.integer ) { char decoloured[ MAX_STRING_CHARS ] = ""; if( g_decolourLogfiles.integer == 1 ) { Com_sprintf( decoloured, sizeof(decoloured), " (\"%s^7\")", client->pers.netname ); G_DecolorString( decoloured, decoloured ); G_LogPrintfColoured( "ClientConnect: %i [%s] (%s) \"%s^7\"%s\n", clientNum, client->pers.ip, client->pers.guid, client->pers.netname, decoloured ); } else { G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\"%s\n", clientNum, client->pers.ip, client->pers.guid, client->pers.netname, decoloured ); } } else { G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\"\n", clientNum, client->pers.ip, client->pers.guid, client->pers.netname ); } if( client->pers.adminLevel ) { G_LogPrintf( "ClientAuth: %i [%s] \"%s^7\" authenticated to admin level %i using GUID %s (^7%s)\n", clientNum, client->pers.ip, client->pers.netname, client->pers.adminLevel, client->pers.guid, client->pers.adminName ); } // don't do the "xxx connected" messages if they were caried over from previous level retval = G_admin_global_check(userinfo); if((retval & GLOBAL_FORCESPEC) || (retval & GLOBAL_MUTE) || (retval & GLOBAL_DENYBUILD)){trap_SendServerCommand( -1, va( "print \"^3!global: ^7%s^7 has restrictions\n\"", client->pers.netname ) );} else if(retval & GLOBAL_WHITELIST){trap_SendServerCommand( -1, va( "print \"^3!global: ^7%s^7 is whitelisted\n\"", client->pers.netname ) );} if(retval & GLOBAL_FORCESPEC){client->pers.specd = qtrue;} if(retval & GLOBAL_MUTE){client->pers.muted = qtrue;} if(retval & GLOBAL_DENYBUILD){client->pers.denyBuild = qtrue;} if( firstTime ) trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname ) ); // count current clients and rank for scoreboard CalculateRanks( ); G_admin_namelog_update( client, qfalse ); // if this is after !restart keepteams or !restart switchteams, apply said selection if ( client->sess.restartTeam != PTE_NONE ) { G_ChangeTeam( ent, client->sess.restartTeam ); client->sess.restartTeam = PTE_NONE; } return NULL; }