mirror of https://github.com/OpenTTD/OpenTTD.git
Merge 2e21e80586
into ac6a945e26
This commit is contained in:
commit
4a36f8b962
|
@ -1,6 +1,6 @@
|
||||||
# OpenTTD's admin network
|
# OpenTTD's admin network
|
||||||
|
|
||||||
Last updated: 2011-01-20
|
Last updated: 2024-03-26
|
||||||
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
@ -49,10 +49,29 @@ Last updated: 2011-01-20
|
||||||
Create a TCP connection to the server on port 3977. The application is
|
Create a TCP connection to the server on port 3977. The application is
|
||||||
expected to authenticate within 10 seconds.
|
expected to authenticate within 10 seconds.
|
||||||
|
|
||||||
To authenticate send a `ADMIN_PACKET_ADMIN_JOIN` packet.
|
To authenticate send either an `ADMIN_PACKET_ADMIN_JOIN` or an
|
||||||
|
`ADMIN_PACKET_ADMIN_JOIN_SECURE` packet.
|
||||||
|
|
||||||
The server will reply with `ADMIN_PACKET_SERVER_PROTOCOL` followed directly by
|
The `ADMIN_PACKET_ADMIN_JOIN` packet sends the password without any
|
||||||
`ADMIN_PACKET_SERVER_WELCOME`.
|
encryption or safeguards over the connection, and as such has been disabled
|
||||||
|
by default.
|
||||||
|
|
||||||
|
The `ADMIN_PACKET_ADMIN_JOIN_SECURE` packet initiates a key exchange
|
||||||
|
authentication schema which tells te server which methods the client
|
||||||
|
supports and the server makes a choice. The server will then send an
|
||||||
|
`ADMIN_PACKET_SERVER_AUTH_REQUEST` packet to which the client has to respond
|
||||||
|
with an `ADMIN_PACKET_ADMIN_AUTH_RESPONSE` packet.
|
||||||
|
|
||||||
|
The current choices for secure authentication are authorized keys, where
|
||||||
|
the client has a private key and the server a list of authorized public
|
||||||
|
keys, and a so-called password-authenticated key exchange which allows to
|
||||||
|
authenticate using a password without actually sending the password.
|
||||||
|
The server falls back to password authentication when the client's key is
|
||||||
|
not in the list of authorized keys.
|
||||||
|
|
||||||
|
When authentication has succeeded for either of the `JOIN` schemas, the
|
||||||
|
server will reply with `ADMIN_PACKET_SERVER_PROTOCOL` followed directly
|
||||||
|
by `ADMIN_PACKET_SERVER_WELCOME`.
|
||||||
|
|
||||||
`ADMIN_PACKET_SERVER_PROTOCOL` contains details about the protocol version.
|
`ADMIN_PACKET_SERVER_PROTOCOL` contains details about the protocol version.
|
||||||
It is the job of your application to check this number and decide whether
|
It is the job of your application to check this number and decide whether
|
||||||
|
|
|
@ -1964,6 +1964,7 @@ DEF_CONSOLE_CMD(ConCompanyPassword)
|
||||||
|
|
||||||
/** All the known authorized keys with their name. */
|
/** All the known authorized keys with their name. */
|
||||||
static std::vector<std::pair<std::string_view, NetworkAuthorizedKeys *>> _console_cmd_authorized_keys{
|
static std::vector<std::pair<std::string_view, NetworkAuthorizedKeys *>> _console_cmd_authorized_keys{
|
||||||
|
{ "admin", &_settings_client.network.admin_authorized_keys },
|
||||||
{ "rcon", &_settings_client.network.rcon_authorized_keys },
|
{ "rcon", &_settings_client.network.rcon_authorized_keys },
|
||||||
{ "server", &_settings_client.network.server_authorized_keys },
|
{ "server", &_settings_client.network.server_authorized_keys },
|
||||||
};
|
};
|
||||||
|
|
|
@ -2590,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 22
|
###length 23
|
||||||
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
|
||||||
|
@ -2603,6 +2603,7 @@ 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_NOT_ON_ALLOW_LIST :not on allow list
|
||||||
|
STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE :none of the requested authentication methods is available
|
||||||
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
|
||||||
|
|
|
@ -63,6 +63,8 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet &p)
|
||||||
case ADMIN_PACKET_ADMIN_RCON: return this->Receive_ADMIN_RCON(p);
|
case ADMIN_PACKET_ADMIN_RCON: return this->Receive_ADMIN_RCON(p);
|
||||||
case ADMIN_PACKET_ADMIN_GAMESCRIPT: return this->Receive_ADMIN_GAMESCRIPT(p);
|
case ADMIN_PACKET_ADMIN_GAMESCRIPT: return this->Receive_ADMIN_GAMESCRIPT(p);
|
||||||
case ADMIN_PACKET_ADMIN_PING: return this->Receive_ADMIN_PING(p);
|
case ADMIN_PACKET_ADMIN_PING: return this->Receive_ADMIN_PING(p);
|
||||||
|
case ADMIN_PACKET_ADMIN_JOIN_SECURE: return this->Receive_ADMIN_JOIN_SECURE(p);
|
||||||
|
case ADMIN_PACKET_ADMIN_AUTH_RESPONSE: return this->Receive_ADMIN_AUTH_RESPONSE(p);
|
||||||
|
|
||||||
case ADMIN_PACKET_SERVER_FULL: return this->Receive_SERVER_FULL(p);
|
case ADMIN_PACKET_SERVER_FULL: return this->Receive_SERVER_FULL(p);
|
||||||
case ADMIN_PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p);
|
case ADMIN_PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p);
|
||||||
|
@ -91,6 +93,8 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet &p)
|
||||||
case ADMIN_PACKET_SERVER_CMD_LOGGING: return this->Receive_SERVER_CMD_LOGGING(p);
|
case ADMIN_PACKET_SERVER_CMD_LOGGING: return this->Receive_SERVER_CMD_LOGGING(p);
|
||||||
case ADMIN_PACKET_SERVER_RCON_END: return this->Receive_SERVER_RCON_END(p);
|
case ADMIN_PACKET_SERVER_RCON_END: return this->Receive_SERVER_RCON_END(p);
|
||||||
case ADMIN_PACKET_SERVER_PONG: return this->Receive_SERVER_PONG(p);
|
case ADMIN_PACKET_SERVER_PONG: return this->Receive_SERVER_PONG(p);
|
||||||
|
case ADMIN_PACKET_SERVER_AUTH_REQUEST: return this->Receive_SERVER_AUTH_REQUEST(p);
|
||||||
|
case ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION: return this->Receive_SERVER_ENABLE_ENCRYPTION(p);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Debug(net, 0, "[tcp/admin] Received invalid packet type {} from '{}' ({})", type, this->admin_name, this->admin_version);
|
Debug(net, 0, "[tcp/admin] Received invalid packet type {} from '{}' ({})", type, this->admin_name, this->admin_version);
|
||||||
|
@ -137,6 +141,8 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_RCON); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_RCON); }
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_GAMESCRIPT); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_GAMESCRIPT); }
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_PING(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_PING); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_PING(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_PING); }
|
||||||
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_JOIN_SECURE(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_JOIN_SECURE); }
|
||||||
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_AUTH_RESPONSE); }
|
||||||
|
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_FULL(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_FULL); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_FULL(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_FULL); }
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_BANNED(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_BANNED); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_BANNED(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_BANNED); }
|
||||||
|
@ -165,3 +171,5 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_NAMES(Packet &)
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_LOGGING(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_LOGGING); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_LOGGING(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_LOGGING); }
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON_END(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON_END); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON_END(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON_END); }
|
||||||
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PONG(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PONG); }
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PONG(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PONG); }
|
||||||
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_AUTH_REQUEST(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_AUTH_REQUEST); }
|
||||||
|
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION); }
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* This protocol may only be extended to ensure stability.
|
* This protocol may only be extended to ensure stability.
|
||||||
*/
|
*/
|
||||||
enum PacketAdminType : uint8_t {
|
enum PacketAdminType : uint8_t {
|
||||||
ADMIN_PACKET_ADMIN_JOIN, ///< The admin announces and authenticates itself to the server.
|
ADMIN_PACKET_ADMIN_JOIN, ///< The admin announces and authenticates itself to the server using an unsecured passwords.
|
||||||
ADMIN_PACKET_ADMIN_QUIT, ///< The admin tells the server that it is quitting.
|
ADMIN_PACKET_ADMIN_QUIT, ///< The admin tells the server that it is quitting.
|
||||||
ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY, ///< The admin tells the server the update frequency of a particular piece of information.
|
ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY, ///< The admin tells the server the update frequency of a particular piece of information.
|
||||||
ADMIN_PACKET_ADMIN_POLL, ///< The admin explicitly polls for a piece of information.
|
ADMIN_PACKET_ADMIN_POLL, ///< The admin explicitly polls for a piece of information.
|
||||||
|
@ -31,6 +31,8 @@ enum PacketAdminType : uint8_t {
|
||||||
ADMIN_PACKET_ADMIN_GAMESCRIPT, ///< The admin sends a JSON string for the GameScript.
|
ADMIN_PACKET_ADMIN_GAMESCRIPT, ///< The admin sends a JSON string for the GameScript.
|
||||||
ADMIN_PACKET_ADMIN_PING, ///< The admin sends a ping to the server, expecting a ping-reply (PONG) packet.
|
ADMIN_PACKET_ADMIN_PING, ///< The admin sends a ping to the server, expecting a ping-reply (PONG) packet.
|
||||||
ADMIN_PACKET_ADMIN_EXTERNAL_CHAT, ///< The admin sends a chat message from external source.
|
ADMIN_PACKET_ADMIN_EXTERNAL_CHAT, ///< The admin sends a chat message from external source.
|
||||||
|
ADMIN_PACKET_ADMIN_JOIN_SECURE, ///< The admin announces and starts a secure authentication handshake.
|
||||||
|
ADMIN_PACKET_ADMIN_AUTH_RESPONSE, ///< The admin responds to the authentication request.
|
||||||
|
|
||||||
ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin.
|
ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin.
|
||||||
ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned.
|
ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned.
|
||||||
|
@ -61,6 +63,8 @@ enum PacketAdminType : uint8_t {
|
||||||
ADMIN_PACKET_SERVER_RCON_END, ///< The server indicates that the remote console command has completed.
|
ADMIN_PACKET_SERVER_RCON_END, ///< The server indicates that the remote console command has completed.
|
||||||
ADMIN_PACKET_SERVER_PONG, ///< The server replies to a ping request from the admin.
|
ADMIN_PACKET_SERVER_PONG, ///< The server replies to a ping request from the admin.
|
||||||
ADMIN_PACKET_SERVER_CMD_LOGGING, ///< The server gives the admin copies of incoming command packets.
|
ADMIN_PACKET_SERVER_CMD_LOGGING, ///< The server gives the admin copies of incoming command packets.
|
||||||
|
ADMIN_PACKET_SERVER_AUTH_REQUEST, ///< The server gives the admin the used authentication method and required parameters.
|
||||||
|
ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION, ///< The server tells that authentication has completed and requests to enable encryption with the keys of the last \c ADMIN_PACKET_ADMIN_AUTH_RESPONSE.
|
||||||
|
|
||||||
INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets.
|
INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets.
|
||||||
};
|
};
|
||||||
|
@ -68,6 +72,7 @@ enum PacketAdminType : uint8_t {
|
||||||
/** Status of an admin. */
|
/** Status of an admin. */
|
||||||
enum AdminStatus {
|
enum AdminStatus {
|
||||||
ADMIN_STATUS_INACTIVE, ///< The admin is not connected nor active.
|
ADMIN_STATUS_INACTIVE, ///< The admin is not connected nor active.
|
||||||
|
ADMIN_STATUS_AUTHENTICATE, ///< The admin is connected and working on authentication.
|
||||||
ADMIN_STATUS_ACTIVE, ///< The admin is active.
|
ADMIN_STATUS_ACTIVE, ///< The admin is active.
|
||||||
ADMIN_STATUS_END, ///< Must ALWAYS be on the end of this list!! (period)
|
ADMIN_STATUS_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||||
};
|
};
|
||||||
|
@ -118,8 +123,8 @@ protected:
|
||||||
NetworkRecvStatus ReceiveInvalidPacket(PacketAdminType type);
|
NetworkRecvStatus ReceiveInvalidPacket(PacketAdminType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join the admin network:
|
* Join the admin network using an unsecured password exchange:
|
||||||
* string Password the server is expecting for this network.
|
* string Unsecured password the server is expecting for this network.
|
||||||
* string Name of the application being used to connect.
|
* string Name of the application being used to connect.
|
||||||
* string Version string of the application being used to connect.
|
* string Version string of the application being used to connect.
|
||||||
* @param p The packet that was just received.
|
* @param p The packet that was just received.
|
||||||
|
@ -200,6 +205,32 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual NetworkRecvStatus Receive_ADMIN_PING(Packet &p);
|
virtual NetworkRecvStatus Receive_ADMIN_PING(Packet &p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join the admin network using a secure authentication method:
|
||||||
|
* string Name of the application being used to connect.
|
||||||
|
* string Version string of the application being used to connect.
|
||||||
|
* uint16_t Bitmask of supported authentication methods. See \c NetworkAuthenticationMethod for the supported methods.
|
||||||
|
*
|
||||||
|
* The server will determine which of the authentication methods supplied by the client will be used.
|
||||||
|
* When there is no supported authentication method, an \c ADMIN_PACKET_SERVER_ERROR packet will be
|
||||||
|
* sent with \c NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE as error.
|
||||||
|
* @param p The packet that was just received.
|
||||||
|
* @return The state the network should have.
|
||||||
|
*/
|
||||||
|
virtual NetworkRecvStatus Receive_ADMIN_JOIN_SECURE(Packet &p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin responds to \c ADMIN_PACKET_SERVER_AUTH_REQUEST with the appropriate
|
||||||
|
* data given the agreed upon \c NetworkAuthenticationMethod.
|
||||||
|
* With \c NETWORK_AUTH_METHOD_X25519_PAKE and \c NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY:
|
||||||
|
* 32 * uint8_t Public key of the client.
|
||||||
|
* 16 * uint8_t Message authentication code (mac).
|
||||||
|
* 8 * uint8_t Encrypted message of the authentication (just random bytes).
|
||||||
|
* @param p The packet that was just received.
|
||||||
|
* @return The state the network should have.
|
||||||
|
*/
|
||||||
|
virtual NetworkRecvStatus Receive_ADMIN_AUTH_RESPONSE(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server is full (connection gets closed).
|
* The server is full (connection gets closed).
|
||||||
* @param p The packet that was just received.
|
* @param p The packet that was just received.
|
||||||
|
@ -472,6 +503,25 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual NetworkRecvStatus Receive_SERVER_CMD_LOGGING(Packet &p);
|
virtual NetworkRecvStatus Receive_SERVER_CMD_LOGGING(Packet &p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server requests authentication challenge from the admin.
|
||||||
|
* uint8_t The chosen authentication method from \c NetworkAuthenticationMethod.
|
||||||
|
* With \c NETWORK_AUTH_METHOD_X25519_PAKE and \c NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY:
|
||||||
|
* 32 * uint8_t Public key of the server.
|
||||||
|
* 24 * uint8_t Nonce to use for the encryption.
|
||||||
|
* @param p The packet that was just received.
|
||||||
|
* @return The state the network should have.
|
||||||
|
*/
|
||||||
|
virtual NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indication to the client that authentication is complete and encryption has to be used from here on forward.
|
||||||
|
* The encryption uses the shared keys generated by the last AUTH_REQUEST key exchange.
|
||||||
|
* 24 * uint8_t Nonce for encrypted connection.
|
||||||
|
* @param p The packet that was just received.
|
||||||
|
*/
|
||||||
|
virtual NetworkRecvStatus Receive_SERVER_ENABLE_ENCRYPTION(Packet &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a ping-reply (pong) to the admin that sent us the ping packet.
|
* Send a ping-reply (pong) to the admin that sent us the ping packet.
|
||||||
* uint32_t Integer identifier - should be the same as read from the admins ping packet.
|
* uint32_t Integer identifier - should be the same as read from the admins ping packet.
|
||||||
|
|
|
@ -379,6 +379,7 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err)
|
||||||
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,
|
STR_NETWORK_ERROR_CLIENT_NOT_ON_ALLOW_LIST,
|
||||||
|
STR_NETWORK_ERROR_CLIENT_NO_AUTHENTICATION_METHOD_AVAILABLE,
|
||||||
};
|
};
|
||||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||||
|
|
||||||
|
@ -948,8 +949,8 @@ bool NetworkServerStart()
|
||||||
Debug(net, 5, "Starting listeners for clients");
|
Debug(net, 5, "Starting listeners for clients");
|
||||||
if (!ServerNetworkGameSocketHandler::Listen(_settings_client.network.server_port)) return false;
|
if (!ServerNetworkGameSocketHandler::Listen(_settings_client.network.server_port)) return false;
|
||||||
|
|
||||||
/* Only listen for admins when the password isn't empty. */
|
/* Only listen for admins when the authentication is configured. */
|
||||||
if (!_settings_client.network.admin_password.empty()) {
|
if (_settings_client.network.AdminAuthenticationConfigured()) {
|
||||||
Debug(net, 5, "Starting listeners for admins");
|
Debug(net, 5, "Starting listeners for admins");
|
||||||
if (!ServerNetworkAdminSocketHandler::Listen(_settings_client.network.server_admin_port)) return false;
|
if (!ServerNetworkAdminSocketHandler::Listen(_settings_client.network.server_admin_port)) return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ uint8_t _network_admins_connected = 0;
|
||||||
NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
|
NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
|
||||||
INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
|
INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
|
||||||
|
|
||||||
|
static NetworkAuthenticationDefaultPasswordProvider _admin_password_provider(_settings_client.network.admin_password); ///< Provides the password validation for the game's password.
|
||||||
|
static NetworkAuthenticationDefaultAuthorizedKeyHandler _admin_authorized_key_handler(_settings_client.network.admin_authorized_keys); ///< Provides the authorized key handling for the game authentication.
|
||||||
|
|
||||||
/** The timeout for authorisation of the client. */
|
/** The timeout for authorisation of the client. */
|
||||||
static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
|
static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
|
||||||
|
|
||||||
|
@ -90,7 +93,7 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
|
||||||
*/
|
*/
|
||||||
/* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
|
/* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
|
||||||
{
|
{
|
||||||
bool accept = !_settings_client.network.admin_password.empty() && _network_admins_connected < MAX_ADMINS;
|
bool accept = _settings_client.network.AdminAuthenticationConfigured() && _network_admins_connected < MAX_ADMINS;
|
||||||
/* We can't go over the MAX_ADMINS limit here. However, if we accept
|
/* We can't go over the MAX_ADMINS limit here. However, if we accept
|
||||||
* the connection, there has to be space in the pool. */
|
* the connection, there has to be space in the pool. */
|
||||||
static_assert(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS);
|
static_assert(NetworkAdminSocketPool::MAX_SIZE == MAX_ADMINS);
|
||||||
|
@ -102,7 +105,7 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
|
||||||
/* static */ void ServerNetworkAdminSocketHandler::Send()
|
/* static */ void ServerNetworkAdminSocketHandler::Send()
|
||||||
{
|
{
|
||||||
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
|
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
|
||||||
if (as->status == ADMIN_STATUS_INACTIVE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) {
|
if (as->status <= ADMIN_STATUS_AUTHENTICATE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) {
|
||||||
Debug(net, 2, "[admin] Admin did not send its authorisation within {} seconds", std::chrono::duration_cast<std::chrono::seconds>(ADMIN_AUTHORISATION_TIMEOUT).count());
|
Debug(net, 2, "[admin] Admin did not send its authorisation within {} seconds", std::chrono::duration_cast<std::chrono::seconds>(ADMIN_AUTHORISATION_TIMEOUT).count());
|
||||||
as->CloseConnection(true);
|
as->CloseConnection(true);
|
||||||
continue;
|
continue;
|
||||||
|
@ -134,6 +137,9 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
|
||||||
*/
|
*/
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
|
||||||
{
|
{
|
||||||
|
/* Whatever the error might be, authentication (keys) must be released as soon as possible. */
|
||||||
|
this->authentication_handler = nullptr;
|
||||||
|
|
||||||
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_ERROR);
|
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_ERROR);
|
||||||
|
|
||||||
p->Send_uint8(error);
|
p->Send_uint8(error);
|
||||||
|
@ -149,6 +155,8 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode er
|
||||||
/** Send the protocol version to the admin. */
|
/** Send the protocol version to the admin. */
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
|
||||||
{
|
{
|
||||||
|
this->status = ADMIN_STATUS_ACTIVE;
|
||||||
|
|
||||||
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_PROTOCOL);
|
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_PROTOCOL);
|
||||||
|
|
||||||
/* announce the protocol version */
|
/* announce the protocol version */
|
||||||
|
@ -491,7 +499,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRcon(uint16_t colour, con
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
|
std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
|
||||||
|
|
||||||
|
@ -505,7 +513,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet &p)
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
std::string json = p.Recv_string(NETWORK_GAMESCRIPT_JSON_LENGTH);
|
std::string json = p.Recv_string(NETWORK_GAMESCRIPT_JSON_LENGTH);
|
||||||
|
|
||||||
|
@ -517,7 +525,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Pack
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
uint32_t d1 = p.Recv_uint32();
|
uint32_t d1 = p.Recv_uint32();
|
||||||
|
|
||||||
|
@ -631,6 +639,11 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
|
if (!_settings_client.network.allow_insecure_admin_login) {
|
||||||
|
/* You're not authorized to login using this method. */
|
||||||
|
return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
|
std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
|
||||||
|
|
||||||
if (_settings_client.network.admin_password.empty() ||
|
if (_settings_client.network.admin_password.empty() ||
|
||||||
|
@ -647,8 +660,6 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet &p)
|
||||||
return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
|
return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->status = ADMIN_STATUS_ACTIVE;
|
|
||||||
|
|
||||||
Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
|
Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
|
||||||
|
|
||||||
return this->SendProtocol();
|
return this->SendProtocol();
|
||||||
|
@ -662,7 +673,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet &)
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
AdminUpdateType type = (AdminUpdateType)p.Recv_uint16();
|
AdminUpdateType type = (AdminUpdateType)p.Recv_uint16();
|
||||||
AdminUpdateFrequency freq = (AdminUpdateFrequency)p.Recv_uint16();
|
AdminUpdateFrequency freq = (AdminUpdateFrequency)p.Recv_uint16();
|
||||||
|
@ -682,7 +693,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENC
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
AdminUpdateType type = (AdminUpdateType)p.Recv_uint8();
|
AdminUpdateType type = (AdminUpdateType)p.Recv_uint8();
|
||||||
uint32_t d1 = p.Recv_uint32();
|
uint32_t d1 = p.Recv_uint32();
|
||||||
|
@ -748,7 +759,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet &p)
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
NetworkAction action = (NetworkAction)p.Recv_uint8();
|
NetworkAction action = (NetworkAction)p.Recv_uint8();
|
||||||
DestType desttype = (DestType)p.Recv_uint8();
|
DestType desttype = (DestType)p.Recv_uint8();
|
||||||
|
@ -774,7 +785,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet &p)
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet &p)
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet &p)
|
||||||
{
|
{
|
||||||
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
if (this->status <= ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
std::string source = p.Recv_string(NETWORK_CHAT_LENGTH);
|
std::string source = p.Recv_string(NETWORK_CHAT_LENGTH);
|
||||||
TextColour colour = (TextColour)p.Recv_uint16();
|
TextColour colour = (TextColour)p.Recv_uint16();
|
||||||
|
@ -791,6 +802,86 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(P
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secure authentication send and receive methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN_SECURE(Packet &p)
|
||||||
|
{
|
||||||
|
if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
|
this->admin_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH);
|
||||||
|
this->admin_version = p.Recv_string(NETWORK_REVISION_LENGTH);
|
||||||
|
NetworkAuthenticationMethodMask method_mask = p.Recv_uint16();
|
||||||
|
|
||||||
|
/* Always exclude key exchange only, as that provides no credential checking. */
|
||||||
|
ClrBit(method_mask, NETWORK_AUTH_METHOD_X25519_KEY_EXCHANGE_ONLY);
|
||||||
|
|
||||||
|
if (this->admin_name.empty() || this->admin_version.empty()) {
|
||||||
|
/* No name or version supplied. */
|
||||||
|
return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto handler = NetworkAuthenticationServerHandler::Create(&_admin_password_provider, &_admin_authorized_key_handler, method_mask);
|
||||||
|
if (!handler->CanBeUsed()) return this->SendError(NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE);
|
||||||
|
|
||||||
|
this->authentication_handler = std::move(handler);
|
||||||
|
Debug(net, 3, "[admin] '{}' ({}) has connected", this->admin_name, this->admin_version);
|
||||||
|
|
||||||
|
return this->SendAuthRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendAuthRequest()
|
||||||
|
{
|
||||||
|
this->status = ADMIN_STATUS_AUTHENTICATE;
|
||||||
|
|
||||||
|
Debug(net, 6, "[admin] '{}' ({}) authenticating using {}", this->admin_name, this->admin_version, this->authentication_handler->GetName());
|
||||||
|
|
||||||
|
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_AUTH_REQUEST);
|
||||||
|
this->authentication_handler->SendRequest(*p);
|
||||||
|
|
||||||
|
this->SendPacket(std::move(p));
|
||||||
|
|
||||||
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendEnableEncryption()
|
||||||
|
{
|
||||||
|
if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
|
auto p = std::make_unique<Packet>(this, ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION);
|
||||||
|
this->authentication_handler->SendEnableEncryption(*p);
|
||||||
|
this->SendPacket(std::move(p));
|
||||||
|
|
||||||
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(Packet &p)
|
||||||
|
{
|
||||||
|
if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
|
||||||
|
|
||||||
|
switch (this->authentication_handler->ReceiveResponse(p)) {
|
||||||
|
case NetworkAuthenticationServerHandler::AUTHENTICATED:
|
||||||
|
Debug(net, 3, "[admin] '{}' ({}) authenticated", this->admin_name, this->admin_version);
|
||||||
|
|
||||||
|
this->SendEnableEncryption();
|
||||||
|
|
||||||
|
this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
|
||||||
|
this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
|
||||||
|
this->authentication_handler = nullptr;
|
||||||
|
return this->SendProtocol();
|
||||||
|
|
||||||
|
case NetworkAuthenticationServerHandler::RETRY_NEXT_METHOD:
|
||||||
|
Debug(net, 6, "[admin] '{}' ({}) authentication failed, trying next method", this->admin_name, this->admin_version);
|
||||||
|
return this->SendAuthRequest();
|
||||||
|
|
||||||
|
case NetworkAuthenticationServerHandler::NOT_AUTHENTICATED:
|
||||||
|
default:
|
||||||
|
Debug(net, 3, "[admin] '{}' ({}) authentication failed", this->admin_name, this->admin_version);
|
||||||
|
return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Useful wrapper functions
|
* Useful wrapper functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,6 +23,8 @@ extern NetworkAdminSocketPool _networkadminsocket_pool;
|
||||||
|
|
||||||
/** Class for handling the server side of the game connection. */
|
/** Class for handling the server side of the game connection. */
|
||||||
class ServerNetworkAdminSocketHandler : public NetworkAdminSocketPool::PoolItem<&_networkadminsocket_pool>, public NetworkAdminSocketHandler, public TCPListenHandler<ServerNetworkAdminSocketHandler, ADMIN_PACKET_SERVER_FULL, ADMIN_PACKET_SERVER_BANNED> {
|
class ServerNetworkAdminSocketHandler : public NetworkAdminSocketPool::PoolItem<&_networkadminsocket_pool>, public NetworkAdminSocketHandler, public TCPListenHandler<ServerNetworkAdminSocketHandler, ADMIN_PACKET_SERVER_FULL, ADMIN_PACKET_SERVER_BANNED> {
|
||||||
|
private:
|
||||||
|
std::unique_ptr<NetworkAuthenticationServerHandler> authentication_handler; ///< The handler for the authentication.
|
||||||
protected:
|
protected:
|
||||||
NetworkRecvStatus Receive_ADMIN_JOIN(Packet &p) override;
|
NetworkRecvStatus Receive_ADMIN_JOIN(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_ADMIN_QUIT(Packet &p) override;
|
NetworkRecvStatus Receive_ADMIN_QUIT(Packet &p) override;
|
||||||
|
@ -33,9 +35,13 @@ protected:
|
||||||
NetworkRecvStatus Receive_ADMIN_RCON(Packet &p) override;
|
NetworkRecvStatus Receive_ADMIN_RCON(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_ADMIN_GAMESCRIPT(Packet &p) override;
|
NetworkRecvStatus Receive_ADMIN_GAMESCRIPT(Packet &p) override;
|
||||||
NetworkRecvStatus Receive_ADMIN_PING(Packet &p) override;
|
NetworkRecvStatus Receive_ADMIN_PING(Packet &p) override;
|
||||||
|
NetworkRecvStatus Receive_ADMIN_JOIN_SECURE(Packet &p) override;
|
||||||
|
NetworkRecvStatus Receive_ADMIN_AUTH_RESPONSE(Packet &p) override;
|
||||||
|
|
||||||
NetworkRecvStatus SendProtocol();
|
NetworkRecvStatus SendProtocol();
|
||||||
NetworkRecvStatus SendPong(uint32_t d1);
|
NetworkRecvStatus SendPong(uint32_t d1);
|
||||||
|
NetworkRecvStatus SendAuthRequest();
|
||||||
|
NetworkRecvStatus SendEnableEncryption();
|
||||||
public:
|
public:
|
||||||
AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals.
|
AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals.
|
||||||
std::chrono::steady_clock::time_point connect_time; ///< Time of connection.
|
std::chrono::steady_clock::time_point connect_time; ///< Time of connection.
|
||||||
|
|
|
@ -682,6 +682,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p
|
||||||
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
|
STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST, // NETWORK_ERROR_NOT_ON_ALLOW_LIST
|
||||||
|
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE
|
||||||
};
|
};
|
||||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ public:
|
||||||
|
|
||||||
/** The authentication method that can be used. */
|
/** The authentication method that can be used. */
|
||||||
enum NetworkAuthenticationMethod : uint8_t {
|
enum NetworkAuthenticationMethod : uint8_t {
|
||||||
NETWORK_AUTH_METHOD_X25519_KEY_EXCHANGE_ONLY, ///< No actual authentication is taking place, just perform a x25519 key exchange.
|
NETWORK_AUTH_METHOD_X25519_KEY_EXCHANGE_ONLY, ///< No actual authentication is taking place, just perform a x25519 key exchange. This method is not supported for the admin connection.
|
||||||
NETWORK_AUTH_METHOD_X25519_PAKE, ///< Authentication using x25519 password-authenticated key agreement.
|
NETWORK_AUTH_METHOD_X25519_PAKE, ///< Authentication using x25519 password-authenticated key agreement.
|
||||||
NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY, ///< Authentication using x22519 key exchange and authorized keys.
|
NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY, ///< Authentication using x22519 key exchange and authorized keys.
|
||||||
NETWORK_AUTH_METHOD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
NETWORK_AUTH_METHOD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum NetworkErrorCode {
|
||||||
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_NOT_ON_ALLOW_LIST,
|
||||||
|
NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE,
|
||||||
|
|
||||||
NETWORK_ERROR_END,
|
NETWORK_ERROR_END,
|
||||||
};
|
};
|
||||||
|
|
|
@ -140,6 +140,7 @@ private:
|
||||||
"server_bind_addresses",
|
"server_bind_addresses",
|
||||||
"server_authorized_keys",
|
"server_authorized_keys",
|
||||||
"rcon_authorized_keys",
|
"rcon_authorized_keys",
|
||||||
|
"admin_authorized_keys"
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1266,6 +1267,7 @@ static void HandleSettingDescs(IniFile &generic_ini, IniFile &private_ini, IniFi
|
||||||
proc_list(private_ini, "bans", _network_ban_list);
|
proc_list(private_ini, "bans", _network_ban_list);
|
||||||
proc_list(private_ini, "server_authorized_keys", _settings_client.network.server_authorized_keys);
|
proc_list(private_ini, "server_authorized_keys", _settings_client.network.server_authorized_keys);
|
||||||
proc_list(private_ini, "rcon_authorized_keys", _settings_client.network.rcon_authorized_keys);
|
proc_list(private_ini, "rcon_authorized_keys", _settings_client.network.rcon_authorized_keys);
|
||||||
|
proc_list(private_ini, "admin_authorized_keys", _settings_client.network.admin_authorized_keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,9 @@ struct NetworkSettings {
|
||||||
NetworkAuthorizedKeys server_authorized_keys; ///< Public keys of clients that are authorized to connect to the game.
|
NetworkAuthorizedKeys server_authorized_keys; ///< Public keys of clients that are authorized to connect to the game.
|
||||||
std::string rcon_password; ///< password for rconsole (server side)
|
std::string rcon_password; ///< password for rconsole (server side)
|
||||||
NetworkAuthorizedKeys rcon_authorized_keys; ///< Public keys of clients that are authorized to use the rconsole (server side).
|
NetworkAuthorizedKeys rcon_authorized_keys; ///< Public keys of clients that are authorized to use the rconsole (server side).
|
||||||
|
bool allow_insecure_admin_login; ///< Whether to allow logging in as admin using the insecure old JOIN packet.
|
||||||
std::string admin_password; ///< password for the admin network
|
std::string admin_password; ///< password for the admin network
|
||||||
|
NetworkAuthorizedKeys admin_authorized_keys; ///< Public keys of clients that are authorized to use the admin network.
|
||||||
std::string client_name; ///< name of the player (as client)
|
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_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 client_public_key; ///< The public key of the client for authorized key logins.
|
||||||
|
@ -336,6 +338,8 @@ struct NetworkSettings {
|
||||||
std::string last_joined; ///< Last joined server
|
std::string last_joined; ///< Last joined server
|
||||||
UseRelayService use_relay_service; ///< Use relay service?
|
UseRelayService use_relay_service; ///< Use relay service?
|
||||||
ParticipateSurvey participate_survey; ///< Participate in the automated survey
|
ParticipateSurvey participate_survey; ///< Participate in the automated survey
|
||||||
|
|
||||||
|
bool AdminAuthenticationConfigured() const { return !this->admin_password.empty() || !this->admin_authorized_keys.empty(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Settings related to the creation of games. */
|
/** Settings related to the creation of games. */
|
||||||
|
|
|
@ -176,6 +176,12 @@ flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
|
||||||
def = true
|
def = true
|
||||||
cat = SC_EXPERT
|
cat = SC_EXPERT
|
||||||
|
|
||||||
|
[SDTC_BOOL]
|
||||||
|
var = network.allow_insecure_admin_login
|
||||||
|
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
|
||||||
|
def = false
|
||||||
|
cat = SC_EXPERT
|
||||||
|
|
||||||
[SDTC_OMANY]
|
[SDTC_OMANY]
|
||||||
var = network.server_game_type
|
var = network.server_game_type
|
||||||
type = SLE_UINT8
|
type = SLE_UINT8
|
||||||
|
|
Loading…
Reference in New Issue