1
0
Fork 0

(svn r19624) [1.0] -Backport from trunk:

- Fix: Possible invalid read when server moves client to spectators before he finishes joining [FS#3755] (r19613)
- Fix: Improve joining behaviour; kicking clients when entering passwords that was just cleared, 'connection lost' for people failing the password (r19610, r19609, r19608, r19607, r19606)
release/1.0
rubidium 2010-04-13 21:40:24 +00:00
parent ba8422354b
commit 7c3487501c
6 changed files with 178 additions and 123 deletions

View File

@ -35,8 +35,10 @@ enum {
PACKET_CLIENT_COMPANY_INFO, PACKET_CLIENT_COMPANY_INFO,
PACKET_SERVER_COMPANY_INFO, PACKET_SERVER_COMPANY_INFO,
PACKET_SERVER_CLIENT_INFO, PACKET_SERVER_CLIENT_INFO,
PACKET_SERVER_NEED_PASSWORD, PACKET_SERVER_NEED_GAME_PASSWORD,
PACKET_CLIENT_PASSWORD, PACKET_SERVER_NEED_COMPANY_PASSWORD,
PACKET_CLIENT_GAME_PASSWORD,
PACKET_CLIENT_COMPANY_PASSWORD,
PACKET_SERVER_WELCOME, PACKET_SERVER_WELCOME,
PACKET_CLIENT_GETMAP, PACKET_CLIENT_GETMAP,
PACKET_SERVER_WAIT, PACKET_SERVER_WAIT,
@ -74,14 +76,15 @@ struct CommandPacket;
/** Status of a client */ /** Status of a client */
enum ClientStatus { enum ClientStatus {
STATUS_INACTIVE, ///< The client is not connected nor active STATUS_INACTIVE, ///< The client is not connected nor active
STATUS_AUTHORIZING,///< The client is authorizing STATUS_AUTH_GAME, ///< The client is authorizing with game (server) password
STATUS_AUTH, ///< The client is authorized STATUS_AUTH_COMPANY, ///< The client is authorizing with company password
STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map STATUS_AUTHORIZED, ///< The client is authorized
STATUS_MAP, ///< The client is downloading the map STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map
STATUS_DONE_MAP, ///< The client has downloaded the map STATUS_MAP, ///< The client is downloading the map
STATUS_PRE_ACTIVE, ///< The client is catching up the delayed frames STATUS_DONE_MAP, ///< The client has downloaded the map
STATUS_ACTIVE, ///< The client is active within in the game STATUS_PRE_ACTIVE, ///< The client is catching up the delayed frames
STATUS_ACTIVE, ///< The client is active within in the game
}; };
class NetworkClientSocket; class NetworkClientSocket;

View File

@ -452,7 +452,7 @@ static bool NetworkHasJoiningClient()
{ {
const NetworkClientSocket *cs; const NetworkClientSocket *cs;
FOR_ALL_CLIENT_SOCKETS(cs) { FOR_ALL_CLIENT_SOCKETS(cs) {
if (cs->status >= STATUS_AUTH && cs->status < STATUS_ACTIVE) return true; if (cs->status >= STATUS_AUTHORIZED && cs->status < STATUS_ACTIVE) return true;
} }
return false; return false;
@ -548,7 +548,7 @@ NetworkRecvStatus NetworkCloseClient(NetworkClientSocket *cs, NetworkRecvStatus
*/ */
if (cs->sock == INVALID_SOCKET) return status; if (cs->sock == INVALID_SOCKET) return status;
if (status != NETWORK_RECV_STATUS_CONN_LOST && !cs->HasClientQuit() && _network_server && cs->status > STATUS_INACTIVE) { if (status != NETWORK_RECV_STATUS_CONN_LOST && !cs->HasClientQuit() && _network_server && cs->status >= STATUS_AUTHORIZED) {
/* We did not receive a leave message from this client... */ /* We did not receive a leave message from this client... */
char client_name[NETWORK_CLIENT_NAME_LENGTH]; char client_name[NETWORK_CLIENT_NAME_LENGTH];
NetworkClientSocket *new_cs; NetworkClientSocket *new_cs;
@ -559,7 +559,7 @@ NetworkRecvStatus NetworkCloseClient(NetworkClientSocket *cs, NetworkRecvStatus
/* Inform other clients of this... strange leaving ;) */ /* Inform other clients of this... strange leaving ;) */
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status > STATUS_AUTH && cs != new_cs) { if (new_cs->status > STATUS_AUTHORIZED && cs != new_cs) {
SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, NETWORK_ERROR_CONNECTION_LOST); SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, NETWORK_ERROR_CONNECTION_LOST);
} }
} }
@ -569,7 +569,7 @@ NetworkRecvStatus NetworkCloseClient(NetworkClientSocket *cs, NetworkRecvStatus
if (_network_server) { if (_network_server) {
/* We just lost one client :( */ /* We just lost one client :( */
if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--; if (cs->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
_network_clients_connected--; _network_clients_connected--;
SetWindowDirty(WC_CLIENT_LIST, 0); SetWindowDirty(WC_CLIENT_LIST, 0);

View File

@ -167,18 +167,32 @@ DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password) DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_GAME_PASSWORD)(const char *password)
{ {
/* /*
* Packet: CLIENT_PASSWORD * Packet: CLIENT_GAME_PASSWORD
* Function: Send a password to the server to authorize * Function: Send a password to the server to authorize
* Data: * Data:
* uint8: NetworkPasswordType * uint8: NetworkPasswordType
* String: Password * String: Password
*/ */
Packet *p = new Packet(PACKET_CLIENT_PASSWORD); Packet *p = new Packet(PACKET_CLIENT_GAME_PASSWORD);
p->Send_uint8 (type); p->Send_string(password);
p->Send_string(type == NETWORK_GAME_PASSWORD ? password : GenerateCompanyPasswordHash(password)); MY_CLIENT->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY;
}
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMPANY_PASSWORD)(const char *password)
{
/*
* Packet: CLIENT_COMPANY_PASSWORD
* Function: Send a password to the server to authorize
* Data:
* uint8: NetworkPasswordType
* String: Password
*/
Packet *p = new Packet(PACKET_CLIENT_COMPANY_PASSWORD);
p->Send_string(GenerateCompanyPasswordHash(password));
MY_CLIENT->Send_Packet(p); MY_CLIENT->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
@ -535,30 +549,32 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
return ret; return ret;
} }
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD) DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)
{ {
NetworkPasswordType type = (NetworkPasswordType)p->Recv_uint8();
const char *password = _network_join_server_password; const char *password = _network_join_server_password;
if (!StrEmpty(password)) {
switch (type) { return SEND_COMMAND(PACKET_CLIENT_GAME_PASSWORD)(password);
case NETWORK_COMPANY_PASSWORD:
/* Initialize the password hash salting variables. */
_password_game_seed = p->Recv_uint32();
p->Recv_string(_password_server_id, sizeof(_password_server_id));
if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
password = _network_join_company_password;
/* FALL THROUGH */
case NETWORK_GAME_PASSWORD:
if (StrEmpty(password)) {
ShowNetworkNeedPassword(type);
} else {
return SEND_COMMAND(PACKET_CLIENT_PASSWORD)(type, password);
}
return NETWORK_RECV_STATUS_OKAY;
default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
} }
ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD);
return NETWORK_RECV_STATUS_OKAY;
}
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)
{
_password_game_seed = p->Recv_uint32();
p->Recv_string(_password_server_id, sizeof(_password_server_id));
if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
const char *password = _network_join_company_password;
if (!StrEmpty(password)) {
return SEND_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)(password);
}
ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD);
return NETWORK_RECV_STATUS_OKAY;
} }
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME) DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
@ -921,8 +937,10 @@ static NetworkClientPacket * const _network_client_packet[] = {
NULL, // PACKET_CLIENT_COMPANY_INFO, NULL, // PACKET_CLIENT_COMPANY_INFO,
RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO), RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO), RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD), RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD),
NULL, // PACKET_CLIENT_PASSWORD, RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD),
NULL, // PACKET_CLIENT_GAME_PASSWORD,
NULL, // PACKET_CLIENT_COMPANY_PASSWORD,
RECEIVE_COMMAND(PACKET_SERVER_WELCOME), RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
NULL, // PACKET_CLIENT_GETMAP, NULL, // PACKET_CLIENT_GETMAP,
RECEIVE_COMMAND(PACKET_SERVER_WAIT), RECEIVE_COMMAND(PACKET_SERVER_WAIT),

View File

@ -22,7 +22,8 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(const CommandPacket *cp);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)();
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType desttype, int dest, const char *msg, int64 data); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType desttype, int dest, const char *msg, int64 data);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_GAME_PASSWORD)(const char *password);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMPANY_PASSWORD)(const char *password);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password);
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK); DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);

View File

@ -2116,23 +2116,6 @@ void ShowClientList()
AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0); AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
} }
static NetworkPasswordType pw_type;
void ShowNetworkNeedPassword(NetworkPasswordType npt)
{
StringID caption;
pw_type = npt;
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, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL, QSF_NONE);
}
/* Vars needed for the join-GUI */ /* Vars needed for the join-GUI */
NetworkJoinStatus _network_join_status; NetworkJoinStatus _network_join_status;
uint8 _network_join_waiting; uint8 _network_join_waiting;
@ -2146,6 +2129,8 @@ enum NetworkJoinStatusWidgets {
}; };
struct NetworkJoinStatusWindow : Window { struct NetworkJoinStatusWindow : Window {
NetworkPasswordType password_type;
NetworkJoinStatusWindow(const WindowDesc *desc) : Window() NetworkJoinStatusWindow(const WindowDesc *desc) : Window()
{ {
this->parent = FindWindowById(WC_NETWORK_WINDOW, 0); this->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
@ -2225,8 +2210,13 @@ struct NetworkJoinStatusWindow : Window {
if (StrEmpty(str)) { if (StrEmpty(str)) {
NetworkDisconnect(); NetworkDisconnect();
ShowNetworkGameWindow(); ShowNetworkGameWindow();
} else { return;
SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, str); }
switch (this->password_type) {
case NETWORK_GAME_PASSWORD: SEND_COMMAND(PACKET_CLIENT_GAME_PASSWORD) (str); break;
case NETWORK_COMPANY_PASSWORD: SEND_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)(str); break;
default: NOT_REACHED();
} }
} }
}; };
@ -2257,6 +2247,21 @@ void ShowJoinStatusWindow()
new NetworkJoinStatusWindow(&_network_join_status_window_desc); new NetworkJoinStatusWindow(&_network_join_status_window_desc);
} }
void ShowNetworkNeedPassword(NetworkPasswordType npt)
{
NetworkJoinStatusWindow *w = (NetworkJoinStatusWindow *)FindWindowById(WC_NETWORK_STATUS_WINDOW, 0);
if (w == NULL) return;
w->password_type = npt;
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, 20, 180, w, CS_ALPHANUMERAL, QSF_NONE);
}
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */ /** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
enum NetworkCompanyPasswordWindowWidgets { enum NetworkCompanyPasswordWindowWidgets {

View File

@ -152,7 +152,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientSocket *cs, Netw
GetString(str, strid, lastof(str)); GetString(str, strid, lastof(str));
/* Only send when the current client was in game */ /* Only send when the current client was in game */
if (cs->status > STATUS_AUTH) { if (cs->status > STATUS_AUTHORIZED) {
NetworkClientSocket *new_cs; NetworkClientSocket *new_cs;
char client_name[NETWORK_CLIENT_NAME_LENGTH]; char client_name[NETWORK_CLIENT_NAME_LENGTH];
@ -163,7 +163,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientSocket *cs, Netw
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status > STATUS_AUTH && new_cs != cs) { if (new_cs->status > STATUS_AUTHORIZED && new_cs != cs) {
/* Some errors we filter to a more general error. Clients don't have to know the real /* Some errors we filter to a more general error. Clients don't have to know the real
* reason a joining failed. */ * reason a joining failed. */
if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
@ -209,22 +209,39 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHECK_NEWGRFS)(NetworkClientSocket *
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientSocket *cs, NetworkPasswordType type) DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_GAME_PASSWORD)(NetworkClientSocket *cs)
{ {
/* /*
* Packet: SERVER_NEED_PASSWORD * Packet: PACKET_SERVER_NEED_GAME_PASSWORD
* Function: Indication to the client that the server needs a password * Function: Indication to the client that the server needs a game password
* Data:
* uint8: Type of password
*/ */
/* Invalid packet when status is AUTH or higher */ /* Invalid packet when status is STATUS_AUTH_GAME or higher */
if (cs->status >= STATUS_AUTH) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET); if (cs->status >= STATUS_AUTH_GAME) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
cs->status = STATUS_AUTHORIZING; cs->status = STATUS_AUTH_GAME;
Packet *p = new Packet(PACKET_SERVER_NEED_PASSWORD); Packet *p = new Packet(PACKET_SERVER_NEED_GAME_PASSWORD);
p->Send_uint8(type); cs->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY;
}
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_COMPANY_PASSWORD)(NetworkClientSocket *cs)
{
/*
* Packet: PACKET_SERVER_NEED_COMPANY_PASSWORD
* Function: Indication to the client that the server needs a company password
* Data:
* uint32: Generation seed
* string: Network ID of the server
*/
/* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
if (cs->status >= STATUS_AUTH_COMPANY) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
cs->status = STATUS_AUTH_COMPANY;
Packet *p = new Packet(PACKET_SERVER_NEED_COMPANY_PASSWORD);
p->Send_uint32(_settings_game.game_creation.generation_seed); p->Send_uint32(_settings_game.game_creation.generation_seed);
p->Send_string(_settings_client.network.network_id); p->Send_string(_settings_client.network.network_id);
cs->Send_Packet(p); cs->Send_Packet(p);
@ -244,9 +261,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
NetworkClientSocket *new_cs; NetworkClientSocket *new_cs;
/* Invalid packet when status is AUTH or higher */ /* Invalid packet when status is AUTH or higher */
if (cs->status >= STATUS_AUTH) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET); if (cs->status >= STATUS_AUTHORIZED) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
cs->status = STATUS_AUTH; cs->status = STATUS_AUTHORIZED;
_network_game_info.clients_on++; _network_game_info.clients_on++;
p = new Packet(PACKET_SERVER_WELCOME); p = new Packet(PACKET_SERVER_WELCOME);
@ -257,7 +274,7 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
/* Transmit info about all the active clients */ /* Transmit info about all the active clients */
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs != cs && new_cs->status > STATUS_AUTH) if (new_cs != cs && new_cs->status > STATUS_AUTHORIZED)
SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, new_cs->GetInfo()); SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, new_cs->GetInfo());
} }
/* Also send the info of the server */ /* Also send the info of the server */
@ -308,12 +325,12 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
static FILE *file_pointer; static FILE *file_pointer;
static uint sent_packets; // How many packets we did send succecfully last time static uint sent_packets; // How many packets we did send succecfully last time
if (cs->status < STATUS_AUTH) { if (cs->status < STATUS_AUTHORIZED) {
/* Illegal call, return error and ignore the packet */ /* Illegal call, return error and ignore the packet */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
} }
if (cs->status == STATUS_AUTH) { if (cs->status == STATUS_AUTHORIZED) {
const char *filename = "network_server.tmp"; const char *filename = "network_server.tmp";
Packet *p; Packet *p;
@ -375,7 +392,7 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
/* Check if we already have a new client to send the map to */ /* Check if we already have a new client to send the map to */
if (!new_map_client) { if (!new_map_client) {
/* If not, this client will get the map */ /* If not, this client will get the map */
new_cs->status = STATUS_AUTH; new_cs->status = STATUS_AUTHORIZED;
new_map_client = true; new_map_client = true;
SEND_COMMAND(PACKET_SERVER_MAP)(new_cs); SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
} else { } else {
@ -648,11 +665,11 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
/* We now want a password from the client else we do not allow him in! */ /* We now want a password from the client else we do not allow him in! */
if (!StrEmpty(_settings_client.network.server_password)) { if (!StrEmpty(_settings_client.network.server_password)) {
return SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD); return SEND_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)(cs);
} }
if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) { if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
return SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD); return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs);
} }
return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
@ -729,42 +746,51 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs); return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
} }
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD)
{ {
NetworkPasswordType type; if (cs->status != STATUS_AUTH_GAME) {
char password[NETWORK_PASSWORD_LENGTH]; return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
const NetworkClientInfo *ci;
type = (NetworkPasswordType)p->Recv_uint8();
p->Recv_string(password, sizeof(password));
if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
/* Check game-password */
if (strcmp(password, _settings_client.network.server_password) != 0) {
/* Password is invalid */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
}
ci = cs->GetInfo();
if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
return SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
}
/* Valid password, allow user */
return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
} else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) {
ci = cs->GetInfo();
if (strcmp(password, _network_company_states[ci->client_playas].password) != 0) {
/* Password is invalid */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
}
return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
} }
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); char password[NETWORK_PASSWORD_LENGTH];
p->Recv_string(password, sizeof(password));
/* Check game password. Allow joining if we cleared the password meanwhile */
if (!StrEmpty(_settings_client.network.server_password) &&
strcmp(password, _settings_client.network.server_password) != 0) {
/* Password is invalid */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
}
const NetworkClientInfo *ci = cs->GetInfo();
if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs);
}
/* Valid password, allow user */
return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
}
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)
{
if (cs->status != STATUS_AUTH_COMPANY) {
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
}
char password[NETWORK_PASSWORD_LENGTH];
p->Recv_string(password, sizeof(password));
/* 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 = cs->GetInfo()->client_playas;
if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
strcmp(password, _network_company_states[playas].password) != 0) {
/* Password is invalid */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
}
return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
} }
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
@ -792,7 +818,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
/* The client was never joined.. so this is impossible, right? /* The client was never joined.. so this is impossible, right?
* Ignore the packet, give the client a warning, and close his connection */ * Ignore the packet, give the client a warning, and close his connection */
if (cs->status < STATUS_AUTH || cs->HasClientQuit()) { if (cs->status < STATUS_AUTHORIZED || cs->HasClientQuit()) {
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
} }
@ -833,7 +859,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
cs->last_frame_server = _frame_counter; cs->last_frame_server = _frame_counter;
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status > STATUS_AUTH) { if (new_cs->status > STATUS_AUTHORIZED) {
SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, cs->GetInfo()); SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, cs->GetInfo());
SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id); SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id);
} }
@ -966,7 +992,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status > STATUS_AUTH) { if (new_cs->status > STATUS_AUTHORIZED) {
SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno); SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno);
} }
} }
@ -993,7 +1019,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status > STATUS_AUTH) { if (new_cs->status > STATUS_AUTHORIZED) {
SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id); SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id);
} }
} }
@ -1004,7 +1030,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
{ {
if (cs->status < STATUS_AUTH) { if (cs->status < STATUS_AUTHORIZED) {
/* Illegal call, return error and ignore the packet */ /* Illegal call, return error and ignore the packet */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
} }
@ -1131,7 +1157,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
{ {
if (cs->status < STATUS_AUTH) { if (cs->status < STATUS_AUTHORIZED) {
/* Illegal call, return error and ignore the packet */ /* Illegal call, return error and ignore the packet */
return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
} }
@ -1272,8 +1298,10 @@ static NetworkServerPacket * const _network_server_packet[] = {
RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO), RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
NULL, // PACKET_SERVER_COMPANY_INFO, NULL, // PACKET_SERVER_COMPANY_INFO,
NULL, // PACKET_SERVER_CLIENT_INFO, NULL, // PACKET_SERVER_CLIENT_INFO,
NULL, // PACKET_SERVER_NEED_PASSWORD, NULL, // PACKET_SERVER_NEED_GAME_PASSWORD,
RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD), NULL, // PACKET_SERVER_NEED_COMPANY_PASSWORD,
RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD),
RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD),
NULL, // PACKET_SERVER_WELCOME, NULL, // PACKET_SERVER_WELCOME,
RECEIVE_COMMAND(PACKET_CLIENT_GETMAP), RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
NULL, // PACKET_SERVER_WAIT, NULL, // PACKET_SERVER_WAIT,