This commit is contained in:
rubidium42 2024-04-23 19:34:11 +02:00 committed by GitHub
commit de9bd52178
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 308 additions and 841 deletions

View File

@ -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

View File

@ -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_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

View File

@ -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.

View File

@ -890,8 +890,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);
@ -899,9 +897,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. */
@ -980,6 +975,46 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID
return CommandCost();
}
/**
* Add or remove the given public key to the allow list of this company.
* @param flags Operation to perform.
* @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 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 (std::invoke(modifier_function, c->allow_list, 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

View File

@ -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 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);
@ -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_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)

View File

@ -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<NWidgetStacked>(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0);
/* Multiplayer buttons. */
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN));
reinit |= this->GetWidget<NWidgetStacked>(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;
}
}
@ -2404,12 +2390,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;
}
}
@ -2508,19 +2488,12 @@ 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;
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);
@ -2568,10 +2541,6 @@ struct CompanyWindow : Window
case WID_C_COMPANY_NAME:
Command<CMD_RENAME_COMPANY>::Post(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME, str);
break;
case WID_C_COMPANY_JOIN:
NetworkClientRequestMove((CompanyID)this->window_number, str);
break;
}
}

View File

@ -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 */

View File

@ -914,7 +914,7 @@ DEF_CONSOLE_CMD(ConClientNickChange)
DEF_CONSOLE_CMD(ConJoinCompany)
{
if (argc < 2) {
IConsolePrint(CC_HELP, "Request joining another company. Usage: 'join <company-id> [<password>]'.");
IConsolePrint(CC_HELP, "Request joining another company. Usage: 'join <company-id>'.");
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;
@ -1829,13 +1828,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 +1836,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;
@ -1915,59 +1907,56 @@ 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 <company-no> \"<password>\".");
} else if (_network_server) {
IConsolePrint(CC_HELP, "Change the password of your or any other company. Usage: 'company_pw [<company-no>] \"<password>\"'.");
} else {
IConsolePrint(CC_HELP, "Change the password of your company. Usage: 'company_pw \"<password>\"'.");
}
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<std::pair<std::string_view, NetworkAuthorizedKeys *>> _console_cmd_authorized_keys{
{ "rcon", &_settings_client.network.rcon_authorized_keys },
{ "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<CMD_COMPANY_ALLOW_LIST_CTRL>::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<CMD_COMPANY_ALLOW_LIST_CTRL>::SendNet(STR_NULL, company, CALCA_REMOVE, authorized_key);
}
IConsolePrint(CC_INFO, "Removed {} from {}.", authorized_key, name);
return;
}
}
DEF_CONSOLE_CMD(ConNetworkAuthorizedKey)
{
if (argc <= 2) {
@ -1979,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:<id>.", 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<ClientID>(std::stoi(id_string)));
@ -2011,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;
}
@ -2803,9 +2800,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 %+");
@ -2821,7 +2815,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 %+");

View File

@ -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,./ .
@ -2461,7 +2460,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
@ -2488,6 +2486,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
@ -2510,13 +2509,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}'?
@ -2533,19 +2530,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

View File

@ -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),

View File

@ -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'.
@ -96,5 +95,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 */

View File

@ -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.

View File

@ -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()

View File

@ -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. */
@ -202,7 +196,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);
@ -224,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.
@ -249,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);
@ -401,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.
@ -497,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.

View File

@ -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);
@ -126,6 +124,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
@ -165,10 +185,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;
@ -205,68 +227,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.
* @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(CompanyID company_id)
{
return HasBit(_network_company_passworded, company_id);
}
/* This puts a text-message to the console, or in the future, the chat-box,
* (to keep it all a bit more general)
@ -663,10 +623,6 @@ void NetworkClose(bool close_admins)
NetworkFreeLocalCommandQueue();
delete[] _network_company_states;
_network_company_states = nullptr;
_network_company_passworded = 0;
InitializeNetworkPools(close_admins);
}
@ -813,7 +769,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
@ -825,10 +781,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);
@ -841,7 +796,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. */
@ -887,6 +841,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;
}
/**
@ -958,7 +915,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;
@ -968,7 +924,6 @@ bool NetworkServerStart()
_network_own_client_id = CLIENT_ID_SERVER;
_network_clients_connected = 0;
_network_company_passworded = 0;
NetworkInitGameInfo();
@ -1296,11 +1251,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()
{
@ -1310,9 +1260,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();

View File

@ -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));

View File

@ -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
@ -35,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 */

View File

@ -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. */
@ -326,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
************/
@ -388,20 +380,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<Packet>(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 +463,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<Packet>(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 +510,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<Packet>(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;
}
@ -608,6 +569,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 +594,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 +614,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);
@ -745,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);
}
}
};
@ -793,34 +757,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<CompanyPasswordRequest>());
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;
@ -831,10 +767,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();
}
@ -1258,19 +1190,6 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(P
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet &p)
{
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()");
return NETWORK_RECV_STATUS_OKAY;
}
/**
* Check the connection's state, i.e. is the connection still up?
*/
@ -1327,12 +1246,10 @@ 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, const std::string &pass)
void NetworkClientRequestMove(CompanyID company_id)
{
MyClient::SendMove(company_id, pass);
MyClient::SendMove(company_id);
}
/**
@ -1442,15 +1359,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(const std::string &password)
{
MyClient::SendSetPassword(password);
}
/**
* Tell whether the client has team members who they can chat to.
* @param cio client to check members of.

View File

@ -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();
@ -109,7 +104,6 @@ public:
typedef ClientNetworkGameSocketHandler MyClient;
void NetworkClient_Connected();
void NetworkClientSetCompanyPassword(const std::string &password);
/** Information required to join a server. */
struct NetworkJoinInfo {
@ -117,7 +111,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;

View File

@ -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.

View File

@ -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<NetworkAuthenticationClientHandler> Create(std::shared_ptr<NetworkAuthenticationPasswordRequestHandler> password_handler, std::string &secret_key, std::string &public_key);
};

View File

@ -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;
@ -41,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();
@ -51,13 +48,12 @@ 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 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();
@ -73,6 +69,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);

View File

@ -1317,7 +1317,6 @@ enum DropDownAdmin {
DD_CLIENT_ADMIN_KICK,
DD_CLIENT_ADMIN_BAN,
DD_COMPANY_ADMIN_RESET,
DD_COMPANY_ADMIN_UNLOCK,
};
/**
@ -1350,15 +1349,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.
*
@ -1429,7 +1419,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.
@ -1465,10 +1454,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);
}
@ -1520,7 +1505,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;
@ -1542,18 +1526,25 @@ private:
ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, client_id);
}
static void OnClickClientAuthorize([[maybe_unused]] NetworkClientListWindow *w, [[maybe_unused]] Point pt, ClientID client_id)
{
AutoRestoreBackup<CompanyID> cur_company(_current_company, NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas);
Command<CMD_COMPANY_ALLOW_LIST_CTRL>::Post(CALCA_ADD, 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.
* @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;
@ -1564,6 +1555,7 @@ private:
if (_network_server) this->buttons[line_count].push_back(std::make_unique<ClientButton>(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<ClientButton>(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<ClientButton>(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;
@ -1598,18 +1590,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);
}
@ -1866,13 +1858,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();
}
@ -1913,10 +1898,6 @@ public:
this->InvalidateData();
break;
}
case WID_CL_COMPANY_JOIN:
NetworkClientRequestMove(this->join_company, str);
break;
}
}
@ -2233,127 +2214,13 @@ void ShowJoinStatusWindow()
new NetworkJoinStatusWindow(&_network_join_status_window_desc);
}
void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr<NetworkAuthenticationPasswordRequest> request)
void ShowNetworkNeedPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request)
{
NetworkJoinStatusWindow *w = dynamic_cast<NetworkJoinStatusWindow *>(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);
}
struct NetworkCompanyPasswordWindow : public Window {
QueryString password_editbox; ///< Password editbox.
Dimension warning_size; ///< How much space to use for the warning text
NetworkCompanyPasswordWindow(WindowDesc *desc, Window *parent) : Window(desc), password_editbox(NETWORK_PASSWORD_LENGTH)
{
this->InitNested(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);
ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_GAME_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_NONE);
}
/**

View File

@ -17,12 +17,11 @@
#include "network_type.h"
#include "network_gamelist.h"
void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr<class NetworkAuthenticationPasswordRequest> request);
void ShowNetworkNeedPassword(std::shared_ptr<class NetworkAuthenticationPasswordRequest> request);
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();

View File

@ -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);
@ -116,7 +114,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);

View File

@ -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));
}
@ -412,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<Packet>(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
@ -472,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) || _network_company_states[ci->client_playas].password.empty()) {
return this->SendWelcome();
}
/* Reset 'lag' counters */
this->last_frame = this->last_frame_server = _frame_counter;
auto p = std::make_unique<Packet>(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;
@ -516,8 +491,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
auto p = std::make_unique<Packet>(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 */
@ -839,19 +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<Packet>(this, PACKET_SERVER_COMPANY_UPDATE);
static_assert(sizeof(_network_company_passworded) <= sizeof(uint16_t));
p->Send_uint16(_network_company_passworded);
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)
@ -938,6 +898,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;
}
@ -959,6 +924,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 */
@ -1019,29 +985,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(P
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &p)
{
if (this->status != STATUS_AUTH_COMPANY) {
return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
}
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();
}
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet &)
{
/* The client was never joined.. so this is impossible, right?
@ -1102,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 */
@ -1177,6 +1117,24 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet
}
}
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;
/* 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<CommandTraits<CMD_COMPANY_ALLOW_LIST_CTRL>::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);
@ -1453,22 +1411,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) {
@ -1540,16 +1482,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 && !_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 */
@ -1614,11 +1549,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()
{
@ -1653,19 +1587,11 @@ static void NetworkAutoCleanCompanies()
/* The company is empty for one month more */
if (c->months_empty != std::numeric_limits<decltype(c->months_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<CMD_COMPANY_CTRL>::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)) {
@ -1742,25 +1668,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(CompanyID company_id, const std::string &password, 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());
}
/**
* Handle the command-queue of a socket.
* @param cs The socket to handle the queue for.
@ -1880,7 +1787,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);
@ -2026,10 +1932,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",
@ -2069,25 +1974,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;
SB(_network_company_passworded, company_id, 1, !!passworded);
SetWindowClassesDirty(WC_COMPANY);
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
}
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.
@ -2268,20 +2154,13 @@ 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;
NetworkUpdateClientInfo(ci->client_id);
Command<CMD_COMPANY_ALLOW_LIST_CTRL>::SendNet(STR_NULL, c->index, CALCA_ADD, ci->public_key);
Command<CMD_RENAME_PRESIDENT>::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);
}
}

View File

@ -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();
@ -128,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 */

View File

@ -70,19 +70,8 @@ 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. */
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.

View File

@ -169,7 +169,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"
@ -385,7 +384,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.
/**
@ -449,7 +447,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. */
@ -486,7 +484,7 @@ static std::vector<OptionData> CreateOptions()
{
std::vector<OptionData> 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
@ -559,9 +557,6 @@ int openttd_main(std::span<char * const> 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': {
@ -900,12 +895,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<CMD_PAUSE>::Post(PM_PAUSED_NORMAL, true);
CheckEngines();

View File

@ -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. */

View File

@ -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<const SlStorageT *>(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<std::vector<std::string>, SlStorageT> || std::is_same_v<std::deque<std::string>, 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<SlStorageT *>(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<std::deque, uint32_t>::SlCalcLen(deque, conv);
case SLE_VAR_I64: return SlStorageHelper<std::deque, int64_t>::SlCalcLen(deque, conv);
case SLE_VAR_U64: return SlStorageHelper<std::deque, uint64_t>::SlCalcLen(deque, conv);
case SLE_VAR_STR: return SlStorageHelper<std::deque, std::string>::SlCalcLen(deque, conv, SL_STDSTR);
default: NOT_REACHED();
}
}
@ -1381,6 +1388,7 @@ static void SlDeque(void *deque, VarType conv)
case SLE_VAR_U32: SlStorageHelper<std::deque, uint32_t>::SlSaveLoad(deque, conv); break;
case SLE_VAR_I64: SlStorageHelper<std::deque, int64_t>::SlSaveLoad(deque, conv); break;
case SLE_VAR_U64: SlStorageHelper<std::deque, uint64_t>::SlSaveLoad(deque, conv); break;
case SLE_VAR_STR: SlStorageHelper<std::deque, std::string>::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<std::vector, uint32_t>::SlCalcLen(vector, conv);
case SLE_VAR_I64: return SlStorageHelper<std::vector, int64_t>::SlCalcLen(vector, conv);
case SLE_VAR_U64: return SlStorageHelper<std::vector, uint64_t>::SlCalcLen(vector, conv);
case SLE_VAR_STR: return SlStorageHelper<std::vector, std::string>::SlCalcLen(vector, conv, SL_STDSTR);
default: NOT_REACHED();
}
}
@ -1423,6 +1432,7 @@ static void SlVector(void *vector, VarType conv)
case SLE_VAR_U32: SlStorageHelper<std::vector, uint32_t>::SlSaveLoad(vector, conv); break;
case SLE_VAR_I64: SlStorageHelper<std::vector, int64_t>::SlSaveLoad(vector, conv); break;
case SLE_VAR_U64: SlStorageHelper<std::vector, uint64_t>::SlSaveLoad(vector, conv); break;
case SLE_VAR_STR: SlStorageHelper<std::vector, std::string>::SlSaveLoad(vector, conv, SL_STDSTR); break;
default: NOT_REACHED();
}
}

View File

@ -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
};
@ -944,6 +946,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.

View File

@ -320,12 +320,9 @@ 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_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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -97,7 +97,7 @@ static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user
*/
class DropDownListCompanyItem : public DropDownIcon<DropDownIcon<DropDownString<DropDownListItem>, true>> {
public:
DropDownListCompanyItem(CompanyID company, bool shaded) : DropDownIcon<DropDownIcon<DropDownString<DropDownListItem>, 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<DropDownIcon<DropDownString<DropDownListItem>, 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);

View File

@ -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.
};

View File

@ -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.

View File

@ -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.
};
@ -97,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.

View File

@ -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