From a08a3069c5a8125749f4cb07d683d45cbc1280e0 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 19 Mar 2024 18:09:35 +0100 Subject: [PATCH 01/14] Codechange: support storing std::string vectors/deques in the savegame --- src/saveload/saveload.cpp | 20 +++++++++++++++----- src/saveload/saveload.h | 10 ++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 28b65ba920..c78a6bbd27 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1244,13 +1244,17 @@ public: */ static size_t SlCalcLen(const void *storage, VarType conv, SaveLoadType cmd = SL_VAR) { - assert(cmd == SL_VAR || cmd == SL_REF); + assert(cmd == SL_VAR || cmd == SL_REF || cmd == SL_STDSTR); const SlStorageT *list = static_cast(storage); - int type_size = SlGetArrayLength(list->size()); - int item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); - return list->size() * item_size + type_size; + size_t type_size = SlGetArrayLength(list->size()); + if constexpr (std::is_same_v, SlStorageT> || std::is_same_v, SlStorageT>) { + return std::accumulate(list->begin(), list->end(), type_size, [](size_t sum, const std::string &str) { return sum + SlCalcStdStringLen(&str); }); + } else { + size_t item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); + return list->size() * item_size + type_size; + } } static void SlSaveLoadMember(SaveLoadType cmd, Tvar *item, VarType conv) @@ -1258,6 +1262,7 @@ public: switch (cmd) { case SL_VAR: SlSaveLoadConv(item, conv); break; case SL_REF: SlSaveLoadRef(item, conv); break; + case SL_STDSTR: SlStdString(item, conv); break; default: NOT_REACHED(); } @@ -1271,7 +1276,7 @@ public: */ static void SlSaveLoad(void *storage, VarType conv, SaveLoadType cmd = SL_VAR) { - assert(cmd == SL_VAR || cmd == SL_REF); + assert(cmd == SL_VAR || cmd == SL_REF || cmd == SL_STDSTR); SlStorageT *list = static_cast(storage); @@ -1290,6 +1295,7 @@ public: switch (cmd) { case SL_VAR: length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? SlReadUint32() : SlReadArrayLength(); break; case SL_REF: length = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? SlReadUint32() : SlReadArrayLength(); break; + case SL_STDSTR: length = SlReadArrayLength(); break; default: NOT_REACHED(); } @@ -1360,6 +1366,7 @@ static inline size_t SlCalcDequeLen(const void *deque, VarType conv) case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(deque, conv); case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(deque, conv); case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(deque, conv); + case SLE_VAR_STR: return SlStorageHelper::SlCalcLen(deque, conv, SL_STDSTR); default: NOT_REACHED(); } } @@ -1381,6 +1388,7 @@ static void SlDeque(void *deque, VarType conv) case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(deque, conv); break; case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(deque, conv); break; case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(deque, conv); break; + case SLE_VAR_STR: SlStorageHelper::SlSaveLoad(deque, conv, SL_STDSTR); break; default: NOT_REACHED(); } } @@ -1402,6 +1410,7 @@ static inline size_t SlCalcVectorLen(const void *vector, VarType conv) case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(vector, conv); case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(vector, conv); case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_STR: return SlStorageHelper::SlCalcLen(vector, conv, SL_STDSTR); default: NOT_REACHED(); } } @@ -1423,6 +1432,7 @@ static void SlVector(void *vector, VarType conv) case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(vector, conv); break; case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(vector, conv); break; case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_STR: SlStorageHelper::SlSaveLoad(vector, conv, SL_STDSTR); break; default: NOT_REACHED(); } } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 05ffac1c04..db9de245c9 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -944,6 +944,16 @@ inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t leng */ #define SLE_CONDDEQUE(base, variable, type, from, to) SLE_GENERAL(SL_DEQUE, base, variable, type, 0, from, to, 0) +/** + * Storage of a vector of #SL_VAR elements in some savegame versions. + * @param base Name of the class or struct containing the list. + * @param variable Name of the variable in the class or struct referenced by \a base. + * @param type Storage of the data in memory and in the savegame. + * @param from First savegame version that has the list. + * @param to Last savegame version that has the list. + */ +#define SLE_CONDVECTOR(base, variable, type, from, to) SLE_GENERAL(SL_VECTOR, base, variable, type, 0, from, to, 0) + /** * Storage of a variable in every version of a savegame. * @param base Name of the class or struct containing the variable. From 421fc7e0341bca5fcb112e3d0cc8a02f34baf30a Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 11:53:08 +0100 Subject: [PATCH 02/14] Codechange: introduce allow list infrastructure for companies --- src/command_type.h | 1 + src/company_base.h | 2 ++ src/company_cmd.cpp | 18 ++++++++++++++++++ src/company_cmd.h | 2 ++ src/network/core/config.h | 5 +++++ src/network/core/tcp_game.h | 3 ++- src/network/network.cpp | 4 +++- src/network/network_base.h | 1 + src/network/network_client.cpp | 3 +++ src/network/network_server.cpp | 27 +++++++++++++++++++++------ src/saveload/company_sl.cpp | 2 ++ src/saveload/saveload.h | 2 ++ src/tests/test_network_crypto.cpp | 1 + 13 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/command_type.h b/src/command_type.h index dae768104b..8f3cbedd93 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -294,6 +294,7 @@ enum Commands : uint16_t { CMD_CREATE_SUBSIDY, ///< create a new subsidy CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc. + CMD_COMPANY_ADD_ALLOW_LIST, ///< Used in multiplayer to add a client's public key to the company's allow list. CMD_CUSTOM_NEWS_ITEM, ///< create a custom news message CMD_CREATE_GOAL, ///< create a new goal CMD_REMOVE_GOAL, ///< remove a goal diff --git a/src/company_base.h b/src/company_base.h index 356a5fe058..cfd06f08f6 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -75,6 +75,8 @@ struct CompanyProperties { uint32_t president_name_2; ///< Parameter of #president_name_1 std::string president_name; ///< Name of the president if the user changed it. + NetworkAuthorizedKeys allow_list; ///< Public keys of clients that are allowed to join this company. + CompanyManagerFace face; ///< Face description of the president. Money money; ///< Money owned by the company. diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index a92ced1154..57126b65bb 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -979,6 +979,24 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID return CommandCost(); } +/** + * Add the given public key to the allow list of this company. + * @param flags Operation to perform. + * @param public_key The public key of the client to add. + * @return The cost of this operation or an error. + */ +CommandCost CmdCompanyAddAllowList(DoCommandFlag flags, const std::string &public_key) +{ + if (flags & DC_EXEC) { + if (Company::Get(_current_company)->allow_list.Add(public_key)) { + InvalidateWindowData(WC_CLIENT_LIST, 0); + SetWindowDirty(WC_COMPANY, _current_company); + } + } + + return CommandCost(); +} + /** * Change the company manager's face. * @param flags operation to perform diff --git a/src/company_cmd.h b/src/company_cmd.h index 8493549c58..5f818c4b8f 100644 --- a/src/company_cmd.h +++ b/src/company_cmd.h @@ -18,6 +18,7 @@ enum ClientID : uint32_t; enum Colours : uint8_t; CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id); +CommandCost CmdCompanyAddAllowList(DoCommandFlag flags, const std::string &public_key); CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company); CommandCost CmdRenameCompany(DoCommandFlag flags, const std::string &text); CommandCost CmdRenamePresident(DoCommandFlag flags, const std::string &text); @@ -25,6 +26,7 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlag flags, CompanyManagerFace cmf CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool primary, Colours colour); DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID | CMD_NO_EST, CMDT_SERVER_SETTING) +DEF_CMD_TRAIT(CMD_COMPANY_ADD_ALLOW_LIST, CmdCompanyAddAllowList, CMD_NO_EST, CMDT_SERVER_SETTING) DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, 0, CMDT_MONEY_MANAGEMENT) DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, 0, CMDT_OTHER_MANAGEMENT) DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, 0, CMDT_OTHER_MANAGEMENT) diff --git a/src/network/core/config.h b/src/network/core/config.h index e74cfb2fff..99e6a3bd94 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -96,5 +96,10 @@ static const uint NETWORK_MAX_GRF_COUNT = 255; * This is related to \c X25519_KEY_SIZE in the network crypto internals. */ static const uint NETWORK_SECRET_KEY_LENGTH = 32 * 2 + 1; +/** + * The maximum length of the hexadecimal encoded public keys, in bytes including '\0'. + * This is related to \c X25519_KEY_SIZE in the network crypto internals. + */ +static const uint NETWORK_PUBLIC_KEY_LENGTH = 32 * 2 + 1; #endif /* NETWORK_CORE_CONFIG_H */ diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index ce6f9bdcea..d29a17d8e0 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -202,7 +202,8 @@ protected: * Send information about a client: * uint32_t ID of the client (always unique on a server. 1 = server, 0 is invalid). * uint8_t ID of the company the client is playing as (255 for spectators). - * string Name of the client. + * string Name of the client. + * string Public key of the client. * @param p The packet that was just received. */ virtual NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p); diff --git a/src/network/network.cpp b/src/network/network.cpp index 2b0a79ba16..9c93ec8151 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -159,10 +159,12 @@ bool NetworkAuthorizedKeys::Contains(std::string_view key) const /** * Add the given key to the authorized keys, when it is not already contained. * @param key The key to add. - * @return \c true when the key was added, \c false when the key already existed. + * @return \c true when the key was added, \c false when the key already existed or the key was empty. */ bool NetworkAuthorizedKeys::Add(std::string_view key) { + if (key.empty()) return false; + auto iter = FindKey(this, key); if (iter != this->end()) return false; diff --git a/src/network/network_base.h b/src/network/network_base.h index 0b717163f7..0b3cbde7d2 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -24,6 +24,7 @@ extern NetworkClientInfoPool _networkclientinfo_pool; struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_pool> { ClientID client_id; ///< Client identifier (same as ClientState->client_id) std::string client_name; ///< Name of the client + std::string public_key; ///< The public key of the client. CompanyID client_playas; ///< As which company is this client playing (CompanyID) TimerGameEconomy::Date join_date; ///< Gamedate the client has joined diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index f6302a40e3..1e6dda3b57 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -608,6 +608,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac Debug(net, 9, "Client::Receive_SERVER_CLIENT_INFO(): client_id={}, playas={}", client_id, playas); std::string name = p.Recv_string(NETWORK_NAME_LENGTH); + std::string public_key = p.Recv_string(NETWORK_PUBLIC_KEY_LENGTH); if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; @@ -632,6 +633,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac ci->client_playas = playas; ci->client_name = name; + ci->public_key = public_key; InvalidateWindowData(WC_CLIENT_LIST, 0); @@ -651,6 +653,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac if (client_id == _network_own_client_id) this->SetInfo(ci); ci->client_name = name; + ci->public_key = public_key; InvalidateWindowData(WC_CLIENT_LIST, 0); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 8bd2f4c7e4..c1bfdde98c 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -332,6 +332,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientIn p->Send_uint32(ci->client_id); p->Send_uint8 (ci->client_playas); p->Send_string(ci->client_name); + p->Send_string(ci->public_key); this->SendPacket(std::move(p)); } @@ -959,6 +960,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet ci->join_date = TimerGameEconomy::date; ci->client_name = client_name; ci->client_playas = playas; + ci->public_key = this->peer_public_key; Debug(desync, 1, "client: {:08x}; {:02x}; {:02x}; {:02x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, (int)ci->client_playas, (int)ci->index); /* Make sure companies to which people try to join are not autocleaned */ @@ -1177,6 +1179,23 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet } } + if (cp.cmd == CMD_COMPANY_ADD_ALLOW_LIST) { + /* Maybe the client just got moved before allowing? */ + if (ci->client_id != CLIENT_ID_SERVER && ci->client_playas != cp.company) return NETWORK_RECV_STATUS_OKAY; + + std::string public_key = std::get<0>(EndianBufferReader::ToValue::Args>(cp.data)); + bool found = false; + for (const NetworkClientInfo *info : NetworkClientInfo::Iterate()) { + if (info->public_key == public_key) { + found = true; + break; + } + } + + /* Maybe the client just left? */ + if (!found) return NETWORK_RECV_STATUS_OKAY; + } + if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) NetworkReplaceCommandClientId(cp, this->client_id); this->incoming_queue.push_back(cp); @@ -1541,7 +1560,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet &p) if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY; /* Check if we require a password for this company */ - if (company_id != COMPANY_SPECTATOR && !_network_company_states[company_id].password.empty()) { + if (company_id != COMPANY_SPECTATOR && !Company::Get(company_id)->allow_list.Contains(this->peer_public_key) && !_network_company_states[company_id].password.empty()) { /* we need a password from the client - should be in this packet */ std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); @@ -2275,13 +2294,9 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */ ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); + Command::SendNet(STR_NULL, c->index, ci->public_key); Command::SendNet(STR_NULL, c->index, ci->client_name); - } - if (ci != nullptr) { - /* ci is nullptr when replaying, or for AIs. In neither case there is a client. - We need to send Admin port update here so that they first know about the new company - and then learn about a possibly joining client (see FS#6025) */ NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1); } } diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index ef83c6de03..82831ae5ff 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -450,6 +450,8 @@ static const SaveLoad _company_desc[] = { SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32), SLE_CONDSSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION), + SLE_CONDVECTOR(CompanyProperties, allow_list, SLE_STR, SLV_COMPANY_ALLOW_LIST, SL_MAX_VERSION), + SLE_VAR(CompanyProperties, face, SLE_UINT32), /* money was changed to a 64 bit field in savegame version 1. */ diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index db9de245c9..94c1303acc 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -379,6 +379,8 @@ enum SaveLoadVersion : uint16_t { SLV_SCRIPT_RANDOMIZER, ///< 333 PR#12063 v14.0-RC1 Save script randomizers. SLV_VEHICLE_ECONOMY_AGE, ///< 334 PR#12141 v14.0 Add vehicle age in economy year, for profit stats minimum age + SLV_COMPANY_ALLOW_LIST, ///< 335 PR#12337 Saving of list of client keys that are allowed to join this company. + SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/tests/test_network_crypto.cpp b/src/tests/test_network_crypto.cpp index 2c8734e11b..1cba244c9b 100644 --- a/src/tests/test_network_crypto.cpp +++ b/src/tests/test_network_crypto.cpp @@ -18,6 +18,7 @@ /* The length of the hexadecimal representation of a X25519 key must fit in the key length. */ static_assert(NETWORK_SECRET_KEY_LENGTH >= X25519_KEY_SIZE * 2 + 1); +static_assert(NETWORK_PUBLIC_KEY_LENGTH >= X25519_KEY_SIZE * 2 + 1); class MockNetworkSocketHandler : public NetworkSocketHandler { public: From 107be92b6b975668f4bdcf8ab78ace9e4676d3d9 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 13:38:37 +0100 Subject: [PATCH 03/14] Feature: authorize specific clients to join network company without password --- src/lang/english.txt | 1 + src/network/network.cpp | 25 +++++++++++++++++++++++++ src/network/network_base.h | 2 ++ src/network/network_crypto.cpp | 9 +++++++++ src/network/network_crypto.h | 1 + src/network/network_func.h | 1 + src/network/network_gui.cpp | 7 +++++++ src/toolbar_gui.cpp | 2 +- 8 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 6f24305f03..53892208a1 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2488,6 +2488,7 @@ STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Your player nam STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrative actions to perform for this client STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrative actions to perform for this company STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Join this company +STR_NETWORK_CLIENT_LIST_COMPANY_AUTHORIZE_TOOLTIP :{BLACK}Authorize this client to join your company STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send a message to this player STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send a message to all players of this company STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send a message to all spectators diff --git a/src/network/network.cpp b/src/network/network.cpp index 9c93ec8151..80144671aa 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -120,6 +120,28 @@ NetworkClientInfo::~NetworkClientInfo() return nullptr; } +/** + * Returns whether the given company can be joined by this client. + * @param company_id The id of the company. + * @return \c true when this company is allowed to join, otherwise \c false. + */ +bool NetworkClientInfo::CanJoinCompany(CompanyID company_id) const +{ + Company *c = Company::GetIfValid(company_id); + return c != nullptr && c->allow_list.Contains(this->public_key); +} + +/** + * Returns whether the given company can be joined by this client. + * @param company_id The id of the company. + * @return \c true when this company is allowed to join, otherwise \c false. + */ +bool NetworkCanJoinCompany(CompanyID company_id) +{ + NetworkClientInfo *info = NetworkClientInfo::GetByClientID(_network_own_client_id); + return info != nullptr && info->CanJoinCompany(company_id); +} + /** * Return the client state given it's client-identifier * @param client_id the ClientID to search for @@ -883,6 +905,9 @@ static void NetworkInitGameInfo() ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST; ci->client_name = _settings_client.network.client_name; + + NetworkAuthenticationClientHandler::EnsureValidSecretKeyAndUpdatePublicKey(_settings_client.network.client_secret_key, _settings_client.network.client_public_key); + ci->public_key = _settings_client.network.client_public_key; } /** diff --git a/src/network/network_base.h b/src/network/network_base.h index 0b3cbde7d2..497db78398 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -36,6 +36,8 @@ struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_p ~NetworkClientInfo(); static NetworkClientInfo *GetByClientID(ClientID client_id); + + bool CanJoinCompany(CompanyID company_id) const; }; #endif /* NETWORK_BASE_H */ diff --git a/src/network/network_crypto.cpp b/src/network/network_crypto.cpp index 3cea679869..38a1f9dd09 100644 --- a/src/network/network_crypto.cpp +++ b/src/network/network_crypto.cpp @@ -443,6 +443,15 @@ void CombinedAuthenticationServerHandler::Add(CombinedAuthenticationServerHandle this->SendResponse(); } +/** + * Ensures that the given secret key is valid, and when not overwrite it with a valid secret key. Then update the public key to be associated with the secret key. + * @param secret_key The location where the secret key is stored; can be overwritten when invalid. + * @param public_key The location where the public key is stored; can be overwritten when invalid. + */ +/* static */ void NetworkAuthenticationClientHandler::EnsureValidSecretKeyAndUpdatePublicKey(std::string &secret_key, std::string &public_key) +{ + X25519AuthorizedKeyClientHandler::GetValidSecretKeyAndUpdatePublicKey(secret_key, public_key); +} /** * Create a NetworkAuthenticationClientHandler. diff --git a/src/network/network_crypto.h b/src/network/network_crypto.h index b63c90d8a0..74424860a9 100644 --- a/src/network/network_crypto.h +++ b/src/network/network_crypto.h @@ -248,6 +248,7 @@ public: */ virtual bool ReceiveEnableEncryption(struct Packet &p) = 0; + static void EnsureValidSecretKeyAndUpdatePublicKey(std::string &secret_key, std::string &public_key); static std::unique_ptr Create(std::shared_ptr password_handler, std::string &secret_key, std::string &public_key); }; diff --git a/src/network/network_func.h b/src/network/network_func.h index 66b4660169..a071571796 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -73,6 +73,7 @@ void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci); bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name); +bool NetworkCanJoinCompany(CompanyID company_id); void NetworkServerDoMove(ClientID client_id, CompanyID company_id); void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string); void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, ClientID from_id, int64_t data = 0, bool from_admin = false); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 54584a1a51..7172ae0a0f 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1541,6 +1541,12 @@ private: ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, client_id); } + static void OnClickClientAuthorize([[maybe_unused]] NetworkClientListWindow *w, [[maybe_unused]] Point pt, ClientID client_id) + { + AutoRestoreBackup cur_company(_current_company, NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas); + Command::Post(NetworkClientInfo::GetByClientID(client_id)->public_key); + } + /** * Part of RebuildList() to create the information for a single company. * @param company_id The company to build the list for. @@ -1563,6 +1569,7 @@ private: if (_network_server) this->buttons[line_count].push_back(std::make_unique(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id)); if (_network_own_client_id != ci->client_id) this->buttons[line_count].push_back(std::make_unique(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat)); + if (_network_own_client_id != ci->client_id && client_playas != COMPANY_SPECTATOR && !ci->CanJoinCompany(client_playas)) this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_COMPANY_AUTHORIZE_TOOLTIP, COLOUR_GREEN, ci->client_id, &NetworkClientListWindow::OnClickClientAuthorize)); if (ci->client_id == _network_own_client_id) { this->player_self_index = this->line_count; diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 58589da48c..1f71b10671 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -97,7 +97,7 @@ static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user */ class DropDownListCompanyItem : public DropDownIcon, true>> { public: - DropDownListCompanyItem(CompanyID company, bool shaded) : DropDownIcon, true>>(SPR_COMPANY_ICON, COMPANY_SPRITE_COLOUR(company), NetworkCompanyIsPassworded(company) ? SPR_LOCK : SPR_EMPTY, PAL_NONE, STR_NULL, company, false, shaded) + DropDownListCompanyItem(CompanyID company, bool shaded) : DropDownIcon, true>>(SPR_COMPANY_ICON, COMPANY_SPRITE_COLOUR(company), NetworkCanJoinCompany(company) ? SPR_EMPTY : SPR_LOCK, PAL_NONE, STR_NULL, company, false, shaded) { SetDParam(0, company); SetDParam(1, company); From 910bb7320648c09654a91028c8e5c67560a5ff48 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 18:40:34 +0100 Subject: [PATCH 04/14] Remove: autoclean_unprotected settings; all companies will be protected --- src/console_cmds.cpp | 10 +--------- src/network/network_server.cpp | 23 +++++++---------------- src/settings_type.h | 3 +-- src/table/settings/network_settings.ini | 8 -------- 4 files changed, 9 insertions(+), 35 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 62a8e18c6d..3f21474051 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1829,13 +1829,6 @@ DEF_CONSOLE_CMD(ConCompanies) SetDParam(0, c->index); std::string company_name = GetString(STR_COMPANY_NAME); - const char *password_state = ""; - if (c->is_ai) { - password_state = "AI"; - } else if (_network_server) { - password_state = _network_company_states[c->index].password.empty() ? "unprotected" : "protected"; - } - std::string colour = GetString(STR_COLOUR_DARK_BLUE + _company_colours[c->index]); IConsolePrint(CC_INFO, "#:{}({}) Company Name: '{}' Year Founded: {} Money: {} Loan: {} Value: {} (T:{}, R:{}, P:{}, S:{}) {}", c->index + 1, colour, company_name, @@ -1844,7 +1837,7 @@ DEF_CONSOLE_CMD(ConCompanies) c->group_all[VEH_ROAD].num_vehicle, c->group_all[VEH_AIRCRAFT].num_vehicle, c->group_all[VEH_SHIP].num_vehicle, - password_state); + c->is_ai ? "AI" : ""); } return true; @@ -2821,7 +2814,6 @@ void IConsoleStdLibRegister() IConsole::AliasRegister("pause_on_join", "setting pause_on_join %+"); IConsole::AliasRegister("autoclean_companies", "setting autoclean_companies %+"); IConsole::AliasRegister("autoclean_protected", "setting autoclean_protected %+"); - IConsole::AliasRegister("autoclean_unprotected", "setting autoclean_unprotected %+"); IConsole::AliasRegister("restart_game_year", "setting restart_game_year %+"); IConsole::AliasRegister("min_players", "setting min_active_clients %+"); IConsole::AliasRegister("reload_cfg", "setting reload_cfg %+"); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index c1bfdde98c..3e7bafb0c3 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1633,11 +1633,10 @@ void NetworkUpdateClientInfo(ClientID client_id) NetworkAdminClientUpdate(ci); } -/** Check if the server has autoclean_companies activated - * Two things happen: - * 1) If a company is not protected, it is closed after 1 year (for example) - * 2) If a company is protected, protection is disabled after 3 years (for example) - * (and item 1. happens a year later) +/** + * Remove companies that have not been used depending on the \c autoclean_companies setting + * and values for \c autoclean_protected, which removes any company, and + * \c autoclean_novehicles, which removes companies without vehicles. */ static void NetworkAutoCleanCompanies() { @@ -1672,19 +1671,11 @@ static void NetworkAutoCleanCompanies() /* The company is empty for one month more */ if (c->months_empty != std::numeric_limitsmonths_empty)>::max()) c->months_empty++; - /* Is the company empty for autoclean_unprotected-months, and is there no protection? */ - if (_settings_client.network.autoclean_unprotected != 0 && c->months_empty > _settings_client.network.autoclean_unprotected && _network_company_states[c->index].password.empty()) { + /* Is the company empty for autoclean_protected-months? */ + if (_settings_client.network.autoclean_protected != 0 && c->months_empty > _settings_client.network.autoclean_protected) { /* Shut the company down */ Command::Post(CCA_DELETE, c->index, CRR_AUTOCLEAN, INVALID_CLIENT_ID); - IConsolePrint(CC_INFO, "Auto-cleaned company #{} with no password.", c->index + 1); - } - /* Is the company empty for autoclean_protected-months, and there is a protection? */ - if (_settings_client.network.autoclean_protected != 0 && c->months_empty > _settings_client.network.autoclean_protected && !_network_company_states[c->index].password.empty()) { - /* Unprotect the company */ - _network_company_states[c->index].password.clear(); - IConsolePrint(CC_INFO, "Auto-removed protection from company #{}.", c->index + 1); - c->months_empty = 0; - NetworkServerUpdateCompanyPassworded(c->index, false); + IConsolePrint(CC_INFO, "Auto-cleaned company #{}.", c->index + 1); } /* Is the company empty for autoclean_novehicles-months, and has no vehicles? */ if (_settings_client.network.autoclean_novehicles != 0 && c->months_empty > _settings_client.network.autoclean_novehicles && !HasBit(has_vehicles, c->index)) { diff --git a/src/settings_type.h b/src/settings_type.h index 017a74664e..cfc6ad7c33 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -324,8 +324,7 @@ struct NetworkSettings { std::string connect_to_ip; ///< default for the "Add server" query std::string network_id; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use - uint8_t autoclean_unprotected; ///< remove passwordless companies after this many months - uint8_t autoclean_protected; ///< remove the password from passworded companies after this many months + uint8_t autoclean_protected; ///< Remove companies after this many months. uint8_t autoclean_novehicles; ///< remove companies with no vehicles after this many months uint8_t max_companies; ///< maximum amount of companies uint8_t max_clients; ///< maximum amount of clients diff --git a/src/table/settings/network_settings.ini b/src/table/settings/network_settings.ini index a96c2c9a5c..2138bd87ea 100644 --- a/src/table/settings/network_settings.ini +++ b/src/table/settings/network_settings.ini @@ -192,14 +192,6 @@ var = network.autoclean_companies flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY def = false -[SDTC_VAR] -var = network.autoclean_unprotected -type = SLE_UINT8 -flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY -def = 12 -min = 0 -max = 240 - [SDTC_VAR] var = network.autoclean_protected type = SLE_UINT8 From c7e35a6b5c1ef1c31d79eef467e5c5672acc4472 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 18:55:43 +0100 Subject: [PATCH 05/14] Change: remove company passwords over client allow lists --- src/network/network.cpp | 12 ++------ src/network/network_client.cpp | 4 +-- src/network/network_func.h | 2 -- src/network/network_gui.cpp | 20 ++++--------- src/network/network_internal.h | 2 -- src/network/network_server.cpp | 52 ++++++++-------------------------- src/network/network_type.h | 5 ---- 7 files changed, 21 insertions(+), 76 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 80144671aa..4e98ed87b9 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -61,7 +61,6 @@ bool _network_server; ///< network-server is active bool _network_available; ///< is network mode available? bool _network_dedicated; ///< are we a dedicated server? bool _is_network_server; ///< Does this client wants to be a network-server? -NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies. ClientID _network_own_client_id; ///< Our client identifier. ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client. uint8_t _network_reconnect; ///< Reconnect timeout @@ -79,7 +78,6 @@ uint32_t _sync_seed_2; ///< Second part of the seed. #endif uint32_t _sync_frame; ///< The frame to perform the sync check. bool _network_first_time; ///< Whether we have finished joining or not. -CompanyMask _network_company_passworded; ///< Bitmask of the password status of all companies. static_assert((int)NETWORK_COMPANY_NAME_LENGTH == MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH); @@ -281,9 +279,9 @@ std::string GenerateCompanyPasswordHash(const std::string &password, const std:: * @param company_id id of the company we want to check the 'passworded' flag for. * @return true if the company requires a password. */ -bool NetworkCompanyIsPassworded(CompanyID company_id) +bool NetworkCompanyIsPassworded([[maybe_unused]] CompanyID company_id) { - return HasBit(_network_company_passworded, company_id); + return false; } /* This puts a text-message to the console, or in the future, the chat-box, @@ -681,10 +679,6 @@ void NetworkClose(bool close_admins) NetworkFreeLocalCommandQueue(); - delete[] _network_company_states; - _network_company_states = nullptr; - _network_company_passworded = 0; - InitializeNetworkPools(close_admins); } @@ -979,7 +973,6 @@ bool NetworkServerStart() Debug(net, 5, "Starting listeners for incoming server queries"); NetworkUDPServerListen(); - _network_company_states = new NetworkCompanyState[MAX_COMPANIES]; _network_server = true; _networking = true; _frame_counter = 0; @@ -989,7 +982,6 @@ bool NetworkServerStart() _network_own_client_id = CLIENT_ID_SERVER; _network_clients_connected = 0; - _network_company_passworded = 0; NetworkInitGameInfo(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1e6dda3b57..a6e6f3277b 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1261,12 +1261,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(P return NETWORK_RECV_STATUS_OKAY; } -NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet &p) +NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet &) { if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - static_assert(sizeof(_network_company_passworded) <= sizeof(uint16_t)); - _network_company_passworded = p.Recv_uint16(); SetWindowClassesDirty(WC_COMPANY); Debug(net, 9, "Client::Receive_SERVER_COMPANY_UPDATE()"); diff --git a/src/network/network_func.h b/src/network/network_func.h index a071571796..753b853666 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -24,8 +24,6 @@ #include "../company_type.h" #include "../string_type.h" -extern NetworkCompanyState *_network_company_states; - extern ClientID _network_own_client_id; extern ClientID _redirect_console_to_client; extern uint8_t _network_reconnect; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 7172ae0a0f..f302a2d7c8 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1428,7 +1428,6 @@ using ClientButton = Button; struct NetworkClientListWindow : Window { private: ClientListWidgets query_widget; ///< During a query this tracks what widget caused the query. - CompanyID join_company; ///< During query for company password, this stores what company we wanted to join. ClientID dd_client_id; ///< During admin dropdown, track which client this was for. CompanyID dd_company_id; ///< During admin dropdown, track which company this was for. @@ -1464,10 +1463,6 @@ private: if (_network_server) { NetworkServerDoMove(CLIENT_ID_SERVER, company_id); MarkWholeScreenDirty(); - } else if (NetworkCompanyIsPassworded(company_id)) { - w->query_widget = WID_CL_COMPANY_JOIN; - w->join_company = company_id; - ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_PASSWORD); } else { NetworkClientRequestMove(company_id); } @@ -1551,14 +1546,15 @@ private: * Part of RebuildList() to create the information for a single company. * @param company_id The company to build the list for. * @param client_playas The company the client is joined as. + * @param can_join_company Whether this company can be joined by us. */ - void RebuildListCompany(CompanyID company_id, CompanyID client_playas) + void RebuildListCompany(CompanyID company_id, CompanyID client_playas, bool can_join_company) { ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); if (_network_server) this->buttons[line_count].push_back(std::make_unique(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR)); this->buttons[line_count].emplace_back(chat_button); - if (client_playas != company_id) this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai)); + if (can_join_company) this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai)); this->line_count += 1; @@ -1604,18 +1600,18 @@ private: } if (client_playas != COMPANY_SPECTATOR) { - this->RebuildListCompany(client_playas, client_playas); + this->RebuildListCompany(client_playas, client_playas, false); } /* Companies */ for (const Company *c : Company::Iterate()) { if (c->index == client_playas) continue; - this->RebuildListCompany(c->index, client_playas); + this->RebuildListCompany(c->index, client_playas, own_ci != nullptr && c->allow_list.Contains(own_ci->public_key)); } /* Spectators */ - this->RebuildListCompany(COMPANY_SPECTATOR, client_playas); + this->RebuildListCompany(COMPANY_SPECTATOR, client_playas, client_playas != COMPANY_SPECTATOR); this->vscroll->SetCount(this->line_count); } @@ -1919,10 +1915,6 @@ public: this->InvalidateData(); break; } - - case WID_CL_COMPANY_JOIN: - NetworkClientRequestMove(this->join_company, str); - break; } } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 66dea11be4..72622b4f94 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -93,8 +93,6 @@ extern std::string _network_server_name; extern uint8_t _network_reconnect; -extern CompanyMask _network_company_passworded; - void NetworkQueryServer(const std::string &connection_string); void GetBindAddresses(NetworkAddressList *addresses, uint16_t port); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 3e7bafb0c3..b0ff3cf164 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -485,7 +485,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword() this->status = STATUS_AUTH_COMPANY; NetworkClientInfo *ci = this->GetInfo(); - if (!Company::IsValidID(ci->client_playas) || _network_company_states[ci->client_playas].password.empty()) { + if (!Company::IsValidID(ci->client_playas)) { return this->SendWelcome(); } @@ -847,8 +847,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyUpdate() auto p = std::make_unique(this, PACKET_SERVER_COMPANY_UPDATE); - static_assert(sizeof(_network_company_passworded) <= sizeof(uint16_t)); - p->Send_uint16(_network_company_passworded); + p->Send_uint16(0); this->SendPacket(std::move(p)); return NETWORK_RECV_STATUS_OKAY; } @@ -939,6 +938,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet if (!Company::IsValidHumanID(playas)) { return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH); } + + if (!Company::Get(playas)->allow_list.Contains(this->peer_public_key)) { + /* When we're not authorized, just bump us to a spectator. */ + playas = COMPANY_SPECTATOR; + } break; } @@ -1021,7 +1025,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(P return NETWORK_RECV_STATUS_OKAY; } -NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &p) +NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &) { if (this->status != STATUS_AUTH_COMPANY) { return this->SendError(NETWORK_ERROR_NOT_EXPECTED); @@ -1029,18 +1033,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWOR Debug(net, 9, "client[{}] Receive_CLIENT_COMPANY_PASSWORD()", this->client_id); - std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); - - /* Check company password. Allow joining if we cleared the password meanwhile. - * Also, check the company is still valid - client could be moved to spectators - * in the middle of the authorization process */ - CompanyID playas = this->GetInfo()->client_playas; - if (Company::IsValidID(playas) && !_network_company_states[playas].password.empty() && - _network_company_states[playas].password.compare(password) != 0) { - /* Password is invalid */ - return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); - } - return this->SendWelcome(); } @@ -1559,16 +1551,9 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet &p) /* Check if the company is valid, we don't allow moving to AI companies */ if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY; - /* Check if we require a password for this company */ - if (company_id != COMPANY_SPECTATOR && !Company::Get(company_id)->allow_list.Contains(this->peer_public_key) && !_network_company_states[company_id].password.empty()) { - /* we need a password from the client - should be in this packet */ - std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); - - /* Incorrect password sent, return! */ - if (_network_company_states[company_id].password.compare(password) != 0) { - Debug(net, 2, "Wrong password from client-id #{} for company #{}", this->client_id, company_id + 1); - return NETWORK_RECV_STATUS_OKAY; - } + if (company_id != COMPANY_SPECTATOR && !Company::Get(company_id)->allow_list.Contains(this->peer_public_key)) { + Debug(net, 2, "Wrong public key from client-id #{} for company #{}", this->client_id, company_id + 1); + return NETWORK_RECV_STATUS_OKAY; } /* if we get here we can move the client */ @@ -1758,17 +1743,8 @@ bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_na * @param password The new password. * @param already_hashed Is the given password already hashed? */ -void NetworkServerSetCompanyPassword(CompanyID company_id, const std::string &password, bool already_hashed) +void NetworkServerSetCompanyPassword([[maybe_unused]] CompanyID company_id, [[maybe_unused]] const std::string &password, [[maybe_unused]] bool already_hashed) { - if (!Company::IsValidHumanID(company_id)) return; - - if (already_hashed) { - _network_company_states[company_id].password = password; - } else { - _network_company_states[company_id].password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed); - } - - NetworkServerUpdateCompanyPassworded(company_id, !_network_company_states[company_id].password.empty()); } /** @@ -2088,7 +2064,6 @@ void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded) { if (NetworkCompanyIsPassworded(company_id) == passworded) return; - SB(_network_company_passworded, company_id, 1, !!passworded); SetWindowClassesDirty(WC_COMPANY); for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { @@ -2278,9 +2253,6 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) if (!_network_server) return; - _network_company_states[c->index].password.clear(); - NetworkServerUpdateCompanyPassworded(c->index, false); - if (ci != nullptr) { /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */ ci->client_playas = c->index; diff --git a/src/network/network_type.h b/src/network/network_type.h index 4f8617ff37..0ab7d51558 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -70,11 +70,6 @@ struct NetworkCompanyStats { bool ai; ///< Is this company an AI }; -/** Some state information of a company, especially for servers */ -struct NetworkCompanyState { - std::string password; ///< The password for the company -}; - struct NetworkClientInfo; /** The type of password we're asking for. */ From abf6b6828ff839bc08f4a6d71d3e5adf96f3fbe1 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:10:39 +0100 Subject: [PATCH 06/14] Cleanup: remove company password related network packets --- src/network/core/tcp_admin.h | 4 +- src/network/core/tcp_game.cpp | 8 --- src/network/core/tcp_game.h | 39 --------------- src/network/network_admin.cpp | 4 +- src/network/network_client.cpp | 88 ++------------------------------- src/network/network_client.h | 7 +-- src/network/network_server.cpp | 90 +++------------------------------- src/network/network_server.h | 5 -- 8 files changed, 16 insertions(+), 229 deletions(-) diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h index 4320a06f66..e14cd060d8 100644 --- a/src/network/core/tcp_admin.h +++ b/src/network/core/tcp_admin.h @@ -333,7 +333,7 @@ protected: * string Name of the company. * string Name of the companies manager. * uint8_t Main company colour. - * bool Company is password protected. + * bool Company is protected. * uint32_t Year the company was inaugurated. * bool Company is an AI. * @param p The packet that was just received. @@ -347,7 +347,7 @@ protected: * string Name of the company. * string Name of the companies manager. * uint8_t Main company colour. - * bool Company is password protected. + * bool Company is protected. * uint8_t Quarters of bankruptcy. * uint8_t Owner of share 1. * uint8_t Owner of share 2. diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 5b7ef1dfca..c466ceedee 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -83,10 +83,8 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet &p) case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p); case PACKET_CLIENT_IDENTIFY: return this->Receive_CLIENT_IDENTIFY(p); case PACKET_SERVER_AUTH_REQUEST: return this->Receive_SERVER_AUTH_REQUEST(p); - case PACKET_SERVER_NEED_COMPANY_PASSWORD: return this->Receive_SERVER_NEED_COMPANY_PASSWORD(p); case PACKET_CLIENT_AUTH_RESPONSE: return this->Receive_CLIENT_AUTH_RESPONSE(p); case PACKET_SERVER_ENABLE_ENCRYPTION: return this->Receive_SERVER_ENABLE_ENCRYPTION(p); - case PACKET_CLIENT_COMPANY_PASSWORD: return this->Receive_CLIENT_COMPANY_PASSWORD(p); case PACKET_SERVER_WELCOME: return this->Receive_SERVER_WELCOME(p); case PACKET_CLIENT_GETMAP: return this->Receive_CLIENT_GETMAP(p); case PACKET_SERVER_WAIT: return this->Receive_SERVER_WAIT(p); @@ -104,7 +102,6 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet &p) case PACKET_CLIENT_CHAT: return this->Receive_CLIENT_CHAT(p); case PACKET_SERVER_CHAT: return this->Receive_SERVER_CHAT(p); case PACKET_SERVER_EXTERNAL_CHAT: return this->Receive_SERVER_EXTERNAL_CHAT(p); - case PACKET_CLIENT_SET_PASSWORD: return this->Receive_CLIENT_SET_PASSWORD(p); case PACKET_CLIENT_SET_NAME: return this->Receive_CLIENT_SET_NAME(p); case PACKET_CLIENT_QUIT: return this->Receive_CLIENT_QUIT(p); case PACKET_CLIENT_ERROR: return this->Receive_CLIENT_ERROR(p); @@ -118,7 +115,6 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet &p) case PACKET_CLIENT_NEWGRFS_CHECKED: return this->Receive_CLIENT_NEWGRFS_CHECKED(p); case PACKET_SERVER_MOVE: return this->Receive_SERVER_MOVE(p); case PACKET_CLIENT_MOVE: return this->Receive_CLIENT_MOVE(p); - case PACKET_SERVER_COMPANY_UPDATE: return this->Receive_SERVER_COMPANY_UPDATE(p); case PACKET_SERVER_CONFIG_UPDATE: return this->Receive_SERVER_CONFIG_UPDATE(p); default: @@ -166,10 +162,8 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet &) { NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_IDENTIFY); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_AUTH_REQUEST); } -NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_COMPANY_PASSWORD); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_AUTH_RESPONSE); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_ENABLE_ENCRYPTION); } -NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_PASSWORD); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_WELCOME); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GETMAP); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_WAIT(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_WAIT); } @@ -187,7 +181,6 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet &) { r NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_CHAT); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CHAT(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_CHAT); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_EXTERNAL_CHAT); } -NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_PASSWORD); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_NAME); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_QUIT); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_ERROR); } @@ -201,7 +194,6 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_NEWGRFS_CHECKED); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_MOVE(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_MOVE); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_MOVE); } -NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_UPDATE); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_CONFIG_UPDATE); } void NetworkGameSocketHandler::DeferDeletion() diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index d29a17d8e0..5795221a2e 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -71,10 +71,6 @@ enum PacketGameType : uint8_t { PACKET_SERVER_CHECK_NEWGRFS, ///< Server sends NewGRF IDs and MD5 checksums for the client to check. PACKET_CLIENT_NEWGRFS_CHECKED, ///< Client acknowledges that it has all required NewGRFs. - /* Checking the company passwords. */ - PACKET_SERVER_NEED_COMPANY_PASSWORD, ///< Server requests the (hashed) company password. - PACKET_CLIENT_COMPANY_PASSWORD, ///< Client sends the (hashed) company password. - /* The server welcomes the authenticated client and sends information of other clients. */ PACKET_SERVER_WELCOME, ///< Server welcomes you and gives you your #ClientID. PACKET_SERVER_CLIENT_INFO, ///< Server sends you information about a client. @@ -119,9 +115,7 @@ enum PacketGameType : uint8_t { PACKET_SERVER_MOVE, ///< Server tells everyone that someone is moved to another company. /* Configuration updates. */ - PACKET_CLIENT_SET_PASSWORD, ///< A client (re)sets its company's password. PACKET_CLIENT_SET_NAME, ///< A client changes its name. - PACKET_SERVER_COMPANY_UPDATE, ///< Information (password) of a company changed. PACKET_SERVER_CONFIG_UPDATE, ///< Some network configuration important to the client changed. /* A client quitting. */ @@ -225,14 +219,6 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p); - /** - * Indication to the client that the server needs a company password: - * uint32_t Generation seed. - * string Network ID of the server. - * @param p The packet that was just received. - */ - virtual NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p); - /** * Send the response to the authentication request: * 32 * uint8_t Public key of the client. @@ -250,19 +236,9 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_ENABLE_ENCRYPTION(Packet &p); - /** - * Send a password to the server to authorize - * uint8_t Password type (see NetworkPasswordType). - * string The password. - * @param p The packet that was just received. - */ - virtual NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet &p); - /** * The client is joined and ready to receive their map: * uint32_t Own client ID. - * uint32_t Generation seed. - * string Network ID of the server. * @param p The packet that was just received. */ virtual NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p); @@ -402,13 +378,6 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_EXTERNAL_CHAT(Packet &p); - /** - * Set the password for the clients current company: - * string The password. - * @param p The packet that was just received. - */ - virtual NetworkRecvStatus Receive_CLIENT_SET_PASSWORD(Packet &p); - /** * Gives the client a new name: * string New name of the client. @@ -498,18 +467,10 @@ protected: /** * Request the server to move this client into another company: * uint8_t ID of the company the client wants to join. - * string Password, if the company is password protected. * @param p The packet that was just received. */ virtual NetworkRecvStatus Receive_CLIENT_MOVE(Packet &p); - /** - * Update the clients knowledge of which company is password protected: - * uint16_t Bitwise representation of each company - * @param p The packet that was just received. - */ - virtual NetworkRecvStatus Receive_SERVER_COMPANY_UPDATE(Packet &p); - /** * Update the clients knowledge of the max settings: * uint8_t Maximum number of companies allowed. diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 82cebe186e..f2a035cc00 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -328,7 +328,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company SetDParam(0, c->index); p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_uint8 (c->colour); - p->Send_bool (NetworkCompanyIsPassworded(c->index)); + p->Send_bool (true); p->Send_uint32(c->inaugurated_year.base()); p->Send_bool (c->is_ai); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy @@ -353,7 +353,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyUpdate(const Compa SetDParam(0, c->index); p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_uint8 (c->colour); - p->Send_bool (NetworkCompanyIsPassworded(c->index)); + p->Send_bool (true); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy this->SendPacket(std::move(p)); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index a6e6f3277b..3ed70a7054 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -313,11 +313,6 @@ ClientNetworkGameSocketHandler * ClientNetworkGameSocketHandler::my_client = nul /** Last frame we performed an ack. */ static uint32_t last_ack_frame; -/** One bit of 'entropy' used to generate a salt for the company passwords. */ -static uint32_t _password_game_seed; -/** The other bit of 'entropy' used to generate a salt for the company passwords. */ -static std::string _password_server_id; - /** Maximum number of companies of the currently joined server. */ static uint8_t _network_server_max_companies; /** The current name of the server you are on. */ @@ -388,20 +383,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendAuthResponse() return NETWORK_RECV_STATUS_OKAY; } -/** - * Set the company password as requested. - * @param password The company password. - */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyPassword(const std::string &password) -{ - Debug(net, 9, "Client::SendCompanyPassword()"); - - auto p = std::make_unique(my_client, PACKET_CLIENT_COMPANY_PASSWORD); - p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed)); - my_client->SendPacket(std::move(p)); - return NETWORK_RECV_STATUS_OKAY; -} - /** Request the map from the server. */ NetworkRecvStatus ClientNetworkGameSocketHandler::SendGetMap() { @@ -485,21 +466,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendError(NetworkErrorCode err return NETWORK_RECV_STATUS_OKAY; } -/** - * Tell the server that we like to change the password of the company. - * @param password The new password. - */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetPassword(const std::string &password) -{ - Debug(net, 9, "Client::SendSetPassword()"); - - auto p = std::make_unique(my_client, PACKET_CLIENT_SET_PASSWORD); - - p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed)); - my_client->SendPacket(std::move(p)); - return NETWORK_RECV_STATUS_OKAY; -} - /** * Tell the server that we like to change the name of the client. * @param name The new name. @@ -547,15 +513,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const std::string &pa /** * Ask the server to move us. * @param company The company to move to. - * @param password The password of the company to move to. */ -NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company, const std::string &password) +NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company) { Debug(net, 9, "Client::SendMove(): company={}", company); auto p = std::make_unique(my_client, PACKET_CLIENT_MOVE); p->Send_uint8(company); - p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed)); my_client->SendPacket(std::move(p)); return NETWORK_RECV_STATUS_OKAY; } @@ -796,34 +760,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTI return this->SendIdentify(); } -class CompanyPasswordRequest : public NetworkAuthenticationPasswordRequest { - virtual void Reply(const std::string &password) override - { - MyClient::SendCompanyPassword(password); - } -}; - -NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p) -{ - if (this->status < STATUS_ENCRYPTED || this->status >= STATUS_AUTH_COMPANY) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - Debug(net, 9, "Client::status = AUTH_COMPANY"); - this->status = STATUS_AUTH_COMPANY; - - Debug(net, 9, "Client::Receive_SERVER_NEED_COMPANY_PASSWORD()"); - - _password_game_seed = p.Recv_uint32(); - _password_server_id = p.Recv_string(NETWORK_SERVER_ID_LENGTH); - if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - - if (!_network_join.company_password.empty()) { - return SendCompanyPassword(_network_join.company_password); - } - - ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD, std::make_shared()); - - return NETWORK_RECV_STATUS_OKAY; -} - NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet &p) { if (this->status < STATUS_ENCRYPTED || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; @@ -834,10 +770,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet Debug(net, 9, "Client::Receive_SERVER_WELCOME(): client_id={}", _network_own_client_id); - /* Initialize the password hash salting variables, even if they were previously. */ - _password_game_seed = p.Recv_uint32(); - _password_server_id = p.Recv_string(NETWORK_SERVER_ID_LENGTH); - /* Start receiving the map */ return SendGetMap(); } @@ -1261,17 +1193,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(P return NETWORK_RECV_STATUS_OKAY; } -NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet &) -{ - if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - - SetWindowClassesDirty(WC_COMPANY); - - Debug(net, 9, "Client::Receive_SERVER_COMPANY_UPDATE()"); - - return NETWORK_RECV_STATUS_OKAY; -} - /** * Check the connection's state, i.e. is the connection still up? */ @@ -1331,9 +1252,9 @@ void NetworkClientSendRcon(const std::string &password, const std::string &comma * @param pass the password, is only checked on the server end if a password is needed. * @return void */ -void NetworkClientRequestMove(CompanyID company_id, const std::string &pass) +void NetworkClientRequestMove(CompanyID company_id, [[maybe_unused]] const std::string &pass) { - MyClient::SendMove(company_id, pass); + MyClient::SendMove(company_id); } /** @@ -1447,9 +1368,8 @@ void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const * Set/Reset company password on the client side. * @param password Password to be set. */ -void NetworkClientSetCompanyPassword(const std::string &password) +void NetworkClientSetCompanyPassword([[maybe_unused]] const std::string &password) { - MyClient::SendSetPassword(password); } /** diff --git a/src/network/network_client.h b/src/network/network_client.h index 8d68b8d8ba..0c2dda37eb 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -27,7 +27,6 @@ private: STATUS_AUTH_GAME, ///< Last action was requesting game (server) password. STATUS_ENCRYPTED, ///< The game authentication has completed and from here on the connection to the server is encrypted. STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs. - STATUS_AUTH_COMPANY, ///< Last action was requesting company password. STATUS_AUTHORIZED, ///< The client is authorized at the server. STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map. STATUS_MAP, ///< The client is downloading the map. @@ -48,7 +47,6 @@ protected: NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p) override; NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p) override; NetworkRecvStatus Receive_SERVER_ENABLE_ENCRYPTION(Packet &p) override; - NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p) override; NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p) override; NetworkRecvStatus Receive_SERVER_WAIT(Packet &p) override; NetworkRecvStatus Receive_SERVER_MAP_BEGIN(Packet &p) override; @@ -68,7 +66,6 @@ protected: NetworkRecvStatus Receive_SERVER_RCON(Packet &p) override; NetworkRecvStatus Receive_SERVER_CHECK_NEWGRFS(Packet &p) override; NetworkRecvStatus Receive_SERVER_MOVE(Packet &p) override; - NetworkRecvStatus Receive_SERVER_COMPANY_UPDATE(Packet &p) override; NetworkRecvStatus Receive_SERVER_CONFIG_UPDATE(Packet &p) override; static NetworkRecvStatus SendNewGRFsOk(); @@ -90,13 +87,11 @@ public: static NetworkRecvStatus SendAck(); static NetworkRecvStatus SendAuthResponse(); - static NetworkRecvStatus SendCompanyPassword(const std::string &password); static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data); - static NetworkRecvStatus SendSetPassword(const std::string &password); static NetworkRecvStatus SendSetName(const std::string &name); static NetworkRecvStatus SendRCon(const std::string &password, const std::string &command); - static NetworkRecvStatus SendMove(CompanyID company, const std::string &password); + static NetworkRecvStatus SendMove(CompanyID company); static bool IsConnected(); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index b0ff3cf164..11b000d203 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -413,8 +413,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck() this->status = STATUS_NEWGRFS_CHECK; if (_grfconfig == nullptr) { - /* There are no NewGRFs, continue with the company password. */ - return this->SendNeedCompanyPassword(); + /* There are no NewGRFs, so they're welcome. */ + return this->SendWelcome(); } auto p = std::make_unique(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU); @@ -473,39 +473,13 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendEnableEncryption() return NETWORK_RECV_STATUS_OKAY; } -/** Request the company password. */ -NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword() -{ - Debug(net, 9, "client[{}] SendNeedCompanyPassword()", this->client_id); - - /* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */ - if (this->status != STATUS_NEWGRFS_CHECK) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET); - - Debug(net, 9, "client[{}] status = AUTH_COMPANY", this->client_id); - this->status = STATUS_AUTH_COMPANY; - - NetworkClientInfo *ci = this->GetInfo(); - if (!Company::IsValidID(ci->client_playas)) { - return this->SendWelcome(); - } - - /* Reset 'lag' counters */ - this->last_frame = this->last_frame_server = _frame_counter; - - auto p = std::make_unique(this, PACKET_SERVER_NEED_COMPANY_PASSWORD); - p->Send_uint32(_settings_game.game_creation.generation_seed); - p->Send_string(_settings_client.network.network_id); - this->SendPacket(std::move(p)); - return NETWORK_RECV_STATUS_OKAY; -} - /** Send the client a welcome message with some basic information. */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome() { Debug(net, 9, "client[{}] SendWelcome()", this->client_id); - /* Invalid packet when status is anything but STATUS_AUTH_COMPANY. */ - if (this->status != STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET); + /* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */ + if (this->status != STATUS_NEWGRFS_CHECK) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET); Debug(net, 9, "client[{}] status = AUTHORIZED", this->client_id); this->status = STATUS_AUTHORIZED; @@ -517,8 +491,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome() auto p = std::make_unique(this, PACKET_SERVER_WELCOME); p->Send_uint32(this->client_id); - p->Send_uint32(_settings_game.game_creation.generation_seed); - p->Send_string(_settings_client.network.network_id); this->SendPacket(std::move(p)); /* Transmit info about all the active clients */ @@ -840,18 +812,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMove(ClientID client_id, C return NETWORK_RECV_STATUS_OKAY; } -/** Send an update about the company password states. */ -NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyUpdate() -{ - Debug(net, 9, "client[{}] SendCompanyUpdate()", this->client_id); - - auto p = std::make_unique(this, PACKET_SERVER_COMPANY_UPDATE); - - p->Send_uint16(0); - this->SendPacket(std::move(p)); - return NETWORK_RECV_STATUS_OKAY; -} - /** Send an update about the max company/spectator counts. */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate() { @@ -885,7 +845,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED Debug(net, 9, "client[{}] Receive_CLIENT_NEWGRFS_CHECKED()", this->client_id); - return this->SendNeedCompanyPassword(); + return this->SendWelcome(); } NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p) @@ -1025,17 +985,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(P return NETWORK_RECV_STATUS_OKAY; } -NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &) -{ - if (this->status != STATUS_AUTH_COMPANY) { - return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - } - - Debug(net, 9, "client[{}] Receive_CLIENT_COMPANY_PASSWORD()", this->client_id); - - return this->SendWelcome(); -} - NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet &) { /* The client was never joined.. so this is impossible, right? @@ -1096,10 +1045,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet & NetworkAdminClientInfo(this, true); /* also update the new client with our max values */ - this->SendConfigUpdate(); - - /* quickly update the syncing client with company details */ - return this->SendCompanyUpdate(); + return this->SendConfigUpdate(); } /* Wrong status for this packet, give a warning to client, and close connection */ @@ -1464,22 +1410,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet &p) return NETWORK_RECV_STATUS_OKAY; } -NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet &p) -{ - if (this->status != STATUS_ACTIVE) { - /* Illegal call, return error and ignore the packet */ - return this->SendError(NETWORK_ERROR_NOT_EXPECTED); - } - - Debug(net, 9, "client[{}] Receive_CLIENT_SET_PASSWORD()", this->client_id); - - std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); - const NetworkClientInfo *ci = this->GetInfo(); - - NetworkServerSetCompanyPassword(ci->client_playas, password); - return NETWORK_RECV_STATUS_OKAY; -} - NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet &p) { if (this->status != STATUS_ACTIVE) { @@ -1866,7 +1796,6 @@ void NetworkServer_Tick(bool send_frame) break; case NetworkClientSocket::STATUS_AUTH_GAME: - case NetworkClientSocket::STATUS_AUTH_COMPANY: /* These don't block? */ if (lag > _settings_client.network.max_password_time) { IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it took longer than {} ticks to enter the password.", cs->client_id, cs->GetClientIP(), _settings_client.network.max_password_time); @@ -2012,10 +1941,9 @@ void NetworkServerShowStatusToConsole() { static const char * const stat_str[] = { "inactive", - "authorizing (server password)", + "authorizing", "identifing client", "checking NewGRFs", - "authorizing (company password)", "authorized", "waiting", "loading map", @@ -2066,10 +1994,6 @@ void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded) SetWindowClassesDirty(WC_COMPANY); - for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { - if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate(); - } - NetworkAdminCompanyUpdate(Company::GetIfValid(company_id)); } diff --git a/src/network/network_server.h b/src/network/network_server.h index 6b75a123f9..2c91b7cfe1 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -30,13 +30,11 @@ protected: NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p) override; NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet &p) override; NetworkRecvStatus Receive_CLIENT_AUTH_RESPONSE(Packet &p) override; - NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet &p) override; NetworkRecvStatus Receive_CLIENT_GETMAP(Packet &p) override; NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet &p) override; NetworkRecvStatus Receive_CLIENT_ACK(Packet &p) override; NetworkRecvStatus Receive_CLIENT_COMMAND(Packet &p) override; NetworkRecvStatus Receive_CLIENT_CHAT(Packet &p) override; - NetworkRecvStatus Receive_CLIENT_SET_PASSWORD(Packet &p) override; NetworkRecvStatus Receive_CLIENT_SET_NAME(Packet &p) override; NetworkRecvStatus Receive_CLIENT_QUIT(Packet &p) override; NetworkRecvStatus Receive_CLIENT_ERROR(Packet &p) override; @@ -49,7 +47,6 @@ protected: NetworkRecvStatus SendWelcome(); NetworkRecvStatus SendAuthRequest(); NetworkRecvStatus SendEnableEncryption(); - NetworkRecvStatus SendNeedCompanyPassword(); public: /** Status of a client */ @@ -58,7 +55,6 @@ public: STATUS_AUTH_GAME, ///< The client is authorizing with game (server) password. STATUS_IDENTIFY, ///< The client is identifying itself. STATUS_NEWGRFS_CHECK, ///< The client is checking NewGRFs. - STATUS_AUTH_COMPANY, ///< The client is authorizing with company password. STATUS_AUTHORIZED, ///< The client is authorized. STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map. STATUS_MAP, ///< The client is downloading the map. @@ -104,7 +100,6 @@ public: NetworkRecvStatus SendFrame(); NetworkRecvStatus SendSync(); NetworkRecvStatus SendCommand(const CommandPacket &cp); - NetworkRecvStatus SendCompanyUpdate(); NetworkRecvStatus SendConfigUpdate(); static void Send(); From d7933529ec3d3dff5d51e592eb68be6eb80794cc Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:19:12 +0100 Subject: [PATCH 07/14] Cleanup: remove command line option for company password --- docs/openttd.6 | 5 ----- src/network/network.cpp | 6 ++---- src/network/network_client.h | 1 - src/network/network_func.h | 2 +- src/openttd.cpp | 9 ++------- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/docs/openttd.6 b/docs/openttd.6 index 0319f98cc8..9e8ff63b34 100644 --- a/docs/openttd.6 +++ b/docs/openttd.6 @@ -20,7 +20,6 @@ .Op Fl M Ar musicset .Op Fl n Ar host Ns Oo : Ns Ar port Oc Ns Op # Ns Ar company .Op Fl p Ar password -.Op Fl P Ar password .Op Fl q Ar savegame .Op Fl r Ar width Ns x Ns Ar height .Op Fl s Ar driver @@ -100,10 +99,6 @@ play as. Password used to join server. Only useful with .Fl n . -.It Fl P Ar password -Password used to join company. -Only useful with -.Fl n . .It Fl q Ar savegame Write some information about the specified savegame and exit. .It Fl Q diff --git a/src/network/network.cpp b/src/network/network.cpp index 4e98ed87b9..b2c48d4276 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -825,7 +825,7 @@ public: /** * Join a client to the server at with the given connection string. - * The default for the passwords is \c nullptr. When the server or company needs a + * The default for the passwords is \c nullptr. When the server needs a * password and none is given, the user is asked to enter the password in the GUI. * This function will return false whenever some information required to join is not * correct such as the company number or the client's name, or when there is not @@ -837,10 +837,9 @@ public: * @param connection_string The IP address, port and company number to join as. * @param default_company The company number to join as when none is given. * @param join_server_password The password for the server. - * @param join_company_password The password for the company. * @return Whether the join has started. */ -bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password, const std::string &join_company_password) +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password) { Debug(net, 9, "NetworkClientConnectGame(): connection_string={}", connection_string); @@ -853,7 +852,6 @@ bool NetworkClientConnectGame(const std::string &connection_string, CompanyID de _network_join.connection_string = resolved_connection_string; _network_join.company = join_as; _network_join.server_password = join_server_password; - _network_join.company_password = join_company_password; if (_game_mode == GM_MENU) { /* From the menu we can immediately continue with the actual join. */ diff --git a/src/network/network_client.h b/src/network/network_client.h index 0c2dda37eb..47fb81b3cd 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -112,7 +112,6 @@ struct NetworkJoinInfo { std::string connection_string; ///< The address of the server to join. CompanyID company; ///< The company to join. std::string server_password; ///< The password of the server to join. - std::string company_password; ///< The password of the company to join. }; extern NetworkJoinInfo _network_join; diff --git a/src/network/network_func.h b/src/network/network_func.h index 753b853666..8cb15ae2ee 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -49,7 +49,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); -bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password = "", const std::string &join_company_password = ""); +bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password = ""); void NetworkClientJoinGame(); void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); void NetworkClientSendRcon(const std::string &password, const std::string &command); diff --git a/src/openttd.cpp b/src/openttd.cpp index 898ea24832..055b396b2a 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -170,7 +170,6 @@ static void ShowHelp() " -G seed = Set random seed\n" " -n host[:port][#company]= Join network game\n" " -p password = Password to join server\n" - " -P password = Password to join company\n" " -D [host][:port] = Start dedicated server\n" #if !defined(_WIN32) " -f = Fork into the background (dedicated only)\n" @@ -386,7 +385,6 @@ struct AfterNewGRFScan : NewGRFScanCallback { uint16_t dedicated_port = 0; ///< Port for the dedicated server. std::string connection_string; ///< Information about the server to connect to std::string join_server_password; ///< The password to join the server with. - std::string join_company_password; ///< The password to join the company with. bool save_config = true; ///< The save config setting. /** @@ -450,7 +448,7 @@ struct AfterNewGRFScan : NewGRFScanCallback { LoadIntroGame(); _switch_mode = SM_NONE; - NetworkClientConnectGame(connection_string, COMPANY_NEW_COMPANY, join_server_password, join_company_password); + NetworkClientConnectGame(connection_string, COMPANY_NEW_COMPANY, join_server_password); } /* After the scan we're not used anymore. */ @@ -487,7 +485,7 @@ static std::vector CreateOptions() { std::vector options; /* Options that require a parameter. */ - for (char c : "GIMPSbcmnpqrstv") options.push_back({ .type = ODF_HAS_VALUE, .id = c, .shortname = c }); + for (char c : "GIMSbcmnpqrstv") options.push_back({ .type = ODF_HAS_VALUE, .id = c, .shortname = c }); #if !defined(_WIN32) options.push_back({ .type = ODF_HAS_VALUE, .id = 'f', .shortname = 'f' }); #endif @@ -560,9 +558,6 @@ int openttd_main(std::span arguments) case 'p': scanner->join_server_password = mgo.opt; break; - case 'P': - scanner->join_company_password = mgo.opt; - break; case 'r': ParseResolution(&resolution, mgo.opt); break; case 't': scanner->startyear = atoi(mgo.opt); break; case 'd': { From 5d4f35d851d258a955ece740a58bdc553e8b38fe Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:26:08 +0100 Subject: [PATCH 08/14] Cleanup: remove client side password checks when moving to a different company --- src/company_gui.cpp | 7 ------- src/console_cmds.cpp | 9 ++++----- src/network/network_client.cpp | 4 +--- src/network/network_func.h | 2 +- src/widgets/network_widget.h | 1 - 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 2e387b4996..586fb1e186 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -2519,9 +2519,6 @@ struct CompanyWindow : Window if (_network_server) { NetworkServerDoMove(CLIENT_ID_SERVER, company); MarkWholeScreenDirty(); - } else if (NetworkCompanyIsPassworded(company)) { - /* ask for the password */ - ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, this, CS_ALPHANUMERAL, QSF_PASSWORD); } else { /* just send the join command */ NetworkClientRequestMove(company); @@ -2569,10 +2566,6 @@ struct CompanyWindow : Window case WID_C_COMPANY_NAME: Command::Post(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME, str); break; - - case WID_C_COMPANY_JOIN: - NetworkClientRequestMove((CompanyID)this->window_number, str); - break; } } diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 3f21474051..be317e3b68 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -914,7 +914,7 @@ DEF_CONSOLE_CMD(ConClientNickChange) DEF_CONSOLE_CMD(ConJoinCompany) { if (argc < 2) { - IConsolePrint(CC_HELP, "Request joining another company. Usage: 'join []'."); + IConsolePrint(CC_HELP, "Request joining another company. Usage: 'join '."); IConsolePrint(CC_HELP, "For valid company-id see company list, use 255 for spectator."); return true; } @@ -943,9 +943,8 @@ DEF_CONSOLE_CMD(ConJoinCompany) return true; } - /* Check if the company requires a password */ - if (NetworkCompanyIsPassworded(company_id) && argc < 3) { - IConsolePrint(CC_ERROR, "Company {} requires a password to join.", company_id + 1); + if (!info->CanJoinCompany(company_id)) { + IConsolePrint(CC_ERROR, "You are not allowed to join this company."); return true; } @@ -953,7 +952,7 @@ DEF_CONSOLE_CMD(ConJoinCompany) if (_network_server) { NetworkServerDoMove(CLIENT_ID_SERVER, company_id); } else { - NetworkClientRequestMove(company_id, NetworkCompanyIsPassworded(company_id) ? argv[2] : ""); + NetworkClientRequestMove(company_id); } return true; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 3ed70a7054..78695d8552 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1249,10 +1249,8 @@ void NetworkClientSendRcon(const std::string &password, const std::string &comma /** * Notify the server of this client wanting to be moved to another company. * @param company_id id of the company the client wishes to be moved to. - * @param pass the password, is only checked on the server end if a password is needed. - * @return void */ -void NetworkClientRequestMove(CompanyID company_id, [[maybe_unused]] const std::string &pass) +void NetworkClientRequestMove(CompanyID company_id) { MyClient::SendMove(company_id); } diff --git a/src/network/network_func.h b/src/network/network_func.h index 8cb15ae2ee..de7036a30a 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -51,7 +51,7 @@ void NetworkUpdateClientInfo(ClientID client_id); void NetworkClientsToSpectators(CompanyID cid); bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const std::string &join_server_password = ""); void NetworkClientJoinGame(); -void NetworkClientRequestMove(CompanyID company, const std::string &pass = ""); +void NetworkClientRequestMove(CompanyID company); void NetworkClientSendRcon(const std::string &password, const std::string &command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h index 276874f92e..7efbb236eb 100644 --- a/src/widgets/network_widget.h +++ b/src/widgets/network_widget.h @@ -86,7 +86,6 @@ enum ClientListWidgets : WidgetID { WID_CL_CLIENT_NAME_EDIT, ///< Edit button for client name. WID_CL_MATRIX, ///< Company/client list. WID_CL_SCROLLBAR, ///< Scrollbar for company/client list. - WID_CL_COMPANY_JOIN, ///< Used for QueryWindow when a company has a password. WID_CL_CLIENT_COMPANY_COUNT, ///< Count of clients and companies. }; From 1df632787dff2670dd65c9ce68917b55a7d754f2 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:36:09 +0100 Subject: [PATCH 09/14] Cleanup: remove UI for changing the password --- src/company_cmd.cpp | 5 -- src/company_gui.cpp | 26 +------ src/console_cmds.cpp | 50 ------------- src/lang/english.txt | 12 ---- src/network/network.cpp | 19 ----- src/network/network_client.cpp | 8 --- src/network/network_client.h | 1 - src/network/network_func.h | 1 - src/network/network_gui.cpp | 126 --------------------------------- src/network/network_gui.h | 1 - src/network/network_server.cpp | 24 ------- src/network/network_server.h | 2 - src/openttd.cpp | 6 -- src/widgets/company_widget.h | 2 - src/widgets/network_widget.h | 11 --- src/window_type.h | 7 -- 16 files changed, 1 insertion(+), 300 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 57126b65bb..770c20011b 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -889,8 +889,6 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID break; } - /* Send new companies, before potentially setting the password. Otherwise, - * the password update could be sent when the company is not yet known. */ NetworkAdminCompanyNew(c); NetworkServerNewCompany(c, ci); @@ -898,9 +896,6 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID if (client_id == _network_own_client_id) { assert(_local_company == COMPANY_SPECTATOR); SetLocalCompany(c->index); - if (!_settings_client.network.default_company_pass.empty()) { - NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); - } /* In network games, we need to try setting the company manager face here to sync it to all clients. * If a favorite company manager face is selected, choose it. Otherwise, use a random face. */ diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 586fb1e186..ae94110e55 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -2148,9 +2148,6 @@ static constexpr NWidgetPart _nested_company_widgets[] = { /* Multi player buttons. */ NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 0), - NWidget(NWID_VERTICAL), SetPIPRatio(1, 0, 0), - NWidget(WWT_EMPTY, COLOUR_GREY, WID_C_HAS_PASSWORD), SetFill(0, 0), - EndContainer(), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_HOSTILE_TAKEOVER), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_HOSTILE_TAKEOVER), SetDataTip(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON, STR_COMPANY_VIEW_HOSTILE_TAKEOVER_TOOLTIP), @@ -2159,7 +2156,6 @@ static constexpr NWidgetPart _nested_company_widgets[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_GIVE_MONEY), SetDataTip(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON, STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP), EndContainer(), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_MULTIPLAYER), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_PASSWORD), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_COMPANY_VIEW_PASSWORD_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP), EndContainer(), EndContainer(), @@ -2192,10 +2188,6 @@ struct CompanyWindow : Window /** Display planes in the company window. */ enum CompanyWindowPlanes { - /* Display planes of the #WID_C_SELECT_MULTIPLAYER selection widget. */ - CWP_MP_C_PWD = 0, ///< Display the company password button. - CWP_MP_C_JOIN, ///< Display the join company button. - /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */ CWP_VB_VIEW = 0, ///< Display the view button CWP_VB_BUILD, ///< Display the build button @@ -2236,7 +2228,7 @@ struct CompanyWindow : Window reinit |= this->GetWidget(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0); /* Multiplayer buttons. */ - reinit |= this->GetWidget(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN)); + reinit |= this->GetWidget(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0); this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai); @@ -2294,7 +2286,6 @@ struct CompanyWindow : Window case WID_C_VIEW_INFRASTRUCTURE: case WID_C_GIVE_MONEY: case WID_C_HOSTILE_TAKEOVER: - case WID_C_COMPANY_PASSWORD: case WID_C_COMPANY_JOIN: size.width = GetStringBoundingBox(STR_COMPANY_VIEW_VIEW_HQ_BUTTON).width; size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_BUILD_HQ_BUTTON).width); @@ -2302,14 +2293,9 @@ struct CompanyWindow : Window size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON).width); size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON).width); size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON).width); - size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_PASSWORD).width); size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_JOIN).width); size.width += padding.width; break; - - case WID_C_HAS_PASSWORD: - if (_networking) size = maxdim(size, GetSpriteSize(SPR_LOCK)); - break; } } @@ -2405,12 +2391,6 @@ struct CompanyWindow : Window case WID_C_DESC_INFRASTRUCTURE_COUNTS: DrawInfrastructureCountsWidget(r, c); break; - - case WID_C_HAS_PASSWORD: - if (_networking && NetworkCompanyIsPassworded(c->index)) { - DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top); - } - break; } } @@ -2509,10 +2489,6 @@ struct CompanyWindow : Window ShowBuyCompanyDialog((CompanyID)this->window_number, true); break; - case WID_C_COMPANY_PASSWORD: - if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this); - break; - case WID_C_COMPANY_JOIN: { this->query_widget = WID_C_COMPANY_JOIN; CompanyID company = (CompanyID)this->window_number; diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index be317e3b68..bcdc53f108 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1907,53 +1907,6 @@ DEF_CONSOLE_CMD(ConSayClient) return true; } -DEF_CONSOLE_CMD(ConCompanyPassword) -{ - if (argc == 0) { - if (_network_dedicated) { - IConsolePrint(CC_HELP, "Change the password of a company. Usage: 'company_pw \"\"."); - } else if (_network_server) { - IConsolePrint(CC_HELP, "Change the password of your or any other company. Usage: 'company_pw [] \"\"'."); - } else { - IConsolePrint(CC_HELP, "Change the password of your company. Usage: 'company_pw \"\"'."); - } - - IConsolePrint(CC_HELP, "Use \"*\" to disable the password."); - return true; - } - - CompanyID company_id; - std::string password; - const char *errormsg; - - if (argc == 2) { - company_id = _local_company; - password = argv[1]; - errormsg = "You have to own a company to make use of this command."; - } else if (argc == 3 && _network_server) { - company_id = (CompanyID)(atoi(argv[1]) - 1); - password = argv[2]; - errormsg = "You have to specify the ID of a valid human controlled company."; - } else { - return false; - } - - if (!Company::IsValidHumanID(company_id)) { - IConsolePrint(CC_ERROR, errormsg); - return false; - } - - password = NetworkChangeCompanyPassword(company_id, password); - - if (password.empty()) { - IConsolePrint(CC_INFO, "Company password cleared."); - } else { - IConsolePrint(CC_INFO, "Company password changed to '{}'.", password); - } - - return true; -} - /** All the known authorized keys with their name. */ static std::vector> _console_cmd_authorized_keys{ { "rcon", &_settings_client.network.rcon_authorized_keys }, @@ -2795,9 +2748,6 @@ void IConsoleStdLibRegister() IConsole::CmdRegister("authorized_key", ConNetworkAuthorizedKey, ConHookServerOnly); IConsole::AliasRegister("ak", "authorized_key %+"); - IConsole::CmdRegister("company_pw", ConCompanyPassword, ConHookNeedNetwork); - IConsole::AliasRegister("company_password", "company_pw %+"); - IConsole::AliasRegister("net_frame_freq", "setting frame_freq %+"); IConsole::AliasRegister("net_sync_freq", "setting sync_freq %+"); IConsole::AliasRegister("server_pw", "setting server_password %+"); diff --git a/src/lang/english.txt b/src/lang/english.txt index 53892208a1..967b12fc46 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2511,13 +2511,11 @@ STR_NETWORK_CLIENT_LIST_SERVER_CONNECTION_TYPE_TURN :{BLACK}Via rela STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kick STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Delete -STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Password unlock STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Admin action STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Are you sure you want to kick player '{RAW_STRING}'? STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Are you sure you want to ban player '{RAW_STRING}'? STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Are you sure you want to delete company '{COMPANY}'? -STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Are you sure you want to reset the password of company '{COMPANY}'? STR_NETWORK_ASK_RELAY_CAPTION :{WHITE}Use relay? STR_NETWORK_ASK_RELAY_TEXT :{YELLOW}Failed to establish a connection between you and server '{RAW_STRING}'.{}Would you like to relay this session via '{RAW_STRING}'? @@ -2534,19 +2532,9 @@ STR_NETWORK_ASK_SURVEY_YES :Yes STR_NETWORK_SPECTATORS :Spectators -# Network set password -STR_COMPANY_PASSWORD_CANCEL :{BLACK}Do not save the entered password -STR_COMPANY_PASSWORD_OK :{BLACK}Give the company the new password -STR_COMPANY_PASSWORD_CAPTION :{WHITE}Company password -STR_COMPANY_PASSWORD_MAKE_DEFAULT :{BLACK}Default company password -STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP :{BLACK}Use this company password as default for new companies - # Network company info join/password STR_COMPANY_VIEW_JOIN :{BLACK}Join STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}Join and play as this company -STR_COMPANY_VIEW_PASSWORD :{BLACK}Password -STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}Password-protect your company to prevent unauthorised users from joining -STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}Set company password # Network chat STR_NETWORK_CHAT_SEND :{BLACK}Send diff --git a/src/network/network.cpp b/src/network/network.cpp index b2c48d4276..f07126c2c0 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -221,25 +221,6 @@ uint8_t NetworkSpectatorCount() return count; } -/** - * Change the company password of a given company. - * @param company_id ID of the company the password should be changed for. - * @param password The unhashed password we like to set ('*' or '' resets the password) - * @return The password. - */ -std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password) -{ - if (password.compare("*") == 0) password = ""; - - if (_network_server) { - NetworkServerSetCompanyPassword(company_id, password, false); - } else { - NetworkClientSetCompanyPassword(password); - } - - return password; -} - /** * Hash the given password using server ID and game seed. * @param password Password to hash. diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 78695d8552..920ac56bd4 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1362,14 +1362,6 @@ void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const MyClient::SendChat(action, type, dest, msg, data); } -/** - * Set/Reset company password on the client side. - * @param password Password to be set. - */ -void NetworkClientSetCompanyPassword([[maybe_unused]] const std::string &password) -{ -} - /** * Tell whether the client has team members who they can chat to. * @param cio client to check members of. diff --git a/src/network/network_client.h b/src/network/network_client.h index 47fb81b3cd..75a1ce4dd3 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -104,7 +104,6 @@ public: typedef ClientNetworkGameSocketHandler MyClient; void NetworkClient_Connected(); -void NetworkClientSetCompanyPassword(const std::string &password); /** Information required to join a server. */ struct NetworkJoinInfo { diff --git a/src/network/network_func.h b/src/network/network_func.h index de7036a30a..8d94836652 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -39,7 +39,6 @@ bool NetworkValidateServerName(std::string &server_name); void NetworkUpdateClientName(const std::string &client_name); void NetworkUpdateServerGameType(); bool NetworkCompanyHasClients(CompanyID company); -std::string NetworkChangeCompanyPassword(CompanyID company_id, std::string password); void NetworkReboot(); void NetworkDisconnect(bool close_admins = true); void NetworkGameLoop(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index f302a2d7c8..de8122b0f0 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1316,7 +1316,6 @@ enum DropDownAdmin { DD_CLIENT_ADMIN_KICK, DD_CLIENT_ADMIN_BAN, DD_COMPANY_ADMIN_RESET, - DD_COMPANY_ADMIN_UNLOCK, }; /** @@ -1349,15 +1348,6 @@ static void AdminCompanyResetCallback(Window *, bool confirmed) } } -/** - * Callback function for admin command to unlock company. - * @param confirmed Iff the user pressed Yes. - */ -static void AdminCompanyUnlockCallback(Window *, bool confirmed) -{ - if (confirmed) NetworkServerSetCompanyPassword(_admin_company_id, "", false); -} - /** * Button shown for either a company or client in the client-list. * @@ -1514,7 +1504,6 @@ private: { DropDownList list; list.push_back(MakeDropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET, DD_COMPANY_ADMIN_RESET, NetworkCompanyHasClients(company_id))); - list.push_back(MakeDropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK, DD_COMPANY_ADMIN_UNLOCK, !NetworkCompanyIsPassworded(company_id))); Rect wi_rect; wi_rect.left = pt.x; @@ -1868,13 +1857,6 @@ public: SetDParam(0, _admin_company_id); break; - case DD_COMPANY_ADMIN_UNLOCK: - _admin_company_id = this->dd_company_id; - text = STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK; - callback = AdminCompanyUnlockCallback; - SetDParam(0, _admin_company_id); - break; - default: NOT_REACHED(); } @@ -2246,114 +2228,6 @@ void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptrInitNested(0); - this->UpdateWarningStringSize(); - - this->parent = parent; - this->querystrings[WID_NCP_PASSWORD] = &this->password_editbox; - this->password_editbox.cancel_button = WID_NCP_CANCEL; - this->password_editbox.ok_button = WID_NCP_OK; - this->SetFocusedWidget(WID_NCP_PASSWORD); - } - - void UpdateWarningStringSize() - { - assert(this->nested_root->smallest_x > 0); - this->warning_size.width = this->nested_root->current_x - (WidgetDimensions::scaled.framerect.Horizontal()) * 2; - this->warning_size.height = GetStringHeight(STR_WARNING_PASSWORD_SECURITY, this->warning_size.width); - this->warning_size.height += (WidgetDimensions::scaled.framerect.Vertical()) * 2; - - this->ReInit(); - } - - void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override - { - if (widget == WID_NCP_WARNING) { - size = this->warning_size; - } - } - - void DrawWidget(const Rect &r, WidgetID widget) const override - { - if (widget != WID_NCP_WARNING) return; - - DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), - STR_WARNING_PASSWORD_SECURITY, TC_FROMSTRING, SA_CENTER); - } - - void OnOk() - { - if (this->IsWidgetLowered(WID_NCP_SAVE_AS_DEFAULT_PASSWORD)) { - _settings_client.network.default_company_pass = this->password_editbox.text.buf; - } - - NetworkChangeCompanyPassword(_local_company, this->password_editbox.text.buf); - } - - void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override - { - switch (widget) { - case WID_NCP_OK: - this->OnOk(); - [[fallthrough]]; - - case WID_NCP_CANCEL: - this->Close(); - break; - - case WID_NCP_SAVE_AS_DEFAULT_PASSWORD: - this->ToggleWidgetLoweredState(WID_NCP_SAVE_AS_DEFAULT_PASSWORD); - this->SetDirty(); - break; - } - } -}; - -static constexpr NWidgetPart _nested_network_company_password_window_widgets[] = { - NWidget(NWID_HORIZONTAL), - NWidget(WWT_CLOSEBOX, COLOUR_GREY), - NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_COMPANY_PASSWORD_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_NCP_BACKGROUND), - NWidget(NWID_VERTICAL), SetPIP(5, 5, 5), - NWidget(NWID_HORIZONTAL), SetPIP(5, 5, 5), - NWidget(WWT_TEXT, COLOUR_GREY, WID_NCP_LABEL), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_NULL), - NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NCP_PASSWORD), SetFill(1, 0), SetMinimalSize(194, 12), SetDataTip(STR_COMPANY_VIEW_SET_PASSWORD, STR_NULL), - EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(5, 0, 5), - NWidget(NWID_SPACER), SetFill(1, 0), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NCP_SAVE_AS_DEFAULT_PASSWORD), SetMinimalSize(194, 12), - SetDataTip(STR_COMPANY_PASSWORD_MAKE_DEFAULT, STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP), - EndContainer(), - EndContainer(), - EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_NCP_WARNING), EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_COMPANY_PASSWORD_CANCEL), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_OK), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_COMPANY_PASSWORD_OK), - EndContainer(), -}; - -static WindowDesc _network_company_password_window_desc( - WDP_AUTO, nullptr, 0, 0, - WC_COMPANY_PASSWORD_WINDOW, WC_NONE, - 0, - std::begin(_nested_network_company_password_window_widgets), std::end(_nested_network_company_password_window_widgets) -); - -void ShowNetworkCompanyPasswordWindow(Window *parent) -{ - CloseWindowById(WC_COMPANY_PASSWORD_WINDOW, 0); - - new NetworkCompanyPasswordWindow(&_network_company_password_window_desc, parent); -} - /** * Window used for asking the user if he is okay using a relay server. */ diff --git a/src/network/network_gui.h b/src/network/network_gui.h index 02283e9ae7..222542e210 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -22,7 +22,6 @@ void ShowNetworkChatQueryWindow(DestType type, int dest); void ShowJoinStatusWindow(); void ShowNetworkGameWindow(); void ShowClientList(); -void ShowNetworkCompanyPasswordWindow(Window *parent); void ShowNetworkAskRelay(const std::string &server_connection_string, const std::string &relay_connection_string, const std::string &token); void ShowNetworkAskSurvey(); void ShowSurveyResultTextfileWindow(); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 11b000d203..41f2b9cc50 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1667,16 +1667,6 @@ bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_na return true; } -/** - * Set/Reset a company password on the server end. - * @param company_id ID of the company the password should be changed for. - * @param password The new password. - * @param already_hashed Is the given password already hashed? - */ -void NetworkServerSetCompanyPassword([[maybe_unused]] CompanyID company_id, [[maybe_unused]] const std::string &password, [[maybe_unused]] bool already_hashed) -{ -} - /** * Handle the command-queue of a socket. * @param cs The socket to handle the queue for. @@ -1983,20 +1973,6 @@ void NetworkServerUpdateGameInfo() if (_network_server) FillStaticNetworkServerGameInfo(); } -/** - * Tell that a particular company is (not) passworded. - * @param company_id The company that got/removed the password. - * @param passworded Whether the password was received or removed. - */ -void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded) -{ - if (NetworkCompanyIsPassworded(company_id) == passworded) return; - - SetWindowClassesDirty(WC_COMPANY); - - NetworkAdminCompanyUpdate(Company::GetIfValid(company_id)); -} - /** * Handle the tid-bits of moving a client from one company to another. * @param client_id id of the client we want to move. diff --git a/src/network/network_server.h b/src/network/network_server.h index 2c91b7cfe1..31aa2739bc 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -123,7 +123,5 @@ public: void NetworkServer_Tick(bool send_frame); void ChangeNetworkRestartTime(bool reset); -void NetworkServerSetCompanyPassword(CompanyID company_id, const std::string &password, bool already_hashed = true); -void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded); #endif /* NETWORK_SERVER_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 055b396b2a..e721b8a1eb 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -896,12 +896,6 @@ static void MakeNewGameDone() InitializeRailGUI(); InitializeRoadGUI(); - /* We are the server, we start a new company (not dedicated), - * so set the default password *if* needed. */ - if (_network_server && !_settings_client.network.default_company_pass.empty()) { - NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); - } - if (_settings_client.gui.pause_on_newgame) Command::Post(PM_PAUSED_NORMAL, true); CheckEngines(); diff --git a/src/widgets/company_widget.h b/src/widgets/company_widget.h index f53f83a494..452632dccb 100644 --- a/src/widgets/company_widget.h +++ b/src/widgets/company_widget.h @@ -47,9 +47,7 @@ enum CompanyWidgets : WidgetID { WID_C_SELECT_HOSTILE_TAKEOVER, ///< Selection widget for the hostile takeover button. WID_C_HOSTILE_TAKEOVER, ///< Button to hostile takeover another company. - WID_C_HAS_PASSWORD, ///< Has company password lock. WID_C_SELECT_MULTIPLAYER, ///< Multiplayer selection panel. - WID_C_COMPANY_PASSWORD, ///< Button to set company password. WID_C_COMPANY_JOIN, ///< Button to join company. }; diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h index 7efbb236eb..42aba87e18 100644 --- a/src/widgets/network_widget.h +++ b/src/widgets/network_widget.h @@ -96,17 +96,6 @@ enum NetworkJoinStatusWidgets : WidgetID { WID_NJS_CANCELOK, ///< Cancel / OK button. }; -/** Widgets of the #NetworkCompanyPasswordWindow class. */ -enum NetworkCompanyPasswordWidgets : WidgetID { - WID_NCP_BACKGROUND, ///< Background of the window. - WID_NCP_LABEL, ///< Label in front of the password field. - WID_NCP_PASSWORD, ///< Input field for the password. - WID_NCP_SAVE_AS_DEFAULT_PASSWORD, ///< Toggle 'button' for saving the current password as default password. - WID_NCP_WARNING, ///< Warning text about password security - WID_NCP_CANCEL, ///< Close the window without changing anything. - WID_NCP_OK, ///< Safe the password etc. -}; - /** Widgets of the #NetworkAskRelayWindow class. */ enum NetworkAskRelayWidgets : WidgetID { WID_NAR_CAPTION, ///< Caption of the window. diff --git a/src/window_type.h b/src/window_type.h index 9e4d96acbd..a677c34cdd 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -502,13 +502,6 @@ enum WindowClass { */ WC_SEND_NETWORK_MSG, - /** - * Company password query; %Window numbers: - * - 0 = #NetworkCompanyPasswordWidgets - */ - WC_COMPANY_PASSWORD_WINDOW, - - /** * Industry cargoes chain; %Window numbers: * - 0 = #IndustryCargoesWidgets From 494a918e194c7221e289c875bb64b07d5b551bcb Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:40:42 +0100 Subject: [PATCH 10/14] Cleanup: remove company password hashing and anything related to it --- src/network/core/config.h | 3 +- src/network/network.cpp | 51 ------------------- src/network/network_client.cpp | 3 -- src/network/network_func.h | 1 - src/network/network_internal.h | 1 - src/settings_type.h | 2 - .../settings/network_secrets_settings.ini | 14 ----- 7 files changed, 1 insertion(+), 74 deletions(-) diff --git a/src/network/core/config.h b/src/network/core/config.h index 99e6a3bd94..648ef2a35c 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -54,9 +54,8 @@ static const uint NETWORK_NAME_LENGTH = 80; ///< The m static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0' static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0' static const uint NETWORK_HOSTNAME_PORT_LENGTH = 80 + 6; ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536) -static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0' static const uint NETWORK_REVISION_LENGTH = 33; ///< The maximum length of the revision, in bytes including '\0' -static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH) +static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0' static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = 9000; ///< The maximum length of a receiving gamescript json string, in bytes including '\0'. diff --git a/src/network/network.cpp b/src/network/network.cpp index f07126c2c0..b0b5c29989 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -221,49 +221,6 @@ uint8_t NetworkSpectatorCount() return count; } -/** - * Hash the given password using server ID and game seed. - * @param password Password to hash. - * @param password_server_id Server ID. - * @param password_game_seed Game seed. - * @return The hashed password. - */ -std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32_t password_game_seed) -{ - if (password.empty()) return password; - - size_t password_length = password.size(); - size_t password_server_id_length = password_server_id.size(); - - std::ostringstream salted_password; - /* Add the password with the server's ID and game seed as the salt. */ - for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) { - char password_char = (i < password_length ? password[i] : 0); - char server_id_char = (i < password_server_id_length ? password_server_id[i] : 0); - char seed_char = password_game_seed >> (i % 32); - salted_password << (char)(password_char ^ server_id_char ^ seed_char); // Cast needed, otherwise interpreted as integer to format - } - - Md5 checksum; - MD5Hash digest; - - /* Generate the MD5 hash */ - std::string salted_password_string = salted_password.str(); - checksum.Append(salted_password_string.data(), salted_password_string.size()); - checksum.Finish(digest); - - return FormatArrayAsHex(digest); -} - -/** - * Check if the company we want to join requires a password. - * @param company_id id of the company we want to check the 'passworded' flag for. - * @return true if the company requires a password. - */ -bool NetworkCompanyIsPassworded([[maybe_unused]] CompanyID company_id) -{ - return false; -} /* This puts a text-message to the console, or in the future, the chat-box, * (to keep it all a bit more general) @@ -1277,11 +1234,6 @@ void NetworkGameLoop() NetworkSend(); } -static void NetworkGenerateServerId() -{ - _settings_client.network.network_id = GenerateUid("OpenTTD Server ID"); -} - /** This tries to launch the network for a given OS */ void NetworkStartUp() { @@ -1291,9 +1243,6 @@ void NetworkStartUp() _network_available = NetworkCoreInitialize(); _network_dedicated = false; - /* Generate an server id when there is none yet */ - if (_settings_client.network.network_id.empty()) NetworkGenerateServerId(); - _network_game_info = {}; NetworkInitialize(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 920ac56bd4..307f38814f 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -321,9 +321,6 @@ std::string _network_server_name; /** Information about the game to join to. */ NetworkJoinInfo _network_join; -/** Make sure the server ID length is the same as a md5 hash. */ -static_assert(NETWORK_SERVER_ID_LENGTH == MD5_HASH_BYTES * 2 + 1); - /*********** * Sending functions ************/ diff --git a/src/network/network_func.h b/src/network/network_func.h index 8d94836652..44606459ad 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -54,7 +54,6 @@ void NetworkClientRequestMove(CompanyID company); void NetworkClientSendRcon(const std::string &password, const std::string &command); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data = 0); bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio); -bool NetworkCompanyIsPassworded(CompanyID company_id); uint NetworkMaxCompaniesAllowed(); bool NetworkMaxCompaniesReached(); void NetworkPrintClients(); diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 72622b4f94..92f4380e3d 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -127,7 +127,6 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, uint NetworkCalculateLag(const NetworkClientSocket *cs); StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkMakeClientNameUnique(std::string &new_name); -std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32_t password_game_seed); std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id); NetworkAddress ParseConnectionString(const std::string &connection_string, uint16_t default_port); diff --git a/src/settings_type.h b/src/settings_type.h index cfc6ad7c33..8064466404 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -320,9 +320,7 @@ struct NetworkSettings { std::string client_name; ///< name of the player (as client) std::string client_secret_key; ///< The secret key of the client for authorized key logins. std::string client_public_key; ///< The public key of the client for authorized key logins. - std::string default_company_pass; ///< default password for new companies in encrypted form std::string connect_to_ip; ///< default for the "Add server" query - std::string network_id; ///< network ID for servers bool autoclean_companies; ///< automatically remove companies that are not in use uint8_t autoclean_protected; ///< Remove companies after this many months. uint8_t autoclean_novehicles; ///< remove companies with no vehicles after this many months diff --git a/src/table/settings/network_secrets_settings.ini b/src/table/settings/network_secrets_settings.ini index 3d7908e75a..ed9ae27130 100644 --- a/src/table/settings/network_secrets_settings.ini +++ b/src/table/settings/network_secrets_settings.ini @@ -79,20 +79,6 @@ def = nullptr ; Prevent the user from setting the public key from the console using 'setting' pre_cb = [](auto) { return false; } -[SDTC_SSTR] -var = network.default_company_pass -type = SLE_STR -length = NETWORK_PASSWORD_LENGTH -flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC -def = nullptr - -[SDTC_SSTR] -var = network.network_id -type = SLE_STR -length = NETWORK_SERVER_ID_LENGTH -flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY -def = nullptr - [SDTC_SSTR] var = network.server_invite_code type = SLE_STR From d23c63e5017b20f4eac4b1cd73b0e82e6e36378e Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:43:08 +0100 Subject: [PATCH 11/14] Cleanup: remove UI for asking user for company password --- src/lang/english.txt | 1 - src/network/network_client.cpp | 2 +- src/network/network_gui.cpp | 10 ++-------- src/network/network_gui.h | 2 +- src/network/network_type.h | 6 ------ 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 967b12fc46..d54bdb1b72 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2461,7 +2461,6 @@ STR_NETWORK_CONNECTING_SPECIAL_2 :{BLACK}Fetching STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disconnect STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server is protected. Enter password -STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company is protected. Enter password # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online players diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 307f38814f..2aca0fc6ca 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -709,7 +709,7 @@ class ClientGamePasswordRequestHandler : public NetworkAuthenticationPasswordReq if (!_network_join.server_password.empty()) { request->Reply(_network_join.server_password); } else { - ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD, request); + ShowNetworkNeedPassword(request); } } }; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index de8122b0f0..e9f2e68981 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -2213,19 +2213,13 @@ void ShowJoinStatusWindow() new NetworkJoinStatusWindow(&_network_join_status_window_desc); } -void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr request) +void ShowNetworkNeedPassword(std::shared_ptr request) { NetworkJoinStatusWindow *w = dynamic_cast(FindWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN)); if (w == nullptr) return; w->request = request; - StringID caption; - switch (npt) { - default: NOT_REACHED(); - case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break; - case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break; - } - ShowQueryString(STR_EMPTY, caption, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_PASSWORD); + ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_GAME_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_NONE); } /** diff --git a/src/network/network_gui.h b/src/network/network_gui.h index 222542e210..6c2555a5bf 100644 --- a/src/network/network_gui.h +++ b/src/network/network_gui.h @@ -17,7 +17,7 @@ #include "network_type.h" #include "network_gamelist.h" -void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr request); +void ShowNetworkNeedPassword(std::shared_ptr request); void ShowNetworkChatQueryWindow(DestType type, int dest); void ShowJoinStatusWindow(); void ShowNetworkGameWindow(); diff --git a/src/network/network_type.h b/src/network/network_type.h index 0ab7d51558..911a163de0 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -72,12 +72,6 @@ struct NetworkCompanyStats { struct NetworkClientInfo; -/** The type of password we're asking for. */ -enum NetworkPasswordType { - NETWORK_GAME_PASSWORD, ///< The password of the game. - NETWORK_COMPANY_PASSWORD, ///< The password of the company. -}; - /** * Destination of our chat messages. * @warning The values of the enum items are part of the admin network API. Only append at the end. From fcb8256cba9126000af4675fea0d923cdf1b0f54 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sat, 23 Mar 2024 19:45:21 +0100 Subject: [PATCH 12/14] Cleanup: remove warning about server administrators being able to read passwords --- src/lang/english.txt | 1 - src/misc_gui.cpp | 31 ------------------------------- src/textbuf_gui.h | 1 - src/widgets/misc_widget.h | 1 - 4 files changed, 34 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index d54bdb1b72..4d0cfb2429 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -308,7 +308,6 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}By enabl STR_BUTTON_DEFAULT :{BLACK}Default STR_BUTTON_CANCEL :{BLACK}Cancel STR_BUTTON_OK :{BLACK}OK -STR_WARNING_PASSWORD_SECURITY :{YELLOW}Warning: Server administrators may be able to read any text entered here. # On screen keyboard window STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ . diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 1412e849de..0929c93d27 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -948,7 +948,6 @@ struct QueryStringWindow : public Window { QueryString editbox; ///< Editbox. QueryStringFlags flags; ///< Flags controlling behaviour of the window. - Dimension warning_size; ///< How much space to use for the warning text QueryStringWindow(StringID str, StringID caption, uint max_bytes, uint max_chars, WindowDesc *desc, Window *parent, CharSetFilter afilter, QueryStringFlags flags) : Window(desc), editbox(max_bytes, max_chars) @@ -965,27 +964,12 @@ struct QueryStringWindow : public Window this->flags = flags; this->InitNested(WN_QUERY_STRING); - this->UpdateWarningStringSize(); this->parent = parent; this->SetFocusedWidget(WID_QS_TEXT); } - void UpdateWarningStringSize() - { - if (this->flags & QSF_PASSWORD) { - assert(this->nested_root->smallest_x > 0); - this->warning_size.width = this->nested_root->current_x - WidgetDimensions::scaled.frametext.Horizontal() - WidgetDimensions::scaled.framerect.Horizontal(); - this->warning_size.height = GetStringHeight(STR_WARNING_PASSWORD_SECURITY, this->warning_size.width); - this->warning_size.height += WidgetDimensions::scaled.frametext.Vertical() + WidgetDimensions::scaled.framerect.Vertical(); - } else { - this->warning_size = Dimension{ 0, 0 }; - } - - this->ReInit(); - } - void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override { if (widget == WID_QS_DEFAULT && (this->flags & QSF_ENABLE_DEFAULT) == 0) { @@ -994,20 +978,6 @@ struct QueryStringWindow : public Window resize.width = 0; size.width = 0; } - - if (widget == WID_QS_WARNING) { - size = this->warning_size; - } - } - - void DrawWidget(const Rect &r, WidgetID widget) const override - { - if (widget != WID_QS_WARNING) return; - - if (this->flags & QSF_PASSWORD) { - DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect).Shrink(WidgetDimensions::scaled.frametext), - STR_WARNING_PASSWORD_SECURITY, TC_FROMSTRING, SA_CENTER); - } } void SetStringParameters(WidgetID widget) const override @@ -1061,7 +1031,6 @@ static constexpr NWidgetPart _nested_query_string_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY), NWidget(WWT_EDITBOX, COLOUR_GREY, WID_QS_TEXT), SetMinimalSize(256, 12), SetFill(1, 1), SetPadding(2, 2, 2, 2), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_QS_WARNING), EndContainer(), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_DEFAULT), SetMinimalSize(87, 12), SetFill(1, 1), SetDataTip(STR_BUTTON_DEFAULT, STR_NULL), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_CANCEL), SetMinimalSize(86, 12), SetFill(1, 1), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), diff --git a/src/textbuf_gui.h b/src/textbuf_gui.h index 0284bbd57e..15776fb680 100644 --- a/src/textbuf_gui.h +++ b/src/textbuf_gui.h @@ -20,7 +20,6 @@ enum QueryStringFlags { QSF_ACCEPT_UNCHANGED = 0x01, ///< return success even when the text didn't change QSF_ENABLE_DEFAULT = 0x02, ///< enable the 'Default' button ("\0" is returned) QSF_LEN_IN_CHARS = 0x04, ///< the length of the string is counted in characters - QSF_PASSWORD = 0x08, ///< password entry box, show warning about password security }; DECLARE_ENUM_AS_BIT_SET(QueryStringFlags) diff --git a/src/widgets/misc_widget.h b/src/widgets/misc_widget.h index a3ec814f1b..0d59ee4f8e 100644 --- a/src/widgets/misc_widget.h +++ b/src/widgets/misc_widget.h @@ -32,7 +32,6 @@ enum AboutWidgets : WidgetID { enum QueryStringWidgets : WidgetID { WID_QS_CAPTION, ///< Caption of the window. WID_QS_TEXT, ///< Text of the query. - WID_QS_WARNING, ///< Warning label about password security WID_QS_DEFAULT, ///< Default button. WID_QS_CANCEL, ///< Cancel button. WID_QS_OK, ///< OK button. From bba891149bc5098c024ff05567cc9a36478c2476 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 4 Apr 2024 20:45:00 +0200 Subject: [PATCH 13/14] Codechange: also allow removing clients from the company allow lists --- src/command_type.h | 2 +- src/company_cmd.cpp | 30 ++++++++++++++++++++++++++---- src/company_cmd.h | 4 ++-- src/company_type.h | 8 ++++++++ src/network/network_gui.cpp | 2 +- src/network/network_server.cpp | 7 ++++--- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/command_type.h b/src/command_type.h index 8f3cbedd93..72217fbcef 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -294,7 +294,7 @@ enum Commands : uint16_t { CMD_CREATE_SUBSIDY, ///< create a new subsidy CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc. - CMD_COMPANY_ADD_ALLOW_LIST, ///< Used in multiplayer to add a client's public key to the company's allow list. + CMD_COMPANY_ALLOW_LIST_CTRL, ///< Used in multiplayer to add/remove a client's public key to/from the company's allow list. CMD_CUSTOM_NEWS_ITEM, ///< create a custom news message CMD_CREATE_GOAL, ///< create a new goal CMD_REMOVE_GOAL, ///< remove a goal diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 770c20011b..fc79ac92eb 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -975,15 +975,37 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID } /** - * Add the given public key to the allow list of this company. + * Add or remove the given public key to the allow list of this company. * @param flags Operation to perform. - * @param public_key The public key of the client to add. + * @param action The action to perform. + * @param public_key The public key of the client to add or remove. * @return The cost of this operation or an error. */ -CommandCost CmdCompanyAddAllowList(DoCommandFlag flags, const std::string &public_key) +CommandCost CmdCompanyAllowListCtrl(DoCommandFlag flags, CompanyAllowListCtrlAction action, const std::string &public_key) { + Company *c = Company::GetIfValid(_current_company); + if (c == nullptr) return CMD_ERROR; + + /* The public key length includes the '\0'. */ + if (public_key.size() != NETWORK_PUBLIC_KEY_LENGTH - 1) return CMD_ERROR; + + using ModifierFunction = bool (NetworkAuthorizedKeys::*)(std::string_view key); + ModifierFunction modifier_function; + switch (action) { + case CALCA_ADD: + modifier_function = &NetworkAuthorizedKeys::Add; + break; + + case CALCA_REMOVE: + modifier_function = &NetworkAuthorizedKeys::Remove; + break; + + default: + return CMD_ERROR; + } + if (flags & DC_EXEC) { - if (Company::Get(_current_company)->allow_list.Add(public_key)) { + if (std::invoke(modifier_function, c->allow_list, public_key)) { InvalidateWindowData(WC_CLIENT_LIST, 0); SetWindowDirty(WC_COMPANY, _current_company); } diff --git a/src/company_cmd.h b/src/company_cmd.h index 5f818c4b8f..6f3bf4f7df 100644 --- a/src/company_cmd.h +++ b/src/company_cmd.h @@ -18,7 +18,7 @@ enum ClientID : uint32_t; enum Colours : uint8_t; CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id); -CommandCost CmdCompanyAddAllowList(DoCommandFlag flags, const std::string &public_key); +CommandCost CmdCompanyAllowListCtrl(DoCommandFlag flags, CompanyAllowListCtrlAction action, const std::string &public_key); CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company); CommandCost CmdRenameCompany(DoCommandFlag flags, const std::string &text); CommandCost CmdRenamePresident(DoCommandFlag flags, const std::string &text); @@ -26,7 +26,7 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlag flags, CompanyManagerFace cmf CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool primary, Colours colour); DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID | CMD_NO_EST, CMDT_SERVER_SETTING) -DEF_CMD_TRAIT(CMD_COMPANY_ADD_ALLOW_LIST, CmdCompanyAddAllowList, CMD_NO_EST, CMDT_SERVER_SETTING) +DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CMD_NO_EST, CMDT_SERVER_SETTING) DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, 0, CMDT_MONEY_MANAGEMENT) DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, 0, CMDT_OTHER_MANAGEMENT) DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, 0, CMDT_OTHER_MANAGEMENT) diff --git a/src/company_type.h b/src/company_type.h index c119a17719..355bde8630 100644 --- a/src/company_type.h +++ b/src/company_type.h @@ -72,4 +72,12 @@ enum CompanyCtrlAction : uint8_t { CCA_END, ///< Sentinel for end. }; +/** The action to do with CMD_COMPANY_ALLOW_LIST_CTRL. */ +enum CompanyAllowListCtrlAction : uint8_t { + CALCA_ADD, ///< Create a public key. + CALCA_REMOVE, ///< Remove a public key. + + CALCA_END, ///< Sentinel for end. +}; + #endif /* COMPANY_TYPE_H */ diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index e9f2e68981..d8b8607e73 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1528,7 +1528,7 @@ private: static void OnClickClientAuthorize([[maybe_unused]] NetworkClientListWindow *w, [[maybe_unused]] Point pt, ClientID client_id) { AutoRestoreBackup cur_company(_current_company, NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas); - Command::Post(NetworkClientInfo::GetByClientID(client_id)->public_key); + Command::Post(CALCA_ADD, NetworkClientInfo::GetByClientID(client_id)->public_key); } /** diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 41f2b9cc50..5a9bc089d4 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1117,11 +1117,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet } } - if (cp.cmd == CMD_COMPANY_ADD_ALLOW_LIST) { + if (cp.cmd == CMD_COMPANY_ALLOW_LIST_CTRL) { /* Maybe the client just got moved before allowing? */ if (ci->client_id != CLIENT_ID_SERVER && ci->client_playas != cp.company) return NETWORK_RECV_STATUS_OKAY; - std::string public_key = std::get<0>(EndianBufferReader::ToValue::Args>(cp.data)); + /* Only allow clients to add/remove currently joined clients. The server owner does not go via this method, so is allowed to do more. */ + std::string public_key = std::get<1>(EndianBufferReader::ToValue::Args>(cp.data)); bool found = false; for (const NetworkClientInfo *info : NetworkClientInfo::Iterate()) { if (info->public_key == public_key) { @@ -2157,7 +2158,7 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci) /* ci is nullptr when replaying, or for AIs. In neither case there is a client. */ ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); - Command::SendNet(STR_NULL, c->index, ci->public_key); + Command::SendNet(STR_NULL, c->index, CALCA_ADD, ci->public_key); Command::SendNet(STR_NULL, c->index, ci->client_name); NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1); From e420467d601802fe969c03541814db5a730bd4ab Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 4 Apr 2024 21:30:36 +0200 Subject: [PATCH 14/14] Change: support listing/updating authorized keys of companies by the admin in the console --- src/console_cmds.cpp | 126 ++++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 37 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index bcdc53f108..ca4cd0129d 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1913,6 +1913,50 @@ static std::vector> _consol { "server", &_settings_client.network.server_authorized_keys }, }; +enum ConNetworkAuthorizedKeyAction { + CNAKA_LIST, + CNAKA_ADD, + CNAKA_REMOVE, +}; + +static void PerformNetworkAuthorizedKeyAction(std::string_view name, NetworkAuthorizedKeys *authorized_keys, ConNetworkAuthorizedKeyAction action, const std::string &authorized_key, CompanyID company = INVALID_COMPANY) +{ + switch (action) { + case CNAKA_LIST: + IConsolePrint(CC_WHITE, "The authorized keys for {} are:", name); + for (auto &ak : *authorized_keys) IConsolePrint(CC_INFO, " {}", ak); + return; + + case CNAKA_ADD: + if (authorized_keys->Contains(authorized_key)) { + IConsolePrint(CC_WARNING, "Not added {} to {} as it already exists.", authorized_key, name); + return; + } + + if (company == INVALID_COMPANY) { + authorized_keys->Add(authorized_key); + } else { + Command::SendNet(STR_NULL, company, CALCA_ADD, authorized_key); + } + IConsolePrint(CC_INFO, "Added {} to {}.", authorized_key, name); + return; + + case CNAKA_REMOVE: + if (!authorized_keys->Contains(authorized_key)) { + IConsolePrint(CC_WARNING, "Not removed {} from {} as it does not exist.", authorized_key, name); + return; + } + + if (company == INVALID_COMPANY) { + authorized_keys->Remove(authorized_key); + } else { + Command::SendNet(STR_NULL, company, CALCA_REMOVE, authorized_key); + } + IConsolePrint(CC_INFO, "Removed {} from {}.", authorized_key, name); + return; + } +} + DEF_CONSOLE_CMD(ConNetworkAuthorizedKey) { if (argc <= 2) { @@ -1924,29 +1968,31 @@ DEF_CONSOLE_CMD(ConNetworkAuthorizedKey) std::string buffer; for (auto [name, _] : _console_cmd_authorized_keys) fmt::format_to(std::back_inserter(buffer), ", {}", name); - IConsolePrint(CC_HELP, "The supported types are: all{}.", buffer); + IConsolePrint(CC_HELP, "The supported types are: all{} and company:.", buffer); return true; } - bool valid_type = false; ///< Whether a valid type was given. - - for (auto [name, authorized_keys] : _console_cmd_authorized_keys) { - if (!StrEqualsIgnoreCase(argv[2], name) && !StrEqualsIgnoreCase(argv[2], "all")) continue; - - valid_type = true; - - if (StrEqualsIgnoreCase(argv[1], "list")) { - IConsolePrint(CC_WHITE, "The authorized keys for {} are:", name); - for (auto &authorized_key : *authorized_keys) IConsolePrint(CC_INFO, " {}", authorized_key); - continue; - } + ConNetworkAuthorizedKeyAction action; + std::string_view action_string = argv[1]; + if (StrEqualsIgnoreCase(action_string, "list")) { + action = CNAKA_LIST; + } else if (StrEqualsIgnoreCase(action_string, "add")) { + action = CNAKA_ADD; + } else if (StrEqualsIgnoreCase(action_string, "remove") || StrEqualsIgnoreCase(action_string, "delete")) { + action = CNAKA_REMOVE; + } else { + IConsolePrint(CC_WARNING, "No valid action was given."); + return false; + } + std::string authorized_key; + if (action != CNAKA_LIST) { if (argc <= 3) { IConsolePrint(CC_ERROR, "You must enter the key."); return false; } - std::string authorized_key = argv[3]; + authorized_key = argv[3]; if (StrStartsWithIgnoreCase(authorized_key, "client:")) { std::string id_string(authorized_key.substr(7)); authorized_key = NetworkGetPublicKeyOfClient(static_cast(std::stoi(id_string))); @@ -1956,34 +2002,40 @@ DEF_CONSOLE_CMD(ConNetworkAuthorizedKey) } } - if (StrEqualsIgnoreCase(argv[1], "add")) { - if (authorized_keys->Add(authorized_key)) { - IConsolePrint(CC_INFO, "Added {} to {}.", authorized_key, name); - } else { - IConsolePrint(CC_WARNING, "Not added {} to {} as it already exists.", authorized_key, name); - } - continue; + if (authorized_key.size() != NETWORK_PUBLIC_KEY_LENGTH - 1) { + IConsolePrint(CC_ERROR, "You must enter a valid authorized key."); + return false; } - - if (StrEqualsIgnoreCase(argv[1], "remove")) { - if (authorized_keys->Remove(authorized_key)) { - IConsolePrint(CC_INFO, "Removed {} from {}.", authorized_key, name); - } else { - IConsolePrint(CC_WARNING, "Not removed {} from {} as it does not exist.", authorized_key, name); - } - continue; - } - - IConsolePrint(CC_WARNING, "No valid action was given."); - return false; } - if (!valid_type) { - IConsolePrint(CC_WARNING, "No valid type was given."); - return false; + std::string_view type = argv[2]; + if (StrEqualsIgnoreCase(type, "all")) { + for (auto [name, authorized_keys] : _console_cmd_authorized_keys) PerformNetworkAuthorizedKeyAction(name, authorized_keys, action, authorized_key); + for (Company *c : Company::Iterate()) PerformNetworkAuthorizedKeyAction(fmt::format("company:{}", c->index + 1), &c->allow_list, action, authorized_key, c->index); + return true; } - return true; + if (StrStartsWithIgnoreCase(type, "company:")) { + std::string id_string(type.substr(8)); + Company *c = Company::GetIfValid(std::stoi(id_string) - 1); + if (c == nullptr) { + IConsolePrint(CC_ERROR, "You must enter a valid company id; see 'companies'."); + return false; + } + + PerformNetworkAuthorizedKeyAction(type, &c->allow_list, action, authorized_key, c->index); + return true; + } + + for (auto [name, authorized_keys] : _console_cmd_authorized_keys) { + if (StrEqualsIgnoreCase(type, name)) continue; + + PerformNetworkAuthorizedKeyAction(name, authorized_keys, action, authorized_key); + return true; + } + + IConsolePrint(CC_WARNING, "No valid type was given."); + return false; }