Feature: authorized key authentication for rcon

This commit is contained in:
Rubidium 2024-03-17 11:18:37 +01:00 committed by rubidium42
parent 1cf8799810
commit b7dfa3eb90
5 changed files with 12 additions and 3 deletions

View File

@ -836,6 +836,7 @@ DEF_CONSOLE_CMD(ConRcon)
if (argc == 0) { if (argc == 0) {
IConsolePrint(CC_HELP, "Remote control the server from another client. Usage: 'rcon <password> <command>'."); IConsolePrint(CC_HELP, "Remote control the server from another client. Usage: 'rcon <password> <command>'.");
IConsolePrint(CC_HELP, "Remember to enclose the command in quotes, otherwise only the first parameter is sent."); IConsolePrint(CC_HELP, "Remember to enclose the command in quotes, otherwise only the first parameter is sent.");
IConsolePrint(CC_HELP, "When your client's public key is in the 'authorized keys' for 'rcon', the password is not checked and may be '*'.");
return true; return true;
} }

View File

@ -60,6 +60,7 @@ template SocketList TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERV
static NetworkAuthenticationDefaultPasswordProvider _password_provider(_settings_client.network.server_password); ///< Provides the password validation for the game's password. 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. static NetworkAuthenticationDefaultAuthorizedKeyHandler _authorized_key_handler(_settings_client.network.server_authorized_keys); ///< Provides the authorized key handling for the game authentication.
static NetworkAuthenticationDefaultAuthorizedKeyHandler _rcon_authorized_key_handler(_settings_client.network.rcon_authorized_keys); ///< Provides the authorized key validation for rcon.
/** Writing a savegame directly to a number of packets. */ /** Writing a savegame directly to a number of packets. */
@ -1002,6 +1003,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(P
NetworkRecvStatus status = this->SendEnableEncryption(); NetworkRecvStatus status = this->SendEnableEncryption();
if (status != NETWORK_RECV_STATUS_OKAY) return status; if (status != NETWORK_RECV_STATUS_OKAY) return status;
this->peer_public_key = this->authentication_handler->GetPeerPublicKey();
this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler(); this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler(); this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
this->authentication_handler = nullptr; this->authentication_handler = nullptr;
@ -1503,14 +1505,16 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet &p)
{ {
if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
if (_settings_client.network.rcon_password.empty()) return NETWORK_RECV_STATUS_OKAY;
Debug(net, 9, "client[{}] Receive_CLIENT_RCON()", this->client_id); Debug(net, 9, "client[{}] Receive_CLIENT_RCON()", this->client_id);
std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH);
std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH); std::string command = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
if (_settings_client.network.rcon_password.compare(password) != 0) { if (_rcon_authorized_key_handler.IsAllowed(this->peer_public_key)) {
/* We are allowed, nothing more to validate. */
} else if (_settings_client.network.rcon_password.empty()) {
return NETWORK_RECV_STATUS_OKAY;
} else if (_settings_client.network.rcon_password.compare(password) != 0) {
Debug(net, 1, "[rcon] Wrong password from client-id {}", this->client_id); Debug(net, 1, "[rcon] Wrong password from client-id {}", this->client_id);
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }

View File

@ -24,6 +24,7 @@ extern NetworkClientSocketPool _networkclientsocket_pool;
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. std::unique_ptr<class NetworkAuthenticationServerHandler> authentication_handler; ///< The handler for the authentication.
std::string peer_public_key; ///< The public key of our client.
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;

View File

@ -138,6 +138,7 @@ private:
"servers", "servers",
"server_bind_addresses", "server_bind_addresses",
"server_authorized_keys", "server_authorized_keys",
"rcon_authorized_keys",
}; };
public: public:
@ -1287,6 +1288,7 @@ static void HandleSettingDescs(IniFile &generic_ini, IniFile &private_ini, IniFi
proc_list(private_ini, "servers", _network_host_list); proc_list(private_ini, "servers", _network_host_list);
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);
} }
} }

View File

@ -315,6 +315,7 @@ struct NetworkSettings {
std::string server_password; ///< password for joining this server std::string server_password; ///< password for joining this server
std::vector<std::string> server_authorized_keys; ///< Public keys of clients that are authorized to connect to the game. std::vector<std::string> 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)
std::vector<std::string> rcon_authorized_keys; ///< Public keys of clients that are authorized to use the rconsole (server side).
std::string admin_password; ///< password for the admin network std::string admin_password; ///< password for 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.