mirror of https://github.com/OpenTTD/OpenTTD.git
Feature: authenticate to the server without sending the password
Either using password-authentication key exchange or via authorized keys
This commit is contained in:
parent
dd532cbc77
commit
5706801ea7
|
@ -2574,6 +2574,7 @@ STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Your pla
|
||||||
STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Your server name has not been set. The name can be set at the top of the Multiplayer window
|
STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}Your server name has not been set. The name can be set at the top of the Multiplayer window
|
||||||
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}The revision of this client does not match the server's revision
|
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}The revision of this client does not match the server's revision
|
||||||
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong password
|
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong password
|
||||||
|
STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST :{WHITE}You are not on the list of allowed clients
|
||||||
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full
|
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full
|
||||||
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are banned from this server
|
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are banned from this server
|
||||||
STR_NETWORK_ERROR_KICKED :{WHITE}You were kicked out of the game
|
STR_NETWORK_ERROR_KICKED :{WHITE}You were kicked out of the game
|
||||||
|
@ -2589,7 +2590,7 @@ STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your pla
|
||||||
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possible connection loss
|
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possible connection loss
|
||||||
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION :{WHITE}The last {NUM} second{P "" s} no data has arrived from the server
|
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION :{WHITE}The last {NUM} second{P "" s} no data has arrived from the server
|
||||||
|
|
||||||
###length 21
|
###length 22
|
||||||
STR_NETWORK_ERROR_CLIENT_GENERAL :general error
|
STR_NETWORK_ERROR_CLIENT_GENERAL :general error
|
||||||
STR_NETWORK_ERROR_CLIENT_DESYNC :desync error
|
STR_NETWORK_ERROR_CLIENT_DESYNC :desync error
|
||||||
STR_NETWORK_ERROR_CLIENT_SAVEGAME :could not load map
|
STR_NETWORK_ERROR_CLIENT_SAVEGAME :could not load map
|
||||||
|
@ -2601,6 +2602,7 @@ STR_NETWORK_ERROR_CLIENT_NOT_EXPECTED :received invali
|
||||||
STR_NETWORK_ERROR_CLIENT_WRONG_REVISION :wrong revision
|
STR_NETWORK_ERROR_CLIENT_WRONG_REVISION :wrong revision
|
||||||
STR_NETWORK_ERROR_CLIENT_NAME_IN_USE :name already in use
|
STR_NETWORK_ERROR_CLIENT_NAME_IN_USE :name already in use
|
||||||
STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD :wrong password
|
STR_NETWORK_ERROR_CLIENT_WRONG_PASSWORD :wrong password
|
||||||
|
STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST :not on allow list
|
||||||
STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH :wrong company in DoCommand
|
STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH :wrong company in DoCommand
|
||||||
STR_NETWORK_ERROR_CLIENT_KICKED :kicked by server
|
STR_NETWORK_ERROR_CLIENT_KICKED :kicked by server
|
||||||
STR_NETWORK_ERROR_CLIENT_CHEATER :was trying to use a cheat
|
STR_NETWORK_ERROR_CLIENT_CHEATER :was trying to use a cheat
|
||||||
|
|
|
@ -82,9 +82,10 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet &p)
|
||||||
case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p);
|
case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p);
|
||||||
case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(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_CLIENT_IDENTIFY: return this->Receive_CLIENT_IDENTIFY(p);
|
||||||
case PACKET_SERVER_NEED_GAME_PASSWORD: return this->Receive_SERVER_NEED_GAME_PASSWORD(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_SERVER_NEED_COMPANY_PASSWORD: return this->Receive_SERVER_NEED_COMPANY_PASSWORD(p);
|
||||||
case PACKET_CLIENT_GAME_PASSWORD: return this->Receive_CLIENT_GAME_PASSWORD(p);
|
case PACKET_CLIENT_AUTH_RESPONSE: return this->Receive_CLIENT_AUTH_RESPONSE(p);
|
||||||
|
case PACKET_SERVER_AUTH_COMPLETED: return this->Receive_SERVER_AUTH_COMPLETED(p);
|
||||||
case PACKET_CLIENT_COMPANY_PASSWORD: return this->Receive_CLIENT_COMPANY_PASSWORD(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_SERVER_WELCOME: return this->Receive_SERVER_WELCOME(p);
|
||||||
case PACKET_CLIENT_GETMAP: return this->Receive_CLIENT_GETMAP(p);
|
case PACKET_CLIENT_GETMAP: return this->Receive_CLIENT_GETMAP(p);
|
||||||
|
@ -164,9 +165,10 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet &) {
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); }
|
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); }
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); }
|
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_CLIENT_IDENTIFY(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_IDENTIFY); }
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_GAME_PASSWORD); }
|
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_SERVER_NEED_COMPANY_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_COMPANY_PASSWORD); }
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_PASSWORD); }
|
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_AUTH_RESPONSE); }
|
||||||
|
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_AUTH_COMPLETED(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_AUTH_COMPLETED); }
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_PASSWORD); }
|
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_SERVER_WELCOME(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_WELCOME); }
|
||||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GETMAP); }
|
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GETMAP); }
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "os_abstraction.h"
|
#include "os_abstraction.h"
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
#include "../network_type.h"
|
#include "../network_type.h"
|
||||||
|
#include "../network_crypto.h"
|
||||||
#include "../../core/pool_type.hpp"
|
#include "../../core/pool_type.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
@ -56,16 +57,19 @@ enum PacketGameType : uint8_t {
|
||||||
* the map and other important data.
|
* the map and other important data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* After the initial join, the next step is identification. */
|
/* After the join step, the first perform game authentication and enabling encryption. */
|
||||||
|
PACKET_SERVER_AUTH_REQUEST, ///< The server requests the client to authenticate using a number of methods.
|
||||||
|
PACKET_CLIENT_AUTH_RESPONSE, ///< The client responds to the authentication request.
|
||||||
|
PACKET_SERVER_AUTH_COMPLETED, ///< The server indicates the authentication is completed.
|
||||||
|
|
||||||
|
/* After the authentication is done, the next step is identification. */
|
||||||
PACKET_CLIENT_IDENTIFY, ///< Client telling the server the client's name and requested company.
|
PACKET_CLIENT_IDENTIFY, ///< Client telling the server the client's name and requested company.
|
||||||
|
|
||||||
/* After the identify step, the next is checking NewGRFs. */
|
/* After the identify step, the next is checking NewGRFs. */
|
||||||
PACKET_SERVER_CHECK_NEWGRFS, ///< Server sends NewGRF IDs and MD5 checksums for the client to check.
|
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.
|
PACKET_CLIENT_NEWGRFS_CHECKED, ///< Client acknowledges that it has all required NewGRFs.
|
||||||
|
|
||||||
/* Checking the game, and then company passwords. */
|
/* Checking the company passwords. */
|
||||||
PACKET_SERVER_NEED_GAME_PASSWORD, ///< Server requests the (hashed) game password.
|
|
||||||
PACKET_CLIENT_GAME_PASSWORD, ///< Clients sends the (hashed) game password.
|
|
||||||
PACKET_SERVER_NEED_COMPANY_PASSWORD, ///< Server requests the (hashed) company password.
|
PACKET_SERVER_NEED_COMPANY_PASSWORD, ///< Server requests the (hashed) company password.
|
||||||
PACKET_CLIENT_COMPANY_PASSWORD, ///< Client sends the (hashed) company password.
|
PACKET_CLIENT_COMPANY_PASSWORD, ///< Client sends the (hashed) company password.
|
||||||
|
|
||||||
|
@ -214,10 +218,13 @@ protected:
|
||||||
virtual NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p);
|
virtual NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indication to the client that the server needs a game password.
|
* Indication to the client that it needs to authenticate:
|
||||||
|
* bool Whether to use the password in the key exchange.
|
||||||
|
* 32 * uint8_t Public key of the server.
|
||||||
|
* 24 * uint8_t Nonce for the key exchange.
|
||||||
* @param p The packet that was just received.
|
* @param p The packet that was just received.
|
||||||
*/
|
*/
|
||||||
virtual NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet &p);
|
virtual NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indication to the client that the server needs a company password:
|
* Indication to the client that the server needs a company password:
|
||||||
|
@ -228,12 +235,19 @@ protected:
|
||||||
virtual NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p);
|
virtual NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a password to the server to authorize:
|
* Send the response to the authentication request:
|
||||||
* uint8_t Password type (see NetworkPasswordType).
|
* 32 * uint8_t Public key of the client.
|
||||||
* string The password.
|
* 8 * uint8_t Random message that got encoded and signed.
|
||||||
|
* 16 * uint8_t Message authentication code.
|
||||||
* @param p The packet that was just received.
|
* @param p The packet that was just received.
|
||||||
*/
|
*/
|
||||||
virtual NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet &p);
|
virtual NetworkRecvStatus Receive_CLIENT_AUTH_RESPONSE(Packet &p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indication to the client that authentication has completed.
|
||||||
|
* @param p The packet that was just received.
|
||||||
|
*/
|
||||||
|
virtual NetworkRecvStatus Receive_SERVER_AUTH_COMPLETED(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a password to the server to authorize
|
* Send a password to the server to authorize
|
||||||
|
|
|
@ -321,6 +321,7 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err)
|
||||||
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
|
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
|
||||||
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
|
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
|
||||||
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
|
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
|
||||||
|
STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
|
||||||
};
|
};
|
||||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||||
|
|
||||||
|
|
|
@ -349,7 +349,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin()
|
||||||
p->Send_uint32(_openttd_newgrf_version);
|
p->Send_uint32(_openttd_newgrf_version);
|
||||||
my_client->SendPacket(std::move(p));
|
my_client->SendPacket(std::move(p));
|
||||||
|
|
||||||
return ClientNetworkGameSocketHandler::SendIdentify();
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendIdentify()
|
NetworkRecvStatus ClientNetworkGameSocketHandler::SendIdentify()
|
||||||
|
@ -377,13 +377,14 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendNewGRFsOk()
|
||||||
* Set the game password as requested.
|
* Set the game password as requested.
|
||||||
* @param password The game password.
|
* @param password The game password.
|
||||||
*/
|
*/
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendGamePassword(const std::string &password)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::SendAuthResponse()
|
||||||
{
|
{
|
||||||
Debug(net, 9, "Client::SendGamePassword()");
|
Debug(net, 9, "Client::SendAuthResponse()");
|
||||||
|
|
||||||
auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_GAME_PASSWORD);
|
auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_AUTH_RESPONSE);
|
||||||
p->Send_string(password);
|
my_client->authentication_handler->SendResponse(*p);
|
||||||
my_client->SendPacket(std::move(p));
|
my_client->SendPacket(std::move(p));
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,6 +681,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p
|
||||||
STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
|
STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
|
||||||
STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
|
STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
|
||||||
STR_NETWORK_ERROR_INVALID_CLIENT_NAME, // NETWORK_ERROR_INVALID_CLIENT_NAME
|
STR_NETWORK_ERROR_INVALID_CLIENT_NAME, // NETWORK_ERROR_INVALID_CLIENT_NAME
|
||||||
|
STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST, // NETWORK_ERROR_NOT_ON_ALLOW_LIST
|
||||||
};
|
};
|
||||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||||
|
|
||||||
|
@ -705,7 +707,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p
|
||||||
|
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet &p)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status != STATUS_JOIN) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
if (this->status != STATUS_AUTHENTICATED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
|
|
||||||
uint grf_count = p.Recv_uint8();
|
uint grf_count = p.Recv_uint8();
|
||||||
NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
|
NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
|
||||||
|
@ -736,26 +738,67 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSWORD(Packet &)
|
class ClientGamePasswordRequestHandler : public NetworkAuthenticationPasswordRequestHandler {
|
||||||
|
virtual void SendResponse() override { MyClient::SendAuthResponse(); }
|
||||||
|
virtual void AskUserForPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request) override
|
||||||
|
{
|
||||||
|
if (!_network_join.server_password.empty()) {
|
||||||
|
request->Reply(_network_join.server_password);
|
||||||
|
} else {
|
||||||
|
ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
if (this->status != STATUS_JOIN && this->status != STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
Debug(net, 9, "Client::status = AUTH_GAME");
|
Debug(net, 9, "Client::status = AUTH_GAME");
|
||||||
this->status = STATUS_AUTH_GAME;
|
this->status = STATUS_AUTH_GAME;
|
||||||
|
|
||||||
Debug(net, 9, "Client::Receive_SERVER_NEED_GAME_PASSWORD()");
|
Debug(net, 9, "Client::Receive_SERVER_AUTH_REQUEST()");
|
||||||
|
|
||||||
if (!_network_join.server_password.empty()) {
|
if (this->authentication_handler == nullptr) {
|
||||||
return SendGamePassword(_network_join.server_password);
|
this->authentication_handler = NetworkAuthenticationClientHandler::Create(std::make_shared<ClientGamePasswordRequestHandler>(),
|
||||||
|
_settings_client.network.client_secret_key, _settings_client.network.client_public_key);
|
||||||
}
|
}
|
||||||
|
switch (this->authentication_handler->ReceiveRequest(p)) {
|
||||||
|
case NetworkAuthenticationClientHandler::READY_FOR_RESPONSE:
|
||||||
|
return SendAuthResponse();
|
||||||
|
|
||||||
ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD);
|
case NetworkAuthenticationClientHandler::AWAIT_USER_INPUT:
|
||||||
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
case NetworkAuthenticationClientHandler::INVALID:
|
||||||
|
default:
|
||||||
|
return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_COMPLETED(Packet &)
|
||||||
|
{
|
||||||
|
if (this->status != STATUS_AUTH_GAME || this->authentication_handler == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
|
|
||||||
|
Debug(net, 9, "Client::Receive_SERVER_AUTH_COMPLETED()");
|
||||||
|
|
||||||
|
this->authentication_handler = nullptr;
|
||||||
|
|
||||||
|
Debug(net, 9, "Client::status = AUTHENTICATED");
|
||||||
|
this->status = STATUS_AUTHENTICATED;
|
||||||
|
|
||||||
|
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)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_COMPANY) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
if (this->status < STATUS_AUTHENTICATED || this->status >= STATUS_AUTH_COMPANY) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
Debug(net, 9, "Client::status = AUTH_COMPANY");
|
Debug(net, 9, "Client::status = AUTH_COMPANY");
|
||||||
this->status = STATUS_AUTH_COMPANY;
|
this->status = STATUS_AUTH_COMPANY;
|
||||||
|
|
||||||
|
@ -769,14 +812,14 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PA
|
||||||
return SendCompanyPassword(_network_join.company_password);
|
return SendCompanyPassword(_network_join.company_password);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD);
|
ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD, std::make_shared<CompanyPasswordRequest>());
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet &p)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status < STATUS_JOIN || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
if (this->status < STATUS_AUTHENTICATED || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
Debug(net, 9, "Client::status = AUTHORIZED");
|
Debug(net, 9, "Client::status = AUTHORIZED");
|
||||||
this->status = STATUS_AUTHORIZED;
|
this->status = STATUS_AUTHORIZED;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
/** Class for handling the client side of the game connection. */
|
/** Class for handling the client side of the game connection. */
|
||||||
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
|
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<class NetworkAuthenticationClientHandler> authentication_handler; ///< The handler for the authentication.
|
||||||
std::string connection_string; ///< Address we are connected to.
|
std::string connection_string; ///< Address we are connected to.
|
||||||
std::shared_ptr<struct PacketReader> savegame; ///< Packet reader for reading the savegame.
|
std::shared_ptr<struct PacketReader> savegame; ///< Packet reader for reading the savegame.
|
||||||
uint8_t token; ///< The token we need to send back to the server to prove we're the right client.
|
uint8_t token; ///< The token we need to send back to the server to prove we're the right client.
|
||||||
|
@ -23,8 +24,9 @@ private:
|
||||||
enum ServerStatus {
|
enum ServerStatus {
|
||||||
STATUS_INACTIVE, ///< The client is not connected nor active.
|
STATUS_INACTIVE, ///< The client is not connected nor active.
|
||||||
STATUS_JOIN, ///< We are trying to join a server.
|
STATUS_JOIN, ///< We are trying to join a server.
|
||||||
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
|
|
||||||
STATUS_AUTH_GAME, ///< Last action was requesting game (server) password.
|
STATUS_AUTH_GAME, ///< Last action was requesting game (server) password.
|
||||||
|
STATUS_AUTHENTICATED, ///< The game authentication has completed.
|
||||||
|
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
|
||||||
STATUS_AUTH_COMPANY, ///< Last action was requesting company password.
|
STATUS_AUTH_COMPANY, ///< Last action was requesting company password.
|
||||||
STATUS_AUTHORIZED, ///< The client is authorized at the server.
|
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_WAIT, ///< The client is waiting as someone else is downloading the map.
|
||||||
|
@ -44,7 +46,8 @@ protected:
|
||||||
NetworkRecvStatus Receive_SERVER_BANNED(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_BANNED(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_ERROR(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_ERROR(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p) override;
|
||||||
|
NetworkRecvStatus Receive_SERVER_AUTH_COMPLETED(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_SERVER_WAIT(Packet &p) override;
|
NetworkRecvStatus Receive_SERVER_WAIT(Packet &p) override;
|
||||||
|
@ -86,7 +89,7 @@ public:
|
||||||
static NetworkRecvStatus SendQuit();
|
static NetworkRecvStatus SendQuit();
|
||||||
static NetworkRecvStatus SendAck();
|
static NetworkRecvStatus SendAck();
|
||||||
|
|
||||||
static NetworkRecvStatus SendGamePassword(const std::string &password);
|
static NetworkRecvStatus SendAuthResponse();
|
||||||
static NetworkRecvStatus SendCompanyPassword(const std::string &password);
|
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 SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data);
|
||||||
|
|
|
@ -2103,7 +2103,7 @@ uint32_t _network_join_bytes; ///< The number of bytes we already do
|
||||||
uint32_t _network_join_bytes_total; ///< The total number of bytes to download.
|
uint32_t _network_join_bytes_total; ///< The total number of bytes to download.
|
||||||
|
|
||||||
struct NetworkJoinStatusWindow : Window {
|
struct NetworkJoinStatusWindow : Window {
|
||||||
NetworkPasswordType password_type;
|
std::shared_ptr<NetworkAuthenticationPasswordRequest> request;
|
||||||
|
|
||||||
NetworkJoinStatusWindow(WindowDesc *desc) : Window(desc)
|
NetworkJoinStatusWindow(WindowDesc *desc) : Window(desc)
|
||||||
{
|
{
|
||||||
|
@ -2199,16 +2199,12 @@ struct NetworkJoinStatusWindow : Window {
|
||||||
|
|
||||||
void OnQueryTextFinished(char *str) override
|
void OnQueryTextFinished(char *str) override
|
||||||
{
|
{
|
||||||
if (StrEmpty(str)) {
|
if (StrEmpty(str) || this->request == nullptr) {
|
||||||
NetworkDisconnect();
|
NetworkDisconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this->password_type) {
|
this->request->Reply(str);
|
||||||
case NETWORK_GAME_PASSWORD: MyClient::SendGamePassword (str); break;
|
|
||||||
case NETWORK_COMPANY_PASSWORD: MyClient::SendCompanyPassword(str); break;
|
|
||||||
default: NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2236,11 +2232,11 @@ void ShowJoinStatusWindow()
|
||||||
new NetworkJoinStatusWindow(&_network_join_status_window_desc);
|
new NetworkJoinStatusWindow(&_network_join_status_window_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowNetworkNeedPassword(NetworkPasswordType npt)
|
void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr<NetworkAuthenticationPasswordRequest> request)
|
||||||
{
|
{
|
||||||
NetworkJoinStatusWindow *w = (NetworkJoinStatusWindow *)FindWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
NetworkJoinStatusWindow *w = (NetworkJoinStatusWindow *)FindWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||||
if (w == nullptr) return;
|
if (w == nullptr) return;
|
||||||
w->password_type = npt;
|
w->request = request;
|
||||||
|
|
||||||
StringID caption;
|
StringID caption;
|
||||||
switch (npt) {
|
switch (npt) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "network_type.h"
|
#include "network_type.h"
|
||||||
#include "network_gamelist.h"
|
#include "network_gamelist.h"
|
||||||
|
|
||||||
void ShowNetworkNeedPassword(NetworkPasswordType npt);
|
void ShowNetworkNeedPassword(NetworkPasswordType npt, std::shared_ptr<class NetworkAuthenticationPasswordRequest> request);
|
||||||
void ShowNetworkChatQueryWindow(DestType type, int dest);
|
void ShowNetworkChatQueryWindow(DestType type, int dest);
|
||||||
void ShowJoinStatusWindow();
|
void ShowJoinStatusWindow();
|
||||||
void ShowNetworkGameWindow();
|
void ShowNetworkGameWindow();
|
||||||
|
|
|
@ -58,6 +58,10 @@ INSTANTIATE_POOL_METHODS(NetworkClientSocket)
|
||||||
/** Instantiate the listen sockets. */
|
/** Instantiate the listen sockets. */
|
||||||
template SocketList TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED>::sockets;
|
template SocketList TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED>::sockets;
|
||||||
|
|
||||||
|
static NetworkAuthenticationDefaultPasswordProvider _password_provider(_settings_client.network.server_password); ///< Provides the password validation for the game's password.
|
||||||
|
static NetworkAuthenticationDefaultAuthorizedKeyHandler _authorized_key_handler(_settings_client.network.server_authorized_keys); ///< Provides the authorized key handling for the game authentication.
|
||||||
|
|
||||||
|
|
||||||
/** Writing a savegame directly to a number of packets. */
|
/** Writing a savegame directly to a number of packets. */
|
||||||
struct PacketWriter : SaveFilter {
|
struct PacketWriter : SaveFilter {
|
||||||
ServerNetworkGameSocketHandler *cs; ///< Socket we are associated with.
|
ServerNetworkGameSocketHandler *cs; ///< Socket we are associated with.
|
||||||
|
@ -407,8 +411,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
|
||||||
this->status = STATUS_NEWGRFS_CHECK;
|
this->status = STATUS_NEWGRFS_CHECK;
|
||||||
|
|
||||||
if (_grfconfig == nullptr) {
|
if (_grfconfig == nullptr) {
|
||||||
/* There are no NewGRFs, continue with the game password. */
|
/* There are no NewGRFs, continue with the company password. */
|
||||||
return this->SendNeedGamePassword();
|
return this->SendNeedCompanyPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
|
auto p = std::make_unique<Packet>(this, PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
|
||||||
|
@ -429,25 +433,39 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Request the game password. */
|
/** Request the game password. */
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedGamePassword()
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendAuthRequest()
|
||||||
{
|
{
|
||||||
Debug(net, 9, "client[{}] SendNeedGamePassword()", this->client_id);
|
Debug(net, 9, "client[{}] SendAuthRequest()", this->client_id);
|
||||||
|
|
||||||
/* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */
|
/* Invalid packet when status is anything but STATUS_INACTIVE or STATUS_AUTH_GAME. */
|
||||||
if (this->status != STATUS_NEWGRFS_CHECK) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
if (this->status != STATUS_INACTIVE && status != STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
||||||
|
|
||||||
Debug(net, 9, "client[{}] status = AUTH_GAME", this->client_id);
|
Debug(net, 9, "client[{}] status = AUTH_GAME", this->client_id);
|
||||||
this->status = STATUS_AUTH_GAME;
|
this->status = STATUS_AUTH_GAME;
|
||||||
|
|
||||||
if (_settings_client.network.server_password.empty()) {
|
|
||||||
/* Do not actually need a game password, continue with the company password. */
|
|
||||||
return this->SendNeedCompanyPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset 'lag' counters */
|
/* Reset 'lag' counters */
|
||||||
this->last_frame = this->last_frame_server = _frame_counter;
|
this->last_frame = this->last_frame_server = _frame_counter;
|
||||||
|
|
||||||
auto p = std::make_unique<Packet>(this, PACKET_SERVER_NEED_GAME_PASSWORD);
|
if (this->authentication_handler == nullptr) {
|
||||||
|
this->authentication_handler = NetworkAuthenticationServerHandler::Create(&_password_provider, &_authorized_key_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = std::make_unique<Packet>(this, PACKET_SERVER_AUTH_REQUEST);
|
||||||
|
this->authentication_handler->SendRequest(*p);
|
||||||
|
|
||||||
|
this->SendPacket(std::move(p));
|
||||||
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notify the client that the authentication has completed. */
|
||||||
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendAuthCompleted()
|
||||||
|
{
|
||||||
|
Debug(net, 9, "client[{}] SendAuthCompleted()", this->client_id);
|
||||||
|
|
||||||
|
/* Invalid packet when status is anything but STATUS_AUTH_GAME. */
|
||||||
|
if (this->status != STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
||||||
|
|
||||||
|
auto p = std::make_unique<Packet>(this, PACKET_SERVER_AUTH_COMPLETED);
|
||||||
this->SendPacket(std::move(p));
|
this->SendPacket(std::move(p));
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
@ -457,8 +475,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
|
||||||
{
|
{
|
||||||
Debug(net, 9, "client[{}] SendNeedCompanyPassword()", this->client_id);
|
Debug(net, 9, "client[{}] SendNeedCompanyPassword()", this->client_id);
|
||||||
|
|
||||||
/* Invalid packet when status is anything but STATUS_AUTH_GAME. */
|
/* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */
|
||||||
if (this->status != STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
if (this->status != STATUS_NEWGRFS_CHECK) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
||||||
|
|
||||||
Debug(net, 9, "client[{}] status = AUTH_COMPANY", this->client_id);
|
Debug(net, 9, "client[{}] status = AUTH_COMPANY", this->client_id);
|
||||||
this->status = STATUS_AUTH_COMPANY;
|
this->status = STATUS_AUTH_COMPANY;
|
||||||
|
@ -865,7 +883,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED
|
||||||
|
|
||||||
Debug(net, 9, "client[{}] Receive_CLIENT_NEWGRFS_CHECKED()", this->client_id);
|
Debug(net, 9, "client[{}] Receive_CLIENT_NEWGRFS_CHECKED()", this->client_id);
|
||||||
|
|
||||||
return this->SendNeedGamePassword();
|
return this->SendNeedCompanyPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p)
|
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p)
|
||||||
|
@ -891,13 +909,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p)
|
||||||
return this->SendError(NETWORK_ERROR_WRONG_REVISION);
|
return this->SendError(NETWORK_ERROR_WRONG_REVISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(net, 9, "client[{}] status = IDENTIFY", this->client_id);
|
return this->SendAuthRequest();
|
||||||
this->status = STATUS_IDENTIFY;
|
|
||||||
|
|
||||||
/* Reset 'lag' counters */
|
|
||||||
this->last_frame = this->last_frame_server = _frame_counter;
|
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet &p)
|
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet &p)
|
||||||
|
@ -953,24 +965,52 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet
|
||||||
return this->SendNewGRFCheck();
|
return this->SendNewGRFCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet &p)
|
static NetworkErrorCode GetErrorForAuthenticationMethod(NetworkAuthenticationMethod method)
|
||||||
|
{
|
||||||
|
switch (method) {
|
||||||
|
case NETWORK_AUTH_METHOD_X25519_PAKE:
|
||||||
|
return NETWORK_ERROR_WRONG_PASSWORD;
|
||||||
|
case NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY:
|
||||||
|
return NETWORK_ERROR_NOT_ON_ALLOW_LIST;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status != STATUS_AUTH_GAME) {
|
if (this->status != STATUS_AUTH_GAME) {
|
||||||
return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(net, 9, "client[{}] Receive_CLIENT_GAME_PASSWORD()", this->client_id);
|
Debug(net, 9, "client[{}] Receive_CLIENT_AUTH_RESPONSE()", this->client_id);
|
||||||
|
|
||||||
std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
|
auto authentication_method = this->authentication_handler->GetAuthenticationMethod();
|
||||||
|
switch (this->authentication_handler->ReceiveResponse(p)) {
|
||||||
|
case NetworkAuthenticationServerHandler::AUTHENTICATED:
|
||||||
|
break;
|
||||||
|
|
||||||
/* Check game password. Allow joining if we cleared the password meanwhile */
|
case NetworkAuthenticationServerHandler::RETRY_NEXT_METHOD:
|
||||||
if (!_settings_client.network.server_password.empty() &&
|
return this->SendAuthRequest();
|
||||||
_settings_client.network.server_password.compare(password) != 0) {
|
|
||||||
/* Password is invalid */
|
case NetworkAuthenticationServerHandler::NOT_AUTHENTICATED:
|
||||||
return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
|
default:
|
||||||
|
return this->SendError(GetErrorForAuthenticationMethod(authentication_method));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->SendNeedCompanyPassword();
|
NetworkRecvStatus status = this->SendAuthCompleted();
|
||||||
|
if (status != NETWORK_RECV_STATUS_OKAY) return status;
|
||||||
|
|
||||||
|
this->authentication_handler = nullptr;
|
||||||
|
|
||||||
|
Debug(net, 9, "client[{}] status = IDENTIFY", this->client_id);
|
||||||
|
this->status = STATUS_IDENTIFY;
|
||||||
|
|
||||||
|
/* Reset 'lag' counters */
|
||||||
|
this->last_frame = this->last_frame_server = _frame_counter;
|
||||||
|
|
||||||
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &p)
|
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet &p)
|
||||||
|
@ -1978,9 +2018,9 @@ void NetworkServerShowStatusToConsole()
|
||||||
{
|
{
|
||||||
static const char * const stat_str[] = {
|
static const char * const stat_str[] = {
|
||||||
"inactive",
|
"inactive",
|
||||||
|
"authorizing (server password)",
|
||||||
"identifing client",
|
"identifing client",
|
||||||
"checking NewGRFs",
|
"checking NewGRFs",
|
||||||
"authorizing (server password)",
|
|
||||||
"authorizing (company password)",
|
"authorizing (company password)",
|
||||||
"authorized",
|
"authorized",
|
||||||
"waiting",
|
"waiting",
|
||||||
|
|
|
@ -23,10 +23,12 @@ extern NetworkClientSocketPool _networkclientsocket_pool;
|
||||||
/** Class for handling the server side of the game connection. */
|
/** Class for handling the server side of the game connection. */
|
||||||
class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED> {
|
class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED> {
|
||||||
protected:
|
protected:
|
||||||
|
std::unique_ptr<class NetworkAuthenticationServerHandler> authentication_handler; ///< The handler for the authentication.
|
||||||
|
|
||||||
NetworkRecvStatus Receive_CLIENT_JOIN(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_JOIN(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_AUTH_RESPONSE(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_GETMAP(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_GETMAP(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet &p) override;
|
NetworkRecvStatus Receive_CLIENT_MAP_OK(Packet &p) override;
|
||||||
|
@ -44,16 +46,17 @@ protected:
|
||||||
NetworkRecvStatus SendGameInfo();
|
NetworkRecvStatus SendGameInfo();
|
||||||
NetworkRecvStatus SendNewGRFCheck();
|
NetworkRecvStatus SendNewGRFCheck();
|
||||||
NetworkRecvStatus SendWelcome();
|
NetworkRecvStatus SendWelcome();
|
||||||
NetworkRecvStatus SendNeedGamePassword();
|
NetworkRecvStatus SendAuthRequest();
|
||||||
|
NetworkRecvStatus SendAuthCompleted();
|
||||||
NetworkRecvStatus SendNeedCompanyPassword();
|
NetworkRecvStatus SendNeedCompanyPassword();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** 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_AUTH_GAME, ///< The client is authorizing with game (server) password.
|
||||||
STATUS_IDENTIFY, ///< The client is identifying itself.
|
STATUS_IDENTIFY, ///< The client is identifying itself.
|
||||||
STATUS_NEWGRFS_CHECK, ///< The client is checking NewGRFs.
|
STATUS_NEWGRFS_CHECK, ///< The client is checking NewGRFs.
|
||||||
STATUS_AUTH_GAME, ///< The client is authorizing with game (server) password.
|
|
||||||
STATUS_AUTH_COMPANY, ///< The client is authorizing with company password.
|
STATUS_AUTH_COMPANY, ///< The client is authorizing with company password.
|
||||||
STATUS_AUTHORIZED, ///< The client is authorized.
|
STATUS_AUTHORIZED, ///< The client is authorized.
|
||||||
STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map.
|
STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map.
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum NetworkErrorCode {
|
||||||
NETWORK_ERROR_TIMEOUT_MAP,
|
NETWORK_ERROR_TIMEOUT_MAP,
|
||||||
NETWORK_ERROR_TIMEOUT_JOIN,
|
NETWORK_ERROR_TIMEOUT_JOIN,
|
||||||
NETWORK_ERROR_INVALID_CLIENT_NAME,
|
NETWORK_ERROR_INVALID_CLIENT_NAME,
|
||||||
|
NETWORK_ERROR_NOT_ON_ALLOW_LIST,
|
||||||
|
|
||||||
NETWORK_ERROR_END,
|
NETWORK_ERROR_END,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue