Change: remove company passwords over client allow lists

master
Rubidium 2 months ago committed by rubidium42
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…
Cancel
Save