mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r2308) - Fix: enforce server-only and/or offline commands by giving them flags in the process table. This also fixes bug "[ 1190944 ] Many commands not checked for security"
- CodeChange: move ValParamRailtype() to check rail type from command.h to vehicle.h where it is better suited.
This commit is contained in:
parent
fbb794d450
commit
2bf3d14dfc
242
command.c
242
command.c
|
@ -154,146 +154,146 @@ DEF_COMMAND(CmdRemoveSignalTrack);
|
||||||
DEF_COMMAND(CmdReplaceVehicle);
|
DEF_COMMAND(CmdReplaceVehicle);
|
||||||
|
|
||||||
/* The master command table */
|
/* The master command table */
|
||||||
static CommandProc * const _command_proc_table[] = {
|
static const Command _command_proc_table[] = {
|
||||||
CmdBuildRailroadTrack, /* 0 */
|
{CmdBuildRailroadTrack, 0}, /* 0 */
|
||||||
CmdRemoveRailroadTrack, /* 1 */
|
{CmdRemoveRailroadTrack, 0}, /* 1 */
|
||||||
CmdBuildSingleRail, /* 2 */
|
{CmdBuildSingleRail, 0}, /* 2 */
|
||||||
CmdRemoveSingleRail, /* 3 */
|
{CmdRemoveSingleRail, 0}, /* 3 */
|
||||||
CmdLandscapeClear, /* 4 */
|
{CmdLandscapeClear, 0}, /* 4 */
|
||||||
CmdBuildBridge, /* 5 */
|
{CmdBuildBridge, 0}, /* 5 */
|
||||||
CmdBuildRailroadStation, /* 6 */
|
{CmdBuildRailroadStation, 0}, /* 6 */
|
||||||
CmdBuildTrainDepot, /* 7 */
|
{CmdBuildTrainDepot, 0}, /* 7 */
|
||||||
CmdBuildSingleSignal, /* 8 */
|
{CmdBuildSingleSignal, 0}, /* 8 */
|
||||||
CmdRemoveSingleSignal, /* 9 */
|
{CmdRemoveSingleSignal, 0}, /* 9 */
|
||||||
CmdTerraformLand, /* 10 */
|
{CmdTerraformLand, 0}, /* 10 */
|
||||||
CmdPurchaseLandArea, /* 11 */
|
{CmdPurchaseLandArea, 0}, /* 11 */
|
||||||
CmdSellLandArea, /* 12 */
|
{CmdSellLandArea, 0}, /* 12 */
|
||||||
CmdBuildTunnel, /* 13 */
|
{CmdBuildTunnel, 0}, /* 13 */
|
||||||
CmdRemoveFromRailroadStation, /* 14 */
|
{CmdRemoveFromRailroadStation, 0}, /* 14 */
|
||||||
CmdConvertRail, /* 15 */
|
{CmdConvertRail, 0}, /* 15 */
|
||||||
CmdBuildTrainWaypoint, /* 16 */
|
{CmdBuildTrainWaypoint, 0}, /* 16 */
|
||||||
CmdRenameWaypoint, /* 17 */
|
{CmdRenameWaypoint, 0}, /* 17 */
|
||||||
CmdRemoveTrainWaypoint, /* 18 */
|
{CmdRemoveTrainWaypoint, 0}, /* 18 */
|
||||||
NULL, /* 19 */
|
{NULL, 0}, /* 19 */
|
||||||
NULL, /* 20 */
|
{NULL, 0}, /* 20 */
|
||||||
CmdBuildRoadStop, /* 21 */
|
{CmdBuildRoadStop, 0}, /* 21 */
|
||||||
NULL, /* 22 */
|
{NULL, 0}, /* 22 */
|
||||||
CmdBuildLongRoad, /* 23 */
|
{CmdBuildLongRoad, 0}, /* 23 */
|
||||||
CmdRemoveLongRoad, /* 24 */
|
{CmdRemoveLongRoad, 0}, /* 24 */
|
||||||
CmdBuildRoad, /* 25 */
|
{CmdBuildRoad, 0}, /* 25 */
|
||||||
CmdRemoveRoad, /* 26 */
|
{CmdRemoveRoad, 0}, /* 26 */
|
||||||
CmdBuildRoadDepot, /* 27 */
|
{CmdBuildRoadDepot, 0}, /* 27 */
|
||||||
NULL, /* 28 */
|
{NULL, 0}, /* 28 */
|
||||||
CmdBuildAirport, /* 29 */
|
{CmdBuildAirport, 0}, /* 29 */
|
||||||
CmdBuildDock, /* 30 */
|
{CmdBuildDock, 0}, /* 30 */
|
||||||
CmdBuildShipDepot, /* 31 */
|
{CmdBuildShipDepot, 0}, /* 31 */
|
||||||
CmdBuildBuoy, /* 32 */
|
{CmdBuildBuoy, 0}, /* 32 */
|
||||||
CmdPlantTree, /* 33 */
|
{CmdPlantTree, 0}, /* 33 */
|
||||||
CmdBuildRailVehicle, /* 34 */
|
{CmdBuildRailVehicle, 0}, /* 34 */
|
||||||
CmdMoveRailVehicle, /* 35 */
|
{CmdMoveRailVehicle, 0}, /* 35 */
|
||||||
CmdStartStopTrain, /* 36 */
|
{CmdStartStopTrain, 0}, /* 36 */
|
||||||
NULL, /* 37 */
|
{NULL, 0}, /* 37 */
|
||||||
CmdSellRailWagon, /* 38 */
|
{CmdSellRailWagon, 0}, /* 38 */
|
||||||
CmdSendTrainToDepot, /* 39 */
|
{CmdSendTrainToDepot, 0}, /* 39 */
|
||||||
CmdForceTrainProceed, /* 40 */
|
{CmdForceTrainProceed, 0}, /* 40 */
|
||||||
CmdReverseTrainDirection, /* 41 */
|
{CmdReverseTrainDirection, 0}, /* 41 */
|
||||||
|
|
||||||
CmdModifyOrder, /* 42 */
|
{CmdModifyOrder, 0}, /* 42 */
|
||||||
CmdSkipOrder, /* 43 */
|
{CmdSkipOrder, 0}, /* 43 */
|
||||||
CmdDeleteOrder, /* 44 */
|
{CmdDeleteOrder, 0}, /* 44 */
|
||||||
CmdInsertOrder, /* 45 */
|
{CmdInsertOrder, 0}, /* 45 */
|
||||||
|
|
||||||
CmdChangeTrainServiceInt, /* 46 */
|
{CmdChangeTrainServiceInt, 0}, /* 46 */
|
||||||
|
|
||||||
CmdBuildIndustry, /* 47 */
|
{CmdBuildIndustry, 0}, /* 47 */
|
||||||
CmdBuildCompanyHQ, /* 48 */
|
{CmdBuildCompanyHQ, 0}, /* 48 */
|
||||||
CmdSetPlayerFace, /* 49 */
|
{CmdSetPlayerFace, 0}, /* 49 */
|
||||||
CmdSetPlayerColor, /* 50 */
|
{CmdSetPlayerColor, 0}, /* 50 */
|
||||||
|
|
||||||
CmdIncreaseLoan, /* 51 */
|
{CmdIncreaseLoan, 0}, /* 51 */
|
||||||
CmdDecreaseLoan, /* 52 */
|
{CmdDecreaseLoan, 0}, /* 52 */
|
||||||
|
|
||||||
CmdWantEnginePreview, /* 53 */
|
{CmdWantEnginePreview, 0}, /* 53 */
|
||||||
|
|
||||||
CmdNameVehicle, /* 54 */
|
{CmdNameVehicle, 0}, /* 54 */
|
||||||
CmdRenameEngine, /* 55 */
|
{CmdRenameEngine, 0}, /* 55 */
|
||||||
|
|
||||||
CmdChangeCompanyName, /* 56 */
|
{CmdChangeCompanyName, 0}, /* 56 */
|
||||||
CmdChangePresidentName, /* 57 */
|
{CmdChangePresidentName, 0}, /* 57 */
|
||||||
|
|
||||||
CmdRenameStation, /* 58 */
|
{CmdRenameStation, 0}, /* 58 */
|
||||||
|
|
||||||
CmdSellAircraft, /* 59 */
|
{CmdSellAircraft, 0}, /* 59 */
|
||||||
CmdStartStopAircraft, /* 60 */
|
{CmdStartStopAircraft, 0}, /* 60 */
|
||||||
|
|
||||||
CmdBuildAircraft, /* 61 */
|
{CmdBuildAircraft, 0}, /* 61 */
|
||||||
CmdSendAircraftToHangar, /* 62 */
|
{CmdSendAircraftToHangar, 0}, /* 62 */
|
||||||
CmdChangeAircraftServiceInt, /* 63 */
|
{CmdChangeAircraftServiceInt, 0}, /* 63 */
|
||||||
CmdRefitAircraft, /* 64 */
|
{CmdRefitAircraft, 0}, /* 64 */
|
||||||
|
|
||||||
CmdPlaceSign, /* 65 */
|
{CmdPlaceSign, 0}, /* 65 */
|
||||||
CmdRenameSign, /* 66 */
|
{CmdRenameSign, 0}, /* 66 */
|
||||||
|
|
||||||
CmdBuildRoadVeh, /* 67 */
|
{CmdBuildRoadVeh, 0}, /* 67 */
|
||||||
CmdStartStopRoadVeh, /* 68 */
|
{CmdStartStopRoadVeh, 0}, /* 68 */
|
||||||
CmdSellRoadVeh, /* 69 */
|
{CmdSellRoadVeh, 0}, /* 69 */
|
||||||
CmdSendRoadVehToDepot, /* 70 */
|
{CmdSendRoadVehToDepot, 0}, /* 70 */
|
||||||
CmdTurnRoadVeh, /* 71 */
|
{CmdTurnRoadVeh, 0}, /* 71 */
|
||||||
CmdChangeRoadVehServiceInt, /* 72 */
|
{CmdChangeRoadVehServiceInt, 0}, /* 72 */
|
||||||
|
|
||||||
CmdPause, /* 73 <-- TODO: check/enforce by server */
|
{CmdPause, CMD_SERVER}, /* 73 */
|
||||||
|
|
||||||
CmdBuyShareInCompany, /* 74 */
|
{CmdBuyShareInCompany, 0}, /* 74 */
|
||||||
CmdSellShareInCompany, /* 75 */
|
{CmdSellShareInCompany, 0}, /* 75 */
|
||||||
CmdBuyCompany, /* 76 */
|
{CmdBuyCompany, 0}, /* 76 */
|
||||||
|
|
||||||
CmdBuildTown, /* 77 <-- offline */
|
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
|
||||||
NULL, /* 78 */
|
{NULL, 0}, /* 78 */
|
||||||
NULL, /* 79 */
|
{NULL, 0}, /* 79 */
|
||||||
CmdRenameTown, /* 80 <-- TODO: check/enforce by server */
|
{CmdRenameTown, CMD_SERVER}, /* 80 */
|
||||||
CmdDoTownAction, /* 81 */
|
{CmdDoTownAction, 0}, /* 81 */
|
||||||
|
|
||||||
CmdSetRoadDriveSide, /* 82 <-- TODO: check/enforce by server */
|
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
|
||||||
NULL, /* 83 */
|
{NULL, 0}, /* 83 */
|
||||||
NULL, /* 84 */
|
{NULL, 0}, /* 84 */
|
||||||
CmdChangeDifficultyLevel, /* 85 <-- TODO: check/enforce by server */
|
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
|
||||||
|
|
||||||
CmdStartStopShip, /* 86 */
|
{CmdStartStopShip, 0}, /* 86 */
|
||||||
CmdSellShip, /* 87 */
|
{CmdSellShip, 0}, /* 87 */
|
||||||
CmdBuildShip, /* 88 */
|
{CmdBuildShip, 0}, /* 88 */
|
||||||
CmdSendShipToDepot, /* 89 */
|
{CmdSendShipToDepot, 0}, /* 89 */
|
||||||
CmdChangeShipServiceInt, /* 90 */
|
{CmdChangeShipServiceInt, 0}, /* 90 */
|
||||||
CmdRefitShip, /* 91 */
|
{CmdRefitShip, 0}, /* 91 */
|
||||||
|
|
||||||
NULL, /* 92 */
|
{NULL, 0}, /* 92 */
|
||||||
NULL, /* 93 */
|
{NULL, 0}, /* 93 */
|
||||||
NULL, /* 94 */
|
{NULL, 0}, /* 94 */
|
||||||
NULL, /* 95 */
|
{NULL, 0}, /* 95 */
|
||||||
NULL, /* 96 */
|
{NULL, 0}, /* 96 */
|
||||||
NULL, /* 97 */
|
{NULL, 0}, /* 97 */
|
||||||
NULL, /* 98 */
|
{NULL, 0}, /* 98 */
|
||||||
|
|
||||||
CmdCloneOrder, /* 99 */
|
{CmdCloneOrder, 0}, /* 99 */
|
||||||
|
|
||||||
CmdClearArea, /* 100 */
|
{CmdClearArea, 0}, /* 100 */
|
||||||
NULL, /* 101 */
|
{NULL, 0}, /* 101 */
|
||||||
|
|
||||||
CmdMoneyCheat, /* 102 <-- offline (debug) */
|
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
|
||||||
CmdBuildCanal, /* 103 */
|
{CmdBuildCanal, 0}, /* 103 */
|
||||||
CmdPlayerCtrl, /* 104 */
|
{CmdPlayerCtrl, 0}, /* 104 */
|
||||||
|
|
||||||
CmdLevelLand, /* 105 */
|
{CmdLevelLand, 0}, /* 105 */
|
||||||
|
|
||||||
CmdRefitRailVehicle, /* 106 */
|
{CmdRefitRailVehicle, 0}, /* 106 */
|
||||||
CmdRestoreOrderIndex, /* 107 */
|
{CmdRestoreOrderIndex, 0}, /* 107 */
|
||||||
CmdBuildLock, /* 108 */
|
{CmdBuildLock, 0}, /* 108 */
|
||||||
NULL, /* 109 */
|
{NULL, 0}, /* 109 */
|
||||||
CmdBuildSignalTrack, /* 110 */
|
{CmdBuildSignalTrack, 0}, /* 110 */
|
||||||
CmdRemoveSignalTrack, /* 111 */
|
{CmdRemoveSignalTrack, 0}, /* 111 */
|
||||||
NULL, /* 112 */
|
{NULL, 0}, /* 112 */
|
||||||
CmdGiveMoney, /* 113 */
|
{CmdGiveMoney, 0}, /* 113 */
|
||||||
CmdChangePatchSetting, /* 114 <-- TODO: check/enforce by server */
|
{CmdChangePatchSetting, CMD_SERVER}, /* 114 */
|
||||||
CmdReplaceVehicle, /* 115 */
|
{CmdReplaceVehicle, 0}, /* 115 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||||
|
@ -301,12 +301,14 @@ bool IsValidCommand(uint cmd)
|
||||||
{
|
{
|
||||||
cmd = cmd & 0xFF;
|
cmd = cmd & 0xFF;
|
||||||
|
|
||||||
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd] == NULL)
|
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd].proc == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
|
||||||
|
|
||||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||||
{
|
{
|
||||||
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
|
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
|
||||||
|
@ -323,7 +325,7 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||||
/* Do not even think about executing out-of-bounds tile-commands */
|
/* Do not even think about executing out-of-bounds tile-commands */
|
||||||
if (TILE_FROM_XY(x,y) > MapSize()) return CMD_ERROR;
|
if (TILE_FROM_XY(x,y) > MapSize()) return CMD_ERROR;
|
||||||
|
|
||||||
proc = _command_proc_table[procc];
|
proc = _command_proc_table[procc].proc;
|
||||||
|
|
||||||
if (_docommand_recursive == 0) {
|
if (_docommand_recursive == 0) {
|
||||||
_error_message = INVALID_STRING_ID;
|
_error_message = INVALID_STRING_ID;
|
||||||
|
@ -412,7 +414,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||||
|
|
||||||
// get pointer to command handler
|
// get pointer to command handler
|
||||||
assert((cmd & 0xFF) < lengthof(_command_proc_table));
|
assert((cmd & 0xFF) < lengthof(_command_proc_table));
|
||||||
proc = _command_proc_table[cmd & 0xFF];
|
proc = _command_proc_table[cmd & 0xFF].proc;
|
||||||
|
|
||||||
// Some commands have a different output in dryrun than the realrun
|
// Some commands have a different output in dryrun than the realrun
|
||||||
// e.g.: if you demolish a whole town, the dryrun would say okay.
|
// e.g.: if you demolish a whole town, the dryrun would say okay.
|
||||||
|
|
16
command.h
16
command.h
|
@ -159,6 +159,19 @@ enum {
|
||||||
CMD_SHOW_NO_ERROR = 0x2000,
|
CMD_SHOW_NO_ERROR = 0x2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Command flags for the command table
|
||||||
|
* @see _command_proc_table
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
CMD_SERVER = 0x1, /// the command can only be initiated by the server
|
||||||
|
CMD_OFFLINE = 0x2, /// the command cannot be executed in a multiplayer game; single-player only
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Command {
|
||||||
|
CommandProc *proc;
|
||||||
|
byte flags;
|
||||||
|
} Command;
|
||||||
|
|
||||||
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
|
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
|
||||||
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
|
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
|
||||||
|
|
||||||
|
@ -178,8 +191,7 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||||
|
|
||||||
bool IsValidCommand(uint cmd);
|
bool IsValidCommand(uint cmd);
|
||||||
|
byte GetCommandFlags(uint cmd);
|
||||||
int32 GetAvailableMoneyForCommand(void);
|
int32 GetAvailableMoneyForCommand(void);
|
||||||
|
|
||||||
/* Validate functions for rail building */
|
|
||||||
static inline bool ValParamRailtype(uint32 rail) { return rail <= GetPlayer(_current_player)->max_railtype;}
|
|
||||||
#endif /* COMMAND_H */
|
#endif /* COMMAND_H */
|
||||||
|
|
14
network.h
14
network.h
|
@ -92,13 +92,13 @@ typedef struct NetworkPlayerInfo {
|
||||||
} NetworkPlayerInfo;
|
} NetworkPlayerInfo;
|
||||||
|
|
||||||
typedef struct NetworkClientInfo {
|
typedef struct NetworkClientInfo {
|
||||||
uint16 client_index; // Index of the client (same as ClientState->index)
|
uint16 client_index; /// Index of the client (same as ClientState->index)
|
||||||
char client_name[NETWORK_CLIENT_NAME_LENGTH]; // Name of the client
|
char client_name[NETWORK_CLIENT_NAME_LENGTH]; /// Name of the client
|
||||||
byte client_lang; // The language of the client
|
byte client_lang; /// The language of the client
|
||||||
byte client_playas; // As which player is this client playing
|
byte client_playas; /// As which player is this client playing (PlayerID)
|
||||||
uint32 client_ip; // IP-address of the client (so he can be banned)
|
uint32 client_ip; /// IP-address of the client (so he can be banned)
|
||||||
uint16 join_date; // Gamedate the player has joined
|
uint16 join_date; /// Gamedate the player has joined
|
||||||
char unique_id[NETWORK_NAME_LENGTH]; // Every play sends an unique id so we can indentify him
|
char unique_id[NETWORK_NAME_LENGTH]; /// Every play sends an unique id so we can indentify him
|
||||||
} NetworkClientInfo;
|
} NetworkClientInfo;
|
||||||
|
|
||||||
typedef struct NetworkGameList {
|
typedef struct NetworkGameList {
|
||||||
|
|
|
@ -33,14 +33,14 @@ typedef struct Packet {
|
||||||
|
|
||||||
typedef struct CommandPacket {
|
typedef struct CommandPacket {
|
||||||
struct CommandPacket *next;
|
struct CommandPacket *next;
|
||||||
byte player;
|
byte player; /// player that is executing the command (PlayerID)
|
||||||
uint32 cmd;
|
uint32 cmd; /// command being executed
|
||||||
uint32 p1;
|
uint32 p1; /// parameter p1
|
||||||
uint32 p2;
|
uint32 p2; /// parameter p2
|
||||||
uint32 tile; // Always make it uint32, so it is bigmap compatible
|
uint32 tile; /// tile command being executed on ; always make it uint32, so it is bigmap compatible (TileIndex)
|
||||||
uint32 dp[20]; // decode_params
|
uint32 dp[20]; /// _decode_parameters (for sending strings, etc.)
|
||||||
uint32 frame; // In which frame must this packet be executed?
|
uint32 frame; /// the frame in which this packet is executed
|
||||||
byte callback;
|
byte callback; /// any callback function executed upon successful completion of the command
|
||||||
} CommandPacket;
|
} CommandPacket;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
106
network_server.c
106
network_server.c
|
@ -775,14 +775,40 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const char* GetPlayerIP(const NetworkClientInfo *ci) {return inet_ntoa(*(struct in_addr *)&ci->client_ip);}
|
||||||
|
|
||||||
|
/** Enforce the command flags.
|
||||||
|
* Eg a server-only command can only be executed by a server, etc.
|
||||||
|
* @param *cp the commandpacket that is going to be checked
|
||||||
|
* @param *ci client information for debugging output to console
|
||||||
|
*/
|
||||||
|
static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
|
||||||
|
{
|
||||||
|
byte flags = GetCommandFlags(cp->cmd);
|
||||||
|
|
||||||
|
if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
|
||||||
|
IConsolePrintF(_iconsole_color_error, "WARNING: server only command from player %d (IP: %s), kicking...", ci->client_playas, GetPlayerIP(ci));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CMD_OFFLINE) {
|
||||||
|
IConsolePrintF(_iconsole_color_error, "WARNING: offline only command from player %d (IP: %s), kicking...", ci->client_playas, GetPlayerIP(ci));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The client has done a command and wants us to handle it
|
||||||
|
* @param *cs the connected client that has sent the command
|
||||||
|
* @param *p the packet in which the command was sent
|
||||||
|
*/
|
||||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
||||||
{
|
{
|
||||||
// The client has done a command and wants us to handle it
|
NetworkClientState *new_cs;
|
||||||
|
const NetworkClientInfo *ci;
|
||||||
|
char *dparam_char;
|
||||||
uint i;
|
uint i;
|
||||||
byte callback;
|
byte callback;
|
||||||
NetworkClientState *new_cs;
|
|
||||||
NetworkClientInfo *ci;
|
|
||||||
char *dparam_char;
|
|
||||||
|
|
||||||
CommandPacket *cp = malloc(sizeof(CommandPacket));
|
CommandPacket *cp = malloc(sizeof(CommandPacket));
|
||||||
|
|
||||||
|
@ -798,9 +824,10 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
||||||
cp->p1 = NetworkRecv_uint32(cs, p);
|
cp->p1 = NetworkRecv_uint32(cs, p);
|
||||||
cp->p2 = NetworkRecv_uint32(cs, p);
|
cp->p2 = NetworkRecv_uint32(cs, p);
|
||||||
cp->tile = NetworkRecv_uint32(cs, p);
|
cp->tile = NetworkRecv_uint32(cs, p);
|
||||||
/* We are going to send them byte by byte, because dparam is misused
|
/** @todo We are going to send dparams byte by byte, because dparam is misused
|
||||||
for chars (if it is used), and else we have a BigEndian / LittleEndian
|
* for charstrings (if it is used), and else we have a Big/Little Endian
|
||||||
problem.. we should fix the misuse of dparam... -- TrueLight */
|
* problem.. we should fix the misuse of dparam... -- TrueLight
|
||||||
|
*/
|
||||||
dparam_char = (char *)&cp->dp[0];
|
dparam_char = (char *)&cp->dp[0];
|
||||||
for (i = 0; i < lengthof(cp->dp) * 4; i++) {
|
for (i = 0; i < lengthof(cp->dp) * 4; i++) {
|
||||||
*dparam_char = NetworkRecv_uint8(cs, p);
|
*dparam_char = NetworkRecv_uint8(cs, p);
|
||||||
|
@ -809,51 +836,48 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
||||||
|
|
||||||
callback = NetworkRecv_uint8(cs, p);
|
callback = NetworkRecv_uint8(cs, p);
|
||||||
|
|
||||||
if (cs->quited)
|
if (cs->quited) return;
|
||||||
return;
|
|
||||||
|
ci = DEREF_CLIENT_INFO(cs);
|
||||||
|
|
||||||
/* Check if cp->cmd is valid */
|
/* Check if cp->cmd is valid */
|
||||||
if (!IsValidCommand(cp->cmd)) {
|
if (!IsValidCommand(cp->cmd)) {
|
||||||
|
IConsolePrintF(_iconsole_color_error, "WARNING: invalid command from player %d (IP: %s).", ci->client_playas, GetPlayerIP(ci));
|
||||||
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
|
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ci = DEREF_CLIENT_INFO(cs);
|
if (!CheckCommandFlags(cp, ci)) {
|
||||||
// Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs
|
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
|
||||||
// to match the player in the packet
|
return;
|
||||||
if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas-1 != cp->player) {
|
}
|
||||||
|
|
||||||
|
/** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs
|
||||||
|
* to match the player in the packet. If it doesn't, the client has done
|
||||||
|
* something pretty naughty (or a bug), and will be kicked
|
||||||
|
*/
|
||||||
|
if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas - 1 != cp->player) {
|
||||||
IConsolePrintF(_iconsole_color_error, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
|
IConsolePrintF(_iconsole_color_error, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
|
||||||
ci->client_playas - 1, inet_ntoa(*(struct in_addr *)&ci->client_ip), cp->player);
|
ci->client_playas, GetPlayerIP(ci), cp->player);
|
||||||
// The player did a command with the wrong player_id.. bad!!
|
|
||||||
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
|
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (cp->cmd) {
|
|
||||||
/* Player_ctrl is not always allowed */
|
|
||||||
case CMD_PLAYER_CTRL:
|
|
||||||
{
|
|
||||||
/* cp->p1 == 0, is allowed */
|
|
||||||
if (cp->p1 == 0) {
|
|
||||||
// UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
|
|
||||||
cp->p2 = cs - _clients;
|
|
||||||
} else {
|
|
||||||
/* The rest are cheats */
|
|
||||||
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
/* Don't allow those commands if server == advertising (considered cheating) */
|
/** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the
|
||||||
case CMD_MONEY_CHEAT:
|
* player the correct ID, the server injects p2 and executes the command. Any other p1
|
||||||
{
|
* is prohibited. Pretty ugly and should be redone together with its function.
|
||||||
if (_network_advertise) {
|
* @see CmdPlayerCtrl() players.c:655
|
||||||
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
|
*/
|
||||||
return;
|
if (cp->cmd == CMD_PLAYER_CTRL) {
|
||||||
}
|
if (cp->p1 != 0) {
|
||||||
} break;
|
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
|
||||||
|
cp->p2 = cs - _clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The frame can be executed in the same frame as the next frame-packet
|
// The frame can be executed in the same frame as the next frame-packet
|
||||||
// That frame just before that frame is saved in _frame_counter_max
|
// That frame just before that frame is saved in _frame_counter_max
|
||||||
cp->frame = _frame_counter_max + 1;
|
cp->frame = _frame_counter_max + 1;
|
||||||
|
@ -865,11 +889,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
||||||
if (new_cs->status > STATUS_AUTH) {
|
if (new_cs->status > STATUS_AUTH) {
|
||||||
// Callbacks are only send back to the client who sent them in the
|
// Callbacks are only send back to the client who sent them in the
|
||||||
// first place. This filters that out.
|
// first place. This filters that out.
|
||||||
if (new_cs != cs)
|
cp->callback = (new_cs != cs) ? 0 : callback;
|
||||||
cp->callback = 0;
|
|
||||||
else
|
|
||||||
cp->callback = callback;
|
|
||||||
|
|
||||||
NetworkAddCommandQueue(new_cs, cp);
|
NetworkAddCommandQueue(new_cs, cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,6 +420,9 @@ static inline Vehicle *GetFirstVehicleFromSharedList(Vehicle *v)
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate functions for rail building */
|
||||||
|
static inline bool ValParamRailtype(uint32 rail) { return rail <= GetPlayer(_current_player)->max_railtype;}
|
||||||
|
|
||||||
// NOSAVE: Can be regenerated by inspecting the vehicles.
|
// NOSAVE: Can be regenerated by inspecting the vehicles.
|
||||||
VARDEF VehicleID _vehicle_position_hash[0x1000];
|
VARDEF VehicleID _vehicle_position_hash[0x1000];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue