mirror of https://github.com/OpenTTD/OpenTTD.git
Change: remove company passwords over client allow lists
This commit is contained in:
parent
a002803d1c
commit
71fc907584
|
@ -67,7 +67,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
|
||||
|
@ -85,7 +84,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);
|
||||
|
||||
|
@ -287,9 +285,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,
|
||||
|
@ -687,10 +685,6 @@ void NetworkClose(bool close_admins)
|
|||
|
||||
NetworkFreeLocalCommandQueue();
|
||||
|
||||
delete[] _network_company_states;
|
||||
_network_company_states = nullptr;
|
||||
_network_company_passworded = 0;
|
||||
|
||||
InitializeNetworkPools(close_admins);
|
||||
}
|
||||
|
||||
|
@ -985,7 +979,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;
|
||||
|
@ -995,7 +988,6 @@ bool NetworkServerStart()
|
|||
_network_own_client_id = CLIENT_ID_SERVER;
|
||||
|
||||
_network_clients_connected = 0;
|
||||
_network_company_passworded = 0;
|
||||
|
||||
NetworkInitGameInfo();
|
||||
|
||||
|
|
|
@ -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()");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1423,7 +1423,6 @@ using ClientButton = Button<ClientID>;
|
|||
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.
|
||||
|
@ -1459,10 +1458,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);
|
||||
}
|
||||
|
@ -1546,14 +1541,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<CompanyButton>(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<CompanyButton>(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<CompanyButton>(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;
|
||||
|
||||
|
@ -1599,18 +1595,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)) || _network_server);
|
||||
}
|
||||
|
||||
/* Spectators */
|
||||
this->RebuildListCompany(COMPANY_SPECTATOR, client_playas);
|
||||
this->RebuildListCompany(COMPANY_SPECTATOR, client_playas, client_playas != COMPANY_SPECTATOR);
|
||||
|
||||
this->vscroll->SetCount(this->line_count);
|
||||
}
|
||||
|
@ -1914,10 +1910,6 @@ public:
|
|||
this->InvalidateData();
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_CL_COMPANY_JOIN:
|
||||
NetworkClientRequestMove(this->join_company, str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,8 +80,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);
|
||||
|
|
|
@ -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<Packet>(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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue