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) {
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, "When your client's public key is in the 'authorized keys' for 'rcon', the password is not checked and may be '*'.");
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 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. */
@ -1002,6 +1003,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_AUTH_RESPONSE(P
NetworkRecvStatus status = this->SendEnableEncryption();
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->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
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 (_settings_client.network.rcon_password.empty()) return NETWORK_RECV_STATUS_OKAY;
Debug(net, 9, "client[{}] Receive_CLIENT_RCON()", this->client_id);
std::string password = p.Recv_string(NETWORK_PASSWORD_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);
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> {
protected:
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_IDENTIFY(Packet &p) override;

View File

@ -138,6 +138,7 @@ private:
"servers",
"server_bind_addresses",
"server_authorized_keys",
"rcon_authorized_keys",
};
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, "bans", _network_ban_list);
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::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::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 client_name; ///< name of the player (as client)
std::string client_secret_key; ///< The secret key of the client for authorized key logins.