| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Renegade *
- * *
- * $Archive:: /Commando/Code/Commando/GameSpyBanList.cpp $*
- * *
- * Original Author:: Brian Hayes *
- * *
- * $Author:: Bhayes $*
- * *
- * $Modtime:: 3/15/02 2:55p $*
- * *
- * $Revision:: 3 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- //
- // Filename: GameSpyBanList.cpp
- // Author: Brian Hayes
- // Date: Mar 2002
- // Description: Maintains a list of banned nicknames/hashes/ipaddresses for GameSpy Servers
- //
- #include "cnetwork.h"
- #include "listnode.h"
- #include "GameSpyBanList.h"
- #include "ini.h"
- #include "registry.h"
- #include "rawfile.h"
- #include "gamespyauthmgr.h"
- #include "sctextobj.h"
- #include "consolemode.h"
- #include "gamesideservercontrol.h"
- cGameSpyBanList GameSpyBanList;
- BanEntry::BanEntry(const char *name, const char *ip, const char *hash_id, const char *ip_mask, bool rtype) {
- memset(nickname, 0, sizeof(nickname));
- ipaddress = 0;
- ipmask = 0xffffffff;
- memset(hashid, 0, sizeof(hashid));
- ruletype = rtype;
- if (name) {
- strncpy(nickname, name, sizeof(nickname) - 1);
- }
- if (ip) ipaddress = inet_addr(ip);
- if (hash_id) {
- strncpy(hashid, hash_id, sizeof(hashid) - 1);
- }
- if (ip_mask) {
- ipmask = inet_addr(ip_mask);
- if (!ipmask) ipmask = 0xffffffff;
- }
- }
- cGameSpyBanList::cGameSpyBanList() : BanList(NULL) {
- BanList = new List<BanEntry *> ();
- }
- cGameSpyBanList::~cGameSpyBanList() {
- BanList->Delete();
- delete BanList;
- }
- void cGameSpyBanList::Ban_User(const char *nickname, const char *challenge_response, DWORD ipaddr) {
- char *buff = NULL;
- char *q = NULL;
- FILE *outf = NULL;
- BanEntry *t = NULL;
- if (nickname && !challenge_response) {
- q = buff = new char[(strlen(nickname)*2)+1];
- const char *n = nickname;
- while (*n) {
- if (*n == '%') *q++ = '%';
- *q++ = *n++;
- }
- *q = 0;
- t = new BanEntry(buff);
- delete [] buff;
- } else if (challenge_response) {
- t = new BanEntry(NULL, NULL, challenge_response);
- } else if (ipaddr) {
- t = new BanEntry(NULL, cNetUtil::Address_To_String(ipaddr));
- } else {
- return;
- }
- BanList->Add_Tail(t);
- outf = fopen("banlist.txt", "at");
- if (outf) {
- fprintf(outf, "\"%s\" \"%s\" \"%s\" \"%s\" \"%s\"; \"%s\" console BAN\n", t->Get_Rule_Type() ? "Allow" : "Deny",
- t->Get_Nick_Name(), t->Get_Hash_ID(),
- t->Get_Ip_Address() ? cNetUtil::Address_To_String(t->Get_Ip_Address()) : "",
- t->Get_Ip_Address() ? "255.255.255.255" : "", nickname ? nickname : "");
- fclose(outf);
- }
- }
- void cGameSpyBanList::Think(void) {
- cPlayer *player = NULL;
- for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ()
- ; player_node != NULL; player_node = player_node->Next ()) {
-
- player = player_node->Data ();
- WWASSERT (player != NULL);
-
- if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
- continue;
- }
- if (player->Get_GameSpy_Kick_State() == GAMESPY_KICK_STATE_BEGIN &&
- TIMEGETTIME() - player->Get_GameSpy_Kick_State_Entry_Time_Ms() > 3000) {
- Final_Player_Kick(player->Get_Id());
- } else if (player->Get_GameSpy_Kick_State() == GAMESPY_KICK_STATE_INITIAL &&
- player->Get_GameSpy_Auth_State() == GAMESPY_AUTH_STATE_ACCEPTED) {
- if (Is_User_Banned(StringClass(player->Get_Name()), player->Get_GameSpy_Hash_Id(),
- player->Get_Ip_Address())) {
- Begin_Player_Kick(player->Get_Id());
- } else {
- player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_APPROVED);
- }
- }
- }
- }
- bool cGameSpyBanList::Begin_Player_Kick(int id) {
- cPlayer *player = cPlayerManager::Find_Player(id);
- if (player && player->Get_Is_Active().Is_True() && player->Is_Human()) {
- cScTextObj * p_message = new cScTextObj;
- p_message->Init(L"You've been kicked from the server. Please quit.", TEXT_MESSAGE_PRIVATE, true, HOST_TEXT_SENDER, player->Get_Id());
- player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_BEGIN);
- return true;
- }
- return false;
- }
- bool cGameSpyBanList::Final_Player_Kick(int id) {
- cPlayer *player = cPlayerManager::Find_Player(id);
- if (player && player->Get_Is_Active().Is_True() && player->Is_Human()) {
- StringClass user_name = player->Get_Name();
- ConsoleBox.Print("%s was kicked\n", user_name);
- player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_KICKED);
- cNetwork::Server_Kill_Connection(id);
- cNetwork::Cleanup_After_Client(id);
- return true;
- }
- return false;
- }
- bool cGameSpyBanList::Is_User_Banned(const char *nickname, const char *challenge_response,
- DWORD ipaddress) {
- BanEntry *t = BanList->First();
- bool ret = false;
- for (;t && t->Is_Valid(); t = t->Next()) {
- if (challenge_response && *challenge_response &&
- strcmp(challenge_response, t->Get_Hash_ID()) == 0) {
- ret = true;
- } else if (t->Get_Hash_ID() && strlen(t->Get_Hash_ID())){
- ret = false;
- continue;
- }
- if (ipaddress && t->Get_Ip_Address() && ((ipaddress & t->Get_Ip_Netmask()) ==
- (t->Get_Ip_Address() & t->Get_Ip_Netmask()))) {
- ret = true;
- } else if (t->Get_Ip_Address()) {
- ret = false;
- continue;
- }
- if (t->Get_Nick_Name() && nickname && strlen(t->Get_Nick_Name()) && strlen(nickname)) {
- char *a = strdup(t->Get_Nick_Name());
- char *b = strdup(nickname);
- _strupr(a); _strupr(b);
- //
- // This code means that you can put a BAN name in as
- // "%foo" == match on "foo" at the end of the string
- // "foo%" == match on "foo" at the beginning of the string
- // "%foo%" == match on "foo" anywhere in the string
- //
- // to match on a literal % in the nickname use %%
- //
- // Note the use of small var names to make it even more confusing
- if ( ((a[0] == '%') && (a[1] != '%')) &&
- ((a[strlen(a)-1] == '%') && (a[strlen(a)-2] != '%')) ) {
- a[0] = 0;
- a[strlen(&a[1])] = 0;
- Strip_Escapes(&a[1]);
- ret = (strstr(b, &a[1]) != NULL);
- } else if ((a[0] == '%') && (a[1] != '%')) {
- a[0] = 0;
- Strip_Escapes(&a[1]);
- if (strlen(b) > (strlen(&a[1])-1)) {
- ret = (strcmp(&b[strlen(b)-strlen(&a[1])], &a[1]) == 0);
- }
- } else if (strlen(a) > 1 && (a[strlen(a)-1] == '%') && (a[strlen(a)-2] != '%')) {
- a[strlen(a)-1] = 0;
- Strip_Escapes(a);
- if (strlen(b) > (strlen(a)-1)) {
- b[strlen(a)] = 0;
- ret = (strcmp(b, a) == 0);
- }
- } else {
- Strip_Escapes(a);
- ret = (strcmp(b, a) == 0);
- }
- free(a); free(b);
- }
- if (ret) {
- ret = !t->Get_Rule_Type();
- break;
- }
- }
- if (t && t->Is_Valid()) {
- // matched on a rule
- return ret;
- } else {
- // Everyone is good if they don't match a rule
- return false;
- }
- }
- void cGameSpyBanList::Strip_Escapes(char *var) {
- char *q = (char *)var;
- while ((q = strstr(q, "%%")) != NULL) {
- memmove(q, q+1, strlen(q));
- q++;
- }
- }
- void cGameSpyBanList::LoadBans(void) {
- char buff[512];
- FILE *outf = NULL;
- if (!BanList->Is_Empty()) BanList->Delete();
- outf = fopen("banlist.txt", "rt");
- if (!outf) return;
- buff[sizeof(buff)-1] = 0;
- while (fgets(buff, sizeof(buff)-1, outf)) {
- // Format of each line "ruletype" "nickname" "hashid" "ip" "netmask"
- char *nickname = NULL;
- char *ruletype = NULL;
- char *ip = NULL;
- char *hashid = NULL;
- char *ipmask = NULL;
- if (strlen(buff) < 3) continue;
- if (buff[0] == ';') continue;
- char *s = strchr(buff, '"');
- if (!s) continue;
- *s++ = 0;
- char *q = strchr(s, '"');
- if (!q) continue;
- *q++ = 0;
- ruletype = s;
- s = strchr(q, '"');
- if (!s) continue;
- *s++ = 0;
- q = strchr(s, '"');
- if (!q) continue;
- *q++ = 0;
- nickname = s;
- while (q) {
- s = strchr(q, '"');
- if (!s) break;
- *s++ = 0;
- q = strchr(s, '"');
- if (!q) break;
- *q++ = 0;
- hashid = s;
- s = strchr(q, '"');
- if (!s) break;
- *s++ = 0;
- q = strchr(s, '"');
- if (!q) break;
- *q++ = 0;
- ip = s;
- s = strchr(q, '"');
- if (!s) break;
- *s++ = 0;
- q = strchr(s, '"');
- if (!q) break;
- *q++ = 0;
- ipmask = s;
- break;
- }
- BanEntry *t = new BanEntry(nickname, ip, hashid, ipmask, stricmp(ruletype, "Allow") == 0);
- BanList->Add_Tail(t);
- }
- fclose(outf);
- }
|