From 24c9e6ff66c6386a182b0fe5eef5f371793b468e Mon Sep 17 00:00:00 2001 From: truelight Date: Sat, 15 Jan 2005 20:09:16 +0000 Subject: [PATCH] (svn r1527) -Add: RCon (Remote Connection). A server can set: 'set rcon_pw ' Which enables rcon. A client can now do: 'rcon ""' The command will be executed on the server. (guru3) -Fix: 'kick 1' did crash dedicated servers -Fix: server password is now correctly saved !!Warning!!: do not give your rcon password to people you do not thrust! --- console.c | 8 ++++++++ console_cmds.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- network.c | 2 ++ network.h | 20 ++++++++++++++------ network_client.c | 23 +++++++++++++++++++++++ network_client.h | 1 + network_data.h | 2 ++ network_server.c | 35 +++++++++++++++++++++++++++++++++++ network_server.h | 1 + settings.c | 3 ++- 10 files changed, 131 insertions(+), 11 deletions(-) diff --git a/console.c b/console.c index b66cbdf9d0..223a6f641e 100644 --- a/console.c +++ b/console.c @@ -11,6 +11,8 @@ #include #include "console.h" #include "network.h" +#include "network_data.h" +#include "network_server.h" #ifdef WIN32 #include @@ -372,6 +374,12 @@ void IConsolePrint(uint16 color_code, const char* string) char* i; int j; + if (_redirect_console_to_client != 0) { + /* Redirect the string to the client */ + SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string); + return; + } + if (_network_dedicated) { printf("%s\n", string); return; diff --git a/console_cmds.c b/console_cmds.c index cf58e0b1be..342fae1591 100644 --- a/console_cmds.c +++ b/console_cmds.c @@ -379,6 +379,18 @@ DEF_CONSOLE_CMD(ConBanList) return NULL; } +DEF_CONSOLE_CMD(ConRcon) +{ + if (argc < 3) { + IConsolePrint(_iconsole_color_default, "Usage: rcon "); + return NULL; + } + + SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]); + + return NULL; +} + DEF_CONSOLE_CMD(ConStatus) { const char *status; @@ -425,7 +437,7 @@ DEF_CONSOLE_CMD(ConKick) if (argc == 2) { uint32 index = atoi(argv[1]); - if (index == NETWORK_SERVER_INDEX && !_network_dedicated) { + if (index == NETWORK_SERVER_INDEX) { IConsolePrint(_iconsole_color_default, "Silly boy, you can not kick yourself!"); return NULL; } @@ -900,13 +912,14 @@ DEF_CONSOLE_CMD(ConSet) { if (argc == 3) { // Change server password if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) { - _network_game_info.server_password[0] = '\0'; + _network_server_password[0] = '\0'; _network_game_info.use_password = 0; } else { - ttd_strlcpy(_network_game_info.server_password, argv[2], sizeof(_network_game_info.server_password)); + ttd_strlcpy(_network_server_password, argv[2], sizeof(_network_server_password)); _network_game_info.use_password = 1; } - IConsolePrintF(_iconsole_color_warning, "Game-password changed to '%s'", _network_game_info.server_password); + IConsolePrintF(_iconsole_color_warning, "Game-password changed to '%s'", _network_server_password); + ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_game_info.server_password)); } else { IConsolePrintF(_iconsole_color_default, "Current game-password is set to '%s'", _network_game_info.server_password); IConsolePrint(_iconsole_color_warning, "Usage: set server_pw \"\". Use * as to set no password."); @@ -914,6 +927,28 @@ DEF_CONSOLE_CMD(ConSet) { return NULL; } + // setting the rcon password + if ((strcmp(argv[1], "rcon_pw") == 0) || (strcmp(argv[1], "rcon_password") == 0)) { + if (!_network_server) { + IConsolePrintF(_iconsole_color_error, "You are not the server"); + return NULL; + } + if (argc == 3) { + // Change server password + if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) { + _network_rcon_password[0] = '\0'; + } else { + ttd_strlcpy(_network_rcon_password, argv[2], sizeof(_network_rcon_password)); + } + IConsolePrintF(_iconsole_color_warning, "Rcon-password changed to '%s'", _network_rcon_password); + ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password)); + } else { + IConsolePrintF(_iconsole_color_default, "Current rcon-password is set to '%s'", _network_game_info.rcon_password); + IConsolePrint(_iconsole_color_warning, "Usage: set rcon_pw \"\". Use * as to disable rcon."); + } + return NULL; + } + // setting the company password if ((strcmp(argv[1],"company_pw") == 0) || (strcmp(argv[1],"company_password") == 0)) { if (!_networking) { @@ -1123,6 +1158,7 @@ DEF_CONSOLE_CMD(ConSet) { IConsolePrint(_iconsole_color_error, " - autoclean_unprotected "); IConsolePrint(_iconsole_color_error, " - company_pw \"\""); IConsolePrint(_iconsole_color_error, " - name \"\""); + IConsolePrint(_iconsole_color_error, " - rcon_pw \"\""); IConsolePrint(_iconsole_color_error, " - server_name \"\""); IConsolePrint(_iconsole_color_error, " - server_advertise on/off"); IConsolePrint(_iconsole_color_error, " - server_bind_ip "); @@ -1229,6 +1265,9 @@ void IConsoleStdLibRegister(void) IConsoleCmdHook("status", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient); IConsoleCmdHook("resetengines", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetwork); + IConsoleCmdRegister("rcon", ConRcon); + IConsoleCmdHook("rcon", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork); + IConsoleCmdRegister("ban", ConBan); IConsoleCmdHook("ban", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient); IConsoleCmdRegister("unban", ConUnBan); diff --git a/network.c b/network.c index ebbc8d2f96..c5157842d5 100644 --- a/network.c +++ b/network.c @@ -927,6 +927,8 @@ static void NetworkInitGameInfo(void) NetworkClientInfo *ci; ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name)); + ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password)); + ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password)); if (_network_game_info.server_name[0] == '\0') snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server"); diff --git a/network.h b/network.h index c03aedccae..8084377300 100644 --- a/network.h +++ b/network.h @@ -42,12 +42,15 @@ #define NETWORK_VEHICLE_TYPES 5 #define NETWORK_STATION_TYPES 5 -#define NETWORK_NAME_LENGTH 80 -#define NETWORK_HOSTNAME_LENGTH 80 -#define NETWORK_REVISION_LENGTH 10 -#define NETWORK_PASSWORD_LENGTH 20 -#define NETWORK_PLAYERS_LENGTH 200 -#define NETWORK_CLIENT_NAME_LENGTH 25 +enum { + NETWORK_NAME_LENGTH = 80, + NETWORK_HOSTNAME_LENGTH = 80, + NETWORK_REVISION_LENGTH = 10, + NETWORK_PASSWORD_LENGTH = 20, + NETWORK_PLAYERS_LENGTH = 200, + NETWORK_CLIENT_NAME_LENGTH = 25, + NETWORK_RCONCOMMAND_LENGTH = 500, +}; // This is the struct used by both client and server // some fields will be empty on the client (like game_password) by default @@ -71,6 +74,7 @@ typedef struct NetworkGameInfo { uint16 map_height; // Map height byte map_set; // Graphical set bool dedicated; // Is this a dedicated server? + char rcon_password[NETWORK_PASSWORD_LENGTH]; // RCon password for the server. "" if rcon is disabled } NetworkGameInfo; typedef struct NetworkPlayerInfo { @@ -155,6 +159,10 @@ VARDEF uint32 _network_server_bind_ip; VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH]; VARDEF bool _is_network_server; // Does this client wants to be a network-server? VARDEF char _network_server_name[NETWORK_NAME_LENGTH]; +VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH]; +VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH]; + +VARDEF uint16 _redirect_console_to_client; VARDEF uint16 _network_sync_freq; VARDEF uint8 _network_frame_freq; diff --git a/network_client.c b/network_client.c index cf64e14859..29821a5a5a 100644 --- a/network_client.c +++ b/network_client.c @@ -10,6 +10,7 @@ #include "gfx.h" #include "window.h" #include "settings.h" +#include "console.h" // This file handles all the client-commands @@ -246,6 +247,14 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg) NetworkSend_Packet(p, MY_CLIENT); } +DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command) +{ + Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON); + NetworkSend_string(p, pass); + NetworkSend_string(p, command); + NetworkSend_Packet(p, MY_CLIENT); +} + // ********** // Receiving functions @@ -741,6 +750,18 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME) return NETWORK_RECV_STATUS_SERVER_ERROR; } +DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON) +{ + char rcon_out[NETWORK_RCONCOMMAND_LENGTH]; + uint16 color_code; + + color_code = NetworkRecv_uint16(MY_CLIENT, p); + NetworkRecv_string(MY_CLIENT, p, rcon_out, sizeof(rcon_out)); + + IConsolePrint(color_code, rcon_out); + + return NETWORK_RECV_STATUS_OKAY; +} @@ -782,6 +803,8 @@ static NetworkClientPacket* const _network_client_packet[] = { RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT), RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN), RECEIVE_COMMAND(PACKET_SERVER_NEWGAME), + RECEIVE_COMMAND(PACKET_SERVER_RCON), + NULL, /*PACKET_CLIENT_RCON,*/ }; // If this fails, check the array above with network_data.h diff --git a/network_client.h b/network_client.h index dd839a1f58..7e665e3519 100644 --- a/network_client.h +++ b/network_client.h @@ -13,6 +13,7 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name); DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK); +DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command); NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs); void NetworkClient_Connected(void); diff --git a/network_data.h b/network_data.h index b011150414..d8a9956d50 100644 --- a/network_data.h +++ b/network_data.h @@ -160,6 +160,8 @@ typedef enum { PACKET_SERVER_ERROR_QUIT, PACKET_SERVER_SHUTDOWN, PACKET_SERVER_NEWGAME, + PACKET_SERVER_RCON, + PACKET_CLIENT_RCON, PACKET_END // Should ALWAYS be on the end of this list!! (period) } PacketType; diff --git a/network_server.c b/network_server.c index c746de12b6..0e37fc8ffd 100644 --- a/network_server.c +++ b/network_server.c @@ -566,6 +566,15 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME) NetworkSend_Packet(p, cs); } +DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command) +{ + Packet *p = NetworkSend_Init(PACKET_SERVER_RCON); + + NetworkSend_uint16(p, color); + NetworkSend_string(p, command); + NetworkSend_Packet(p, cs); +} + // ********** // Receiving functions // DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p @@ -1082,6 +1091,30 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME) } } +DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON) +{ + char pass[NETWORK_PASSWORD_LENGTH]; + char command[NETWORK_RCONCOMMAND_LENGTH]; + + if (_network_game_info.rcon_password[0] == '\0') + return; + + NetworkRecv_string(cs, p, pass, sizeof(pass)); + NetworkRecv_string(cs, p, command, sizeof(command)); + + if (strncmp(pass, _network_game_info.rcon_password, sizeof(pass)) != 0) { + DEBUG(net, 0)("[RCon] Wrong password from client-id %d", cs->index); + return; + } + + DEBUG(net, 0)("[RCon] Client-id %d executed: %s", cs->index, command); + + _redirect_console_to_client = cs->index; + IConsoleCmdExec(command); + _redirect_console_to_client = 0; + return; +} + // The layout for the receive-functions by the server typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p); @@ -1121,6 +1154,8 @@ static NetworkServerPacket* const _network_server_packet[] = { NULL, /*PACKET_SERVER_ERROR_QUIT,*/ NULL, /*PACKET_SERVER_SHUTDOWN,*/ NULL, /*PACKET_SERVER_NEWGAME,*/ + NULL, /*PACKET_SERVER_RCON,*/ + RECEIVE_COMMAND(PACKET_CLIENT_RCON), }; // If this fails, check the array above with network_data.h diff --git a/network_server.h b/network_server.h index 976f857844..e79948340a 100644 --- a/network_server.h +++ b/network_server.h @@ -8,6 +8,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error); DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN); DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME); +DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command); bool NetworkFindName(char new_name[NETWORK_NAME_LENGTH]); void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index); diff --git a/settings.c b/settings.c index 3ebce5e177..f880d15ffa 100644 --- a/settings.c +++ b/settings.c @@ -759,7 +759,8 @@ static const SettingDesc network_settings[] = { {"server_advertise",SDT_BOOL, (void*)false, &_network_advertise, NULL}, {"lan_internet", SDT_UINT8, (void*)0, &_network_lan_internet, NULL}, {"player_name", SDT_STRINGBUF | (lengthof(_network_player_name) << 16), NULL, &_network_player_name, NULL}, - {"server_password", SDT_STRINGBUF | (lengthof(_network_game_info.server_password) << 16), NULL, &_network_game_info.server_password, NULL}, + {"server_password", SDT_STRINGBUF | (lengthof(_network_server_password) << 16), NULL, &_network_server_password, NULL}, + {"rcon_password", SDT_STRINGBUF | (lengthof(_network_rcon_password) << 16), NULL, &_network_rcon_password, NULL}, {"server_name", SDT_STRINGBUF | (lengthof(_network_server_name) << 16), NULL, &_network_server_name, NULL}, {"connect_to_ip", SDT_STRINGBUF | (lengthof(_network_default_ip) << 16), NULL, &_network_default_ip, NULL}, {"network_id", SDT_STRINGBUF | (lengthof(_network_unique_id) << 16), NULL, &_network_unique_id, NULL},