From d1d22ce47d43123b947159b6c54911b0573ec3fa Mon Sep 17 00:00:00 2001 From: Belonit <54427022+Belonit@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:48:31 +0300 Subject: [PATCH] Remove woldata.key serial verification --- code/language/language.h | 5 -- code/language/language.rc | 5 -- code/netdlg.h | 1 - code/netdlg2.cpp | 113 +------------------------------------- code/netdlg2.h | 1 - code/netshare.cpp | 2 +- code/session.h | 25 ++------- 7 files changed, 7 insertions(+), 145 deletions(-) diff --git a/code/language/language.h b/code/language/language.h index 3418f8c3e..30c15621e 100644 --- a/code/language/language.h +++ b/code/language/language.h @@ -570,8 +570,6 @@ #define TXT_CONSENT_REQUIRED 849 #define TXT_CLAN_NOSTART 850 #define TXT_DISABLED 851 -#define TXT_SERIALBANNED 852 -#define TXT_SERIALDUP 853 #define TXT_NOD04B 854 #define TXT_SEL_USER 855 #define TXT_GOLD 856 @@ -581,7 +579,6 @@ #define TXT_COLOR_IN_USE 860 #define TXT_NO_CLAN 861 #define TXT_LANGCODE 862 -#define TXT_SERIAL_DUP 863 #define TXT_SCENARIO_TOO_SMALL 864 #define TXT_DOWNLOAD_FAILED 865 #define TXT_GAME_RESTART 866 @@ -721,10 +718,8 @@ #define IDC_REDEPLOY_MCV 1000 #define TXT_FIRESTORM_NO_JOIN_TS 1001 #define IDC_MAPGEN_HILLS 1001 -#define TXT_SERIALUNKNOWN 1002 #define IDC_MAPGEN_TIME_OF_DAY 1002 #define IDC_SERIAL_ERROR_CORRECTION 1002 -#define TXT_SKUSERIALMISMATCH 1003 #define IDC_INTRO 1003 #define IDC_MAPGEN_PLAYERS 1003 #define IDC_SERIAL_DATA_COMPRESSION 1003 diff --git a/code/language/language.rc b/code/language/language.rc index e2c7cc1dd..d90a452f1 100644 --- a/code/language/language.rc +++ b/code/language/language.rc @@ -2031,8 +2031,6 @@ BEGIN TXT_CONSENT_REQUIRED "Since you are under the age of 13 our privacy policy requires that you send us a parental consent form to continue. Press 'yes' to open your web browser to this page." TXT_CLAN_NOSTART "To start a BattleClan tournament game there needs to be an even number of people from two clans. Everyone in the game must be in a clan." TXT_DISABLED "Your account has been temporarily disabled. Make sure the Email address you registered with is correct. Would you like to open your web browser to get more information?" - TXT_SERIALBANNED "(NOT USED ANYMORE)" - TXT_SERIALDUP "Your Serial number is currently in use. Would you like to open your web browser to get more information?" TXT_NOD04B "Taking out this weak GDI position will allow us to reclaim our Sarajevo temple without interruption. Move in under the cover of an ion storm when GDI's communications will be down. Take out the comm center before the storm subsides." TXT_SEL_USER "You must select a user to kick/ignore/ban them." TXT_GOLD "Gold" @@ -2042,7 +2040,6 @@ BEGIN TXT_COLOR_IN_USE "The requested color is already taken." TXT_NO_CLAN "You must be in a BattleClan to join this game." TXT_LANGCODE "0" - TXT_SERIAL_DUP "There are already 2 players with your serial# in that game." END STRINGTABLE DISCARDABLE @@ -2368,8 +2365,6 @@ BEGIN TXT_FIRESTORM_MUST_ENABLE "Firestorm must be enabled to join this game." TXT_FIRESTORM_NO_JOIN_TS "Unable to join original Tiberian Sun game with Firestorm enabled." - TXT_SERIALUNKNOWN "Your serial number was not found. This is most likely due to a mistyped serial number during installation. You must reinstall the game, specifying a valid serial number, to play online." - TXT_SKUSERIALMISMATCH "Your serial number is associated with a product other than Tiberian Sun. You must reinstall the game, specifying a valid Tiberian Sun serial number, to play online." TXT_WDT_TIBERIUM_RANGE "Very Scarce Tiberium" TXT_WDT_TIBERIUM_SCARCE "Scarce Tiberium" TXT_WDT_TIBERIUM_ABUNDANT "Abundant Tiberium" diff --git a/code/netdlg.h b/code/netdlg.h index 0b009acf2..11acaf09b 100644 --- a/code/netdlg.h +++ b/code/netdlg.h @@ -59,5 +59,4 @@ enum RejectType { REJECT_BY_OWNER, // game owner clicked "reject" REJECT_DISBANDED, // game was disbanded REJECT_MISMATCH, // "rules.ini" file mismatch. - REJECT_DUPLICATE_SERIAL, /// player's serial is a duplicate }; diff --git a/code/netdlg2.cpp b/code/netdlg2.cpp index 7e679fcbb..482dfc88a 100644 --- a/code/netdlg2.cpp +++ b/code/netdlg2.cpp @@ -65,7 +65,6 @@ bool Net2ReadyToGo(int load_game); int CurGame; int _netresponse; JoinStateType JoinState; -char SerialNumber[23]; bool Net2IsGameListActive = true; bool Net2GameStarted = false; @@ -518,92 +517,6 @@ int Net2SetHouseAndColor(char *who, int house, int color) } -/// -/// Fetches the serial number recorded in the registry. -/// A key that is missing, or that cannot be opened, simply leaves the buffer as it was -/// found -- the caller is expected to have primed it with something harmless. -/// -/// Buffer to fill in with the serial number found. -/// The registry key, beneath the local machine hive, to read from. -/// Be sure the buffer is big enough to hold an entire encrypted serial number. -static void Get_Serial_From_Registry(char * serial, char const * reg_key) -{ - if (reg_key && strlen(reg_key) != 0) { - HKEY rKey; - char keyname[256]; - strcpy(keyname, reg_key); - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &rKey) == ERROR_SUCCESS) { - DWORD type; - DWORD sizeOfBuffer = ENCRYPTION_STRING_LENGTH; - RegQueryValueEx(rKey, "Serial", NULL, &type, (BYTE *)serial, &sizeOfBuffer); - RegCloseKey(rKey); - } - } - serial[SERIAL_MAX-1] = 0; -} - - -/// -/// Fetches the decrypted serial number of this installation. -/// The scrambled serial is pulled out of the registry and then unpicked with the key file -/// that shipped alongside the game. This routine is used to identify the player to the -/// online service. -/// -/// Buffer to fill in with the decrypted serial number. -/// bool; Was the serial number recovered? Failure means the key file was not -/// available. -/// Be sure the destination buffer is big enough to hold an entire serial number. -bool Decrypt_Serial(char * buffer) -{ - char serial[ENCRYPTION_STRING_LENGTH]; - - bool encrypt = false; - - memset(serial, '0', SERIAL_MAX-1); - serial[SERIAL_MAX-1] = 0; - strcpy(buffer, serial); - memset(serial, 0, sizeof(serial)); - - Get_Serial_From_Registry(serial, "SOFTWARE\\Westwood\\Tiberian Sun"); - - strcpy(buffer, serial); - - int sign = encrypt ? 1 : -1; - - int number; - int temp; - int pos = 0; - - FILE *in = fopen("woldata.key", "r"); - - if (in == NULL) { - return(false); - } - - while ((number = fgetc(in)) != EOF) { - temp = serial[pos] - '0'; - temp %= 10; - number *= sign; - temp += number; - temp += 1000; - temp %= 10; - temp += '0'; - serial[pos] = temp; - - pos++; - if (pos == (int)strlen(serial)) { - pos = 0; - } - } - - fclose(in); - - strcpy(buffer, serial); - - return(true); -} - - /*********************************************************************************************** * Remote_Connect -- handles connecting this user to others * * * @@ -625,7 +538,6 @@ bool Net2Remote_Connect(void) RulesClass::Load_Art_INI(); ArtID = RulesClass::Get_Art_Unique_ID(); AIID = RulesClass::Get_AI_Unique_ID(); - Decrypt_Serial(SerialNumber); //------------------------------------------------------------------------ // Init network timing parameters; these values should work for both a @@ -852,7 +764,6 @@ bool Net2Remote_Connect(void) //------------------------------------------------------------------------ NodeNameType * who = new NodeNameType; strcpy(who->Name, Session.Handle); - strcpy(who->Player.Serial, SerialNumber); who->Player.House = Session.House; who->Player.Color = Session.ColorIdx; Session.Players.Add(who); @@ -1729,7 +1640,7 @@ BOOL CALLBACK MPlayer_Host_Dialog_Proc(HWND window, UINT message, WPARAM wparam, memset(&Session.GPacket, 0, sizeof(Session.GPacket)); Session.GPacket.Command = NET_REJECT_JOIN; Session.GPacket.Reject.Why = (int)REJECT_BY_OWNER; - Ipx.Send_Global_Message(&Session.GPacket, 455, 1, &Session.Players[index]->Address); + Ipx.Send_Global_Message(&Session.GPacket, sizeof(Session.GPacket), 1, &Session.Players[index]->Address); } } } @@ -1935,7 +1846,6 @@ static int Request_To_Join(int join_index) Session.GPacket.Command = NET_QUERY_JOIN; strcpy (Session.GPacket.Name, Session.Handle); - strcpy (Session.GPacket.Serial, SerialNumber); Session.GPacket.PlayerInfo.House = Session.House; Session.GPacket.PlayerInfo.Color = Session.ColorIdx; Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version(); @@ -2232,7 +2142,6 @@ bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address) mypacket.Command = NET_ANSWER_PLAYER; strcpy(mypacket.Name, Session.Handle); - strcpy(mypacket.Serial, SerialNumber); mypacket.PlayerInfo.House = Session.House; mypacket.PlayerInfo.Color = Session.ColorIdx; mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(Session.GameName); @@ -2474,7 +2383,6 @@ static void Get_Join_Responses(void) //.................................................................. who = new NodeNameType; strcpy(who->Name, Session.GPacket.Name); - strcpy(who->Player.Serial, Session.GPacket.Serial); who->Address = Session.GAddress; who->Player.House = Session.GPacket.PlayerInfo.House; who->Player.Color = Session.GPacket.PlayerInfo.Color; @@ -2629,9 +2537,6 @@ static void Get_Join_Responses(void) else if (why==REJECT_DISBANDED) { item = (char *)Fetch_String(TXT_GAME_CANCELLED); } - else if (why==REJECT_DUPLICATE_SERIAL) { - item = (char *)Fetch_String(TXT_SERIAL_DUP); - } if (item) { ODMessageBox(item, 0, Net2Callback, 0); } @@ -3029,21 +2934,6 @@ static void Get_Join_Responses(void) if (Session.GPacket.PlayerInfo.ArtCheatCheck != ArtID) { match = false; } if (Session.GPacket.PlayerInfo.BuildNumber != Build_Number()) { match = false; } } - int dups = 0; - for (i = 0; i < Session.Players.Count(); i++) { - if (!strcmp(Session.Players[i]->Player.Serial, Session.GPacket.Serial)) { - dups++; - } - } - - if (dups >= 2 && !resend) { - memset (&packet, 0, sizeof(GlobalPacketType)); - packet.Command = NET_REJECT_JOIN; - packet.Reject.Why = (int)REJECT_DUPLICATE_SERIAL; - Ipx.Send_Global_Message (&packet, sizeof (GlobalPacketType), 1, &Session.GAddress); - continue; - } - /* ** Don't allow joining if the rules.ini file doesn't appear to match. */ @@ -3105,7 +2995,6 @@ static void Get_Join_Responses(void) strcpy(who->Name, Session.GPacket.Name); who->Address = Session.GAddress; who->Player.House = Session.GPacket.PlayerInfo.House; - strcpy(who->Player.Serial, Session.GPacket.Serial); //.................................................................. // Set player's color; if requested color isn't used, give it to him; diff --git a/code/netdlg2.h b/code/netdlg2.h index 31a14d55d..ea505d1c4 100644 --- a/code/netdlg2.h +++ b/code/netdlg2.h @@ -24,7 +24,6 @@ void Net2EncodeGameopt(char *out); void Net2SetAccept(char *who, int status); int Net2GetAccept(char *who); int Net2SetHouseAndColor(char *who, int house, int color); -bool Decrypt_Serial(char *buffer); bool Net2Remote_Connect(void); bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address); void Net2DisplayGameList(void); diff --git a/code/netshare.cpp b/code/netshare.cpp index 1bee7959f..5a629c7b4 100644 --- a/code/netshare.cpp +++ b/code/netshare.cpp @@ -1495,7 +1495,7 @@ void Send_Preview_To_Guests(void) Call_Back(); GlobalPacketType response = {}; - int length = 455; + int length = sizeof(response); unsigned short product_id; if (Ipx.Get_Global_Message(&response, sizeof(response), &length, &sender_address, &product_id)) { diff --git a/code/session.h b/code/session.h index 771511d84..cbcbf1822 100644 --- a/code/session.h +++ b/code/session.h @@ -108,8 +108,8 @@ class SaveStreamClass; //........................................................................... #define DEFAULT_FRAME_SEND_RATE 3 -#define SERIAL_MAX 23 -#define ENCRYPTION_STRING_LENGTH 128 +// Retains the global packet layout used by existing clients. +#define GLOBAL_PACKET_RESERVED_SIZE 23 //--------------------------------------------------------------------------- // Enums @@ -213,7 +213,6 @@ struct NodeNameType { unsigned int LastTime; // last time we heard from this guy } Game; struct { - char Serial[SERIAL_MAX]; // int House; // "ActLike" House of this player int Color; // Color of this player int ID; // Actual House of this player @@ -268,7 +267,7 @@ struct RemoteFileTransferType { struct GlobalPacketType { NetCommandType Command; // One of the enum's defined above char Name[MPLAYER_NAME_MAX]; // Player or Game Name - char Serial[SERIAL_MAX]; // + char Reserved[GLOBAL_PACKET_RESERVED_SIZE]; // Reserved for global packet compatibility. union { struct { unsigned int IsOpen : 1; // 1 = game is open for joining @@ -286,22 +285,6 @@ struct GlobalPacketType { unsigned int BuildNumber; /// } PlayerInfo; struct { - #if 0 /// Fields that fall 13 bytes short of where TS keeps FileLength (offset 0x83), so the region is padded instead of mapped. - char Scenario[DESCRIP_MAX]; // Scenario Name - unsigned int Credits; // player's credits - unsigned int IsBases : 1; // 1 = bases are allowed - unsigned int IsTiberium : 1; // 1 = tiberium is allowed - unsigned int IsGoodies : 1; // 1 = goodies are allowed - unsigned int IsGhosties : 1; // 1 = ghosts are allowed - unsigned int OfficialScenario :1; // Is this scenario an official Westwood one? - unsigned char BuildLevel; // buildable level - unsigned char UnitCount; // max # units - unsigned char AIPlayers; // # of AI players allowed - int Seed; // random number seed - SpecialClass Special; // command-line options - unsigned int GameSpeed; // Game Speed - unsigned int Version; // version # common to all players - #endif char pad[0x83 - 0x2F]; unsigned int FileLength; // Length of scenario file to expect from host. char ShortFileName[13]; // Name of scenario file to expect from host @@ -356,6 +339,8 @@ struct GlobalPacketType { }; #pragma pack() +static_assert(sizeof(GlobalPacketType) == 455); + //........................................................................... // For finding sync bugs; filled in by the engine when certain conditions // are met; the pointers allow examination of objects in the debugger.