diff options
author | truelight <truelight@openttd.org> | 2005-01-05 14:39:48 +0000 |
---|---|---|
committer | truelight <truelight@openttd.org> | 2005-01-05 14:39:48 +0000 |
commit | 523a6a1cffd1a7567453835500f387f3499b10a2 (patch) | |
tree | 0321af6b507ef39cda02042c21cc3ae5e417a162 /network_server.c | |
parent | f1e9fdf76d951dec71c330f12783917cae464160 (diff) | |
download | openttd-523a6a1cffd1a7567453835500f387f3499b10a2.tar.xz |
(svn r1389) -Add: [Network] Added packet protection. No longer a client or server
reads beyond the size of the packet
-Fix: [Network] A server no longer crashes when a client sends an
invalid DoCommand, but drops the client instead.
Diffstat (limited to 'network_server.c')
-rw-r--r-- | network_server.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/network_server.c b/network_server.c index a294ea518..edd2aab6b 100644 --- a/network_server.c +++ b/network_server.c @@ -580,7 +580,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN) char client_revision[NETWORK_REVISION_LENGTH]; - NetworkRecv_string(p, client_revision, sizeof(client_revision)); + NetworkRecv_string(cs, p, client_revision, sizeof(client_revision)); #if defined(WITH_REV) || defined(WITH_REV_HACK) // Check if the client has revision control enabled @@ -594,10 +594,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN) } #endif - NetworkRecv_string(p, name, sizeof(name)); - playas = NetworkRecv_uint8(p); - client_lang = NetworkRecv_uint8(p); - NetworkRecv_string(p, unique_id, sizeof(unique_id)); + NetworkRecv_string(cs, p, name, sizeof(name)); + playas = NetworkRecv_uint8(cs, p); + client_lang = NetworkRecv_uint8(cs, p); + NetworkRecv_string(cs, p, unique_id, sizeof(unique_id)); + + if (cs->quited) + return; // Check if someone else already has that name snprintf(test_name, sizeof(test_name), "%s", name); @@ -644,8 +647,8 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD) char password[NETWORK_PASSWORD_LENGTH]; NetworkClientInfo *ci; - type = NetworkRecv_uint8(p); - NetworkRecv_string(p, password, sizeof(password)); + type = NetworkRecv_uint8(cs, p); + NetworkRecv_string(cs, p, password, sizeof(password)); if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) { // Check game-password @@ -761,21 +764,30 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) return; } - cp->player = NetworkRecv_uint8(p); - cp->cmd = NetworkRecv_uint32(p); - cp->p1 = NetworkRecv_uint32(p); - cp->p2 = NetworkRecv_uint32(p); - cp->tile = NetworkRecv_uint32(p); + cp->player = NetworkRecv_uint8(cs, p); + cp->cmd = NetworkRecv_uint32(cs, p); + cp->p1 = NetworkRecv_uint32(cs, p); + cp->p2 = NetworkRecv_uint32(cs, p); + cp->tile = NetworkRecv_uint32(cs, p); /* We are going to send them byte by byte, because dparam is misused for chars (if it is used), and else we have a BigEndian / LittleEndian problem.. we should fix the misuse of dparam... -- TrueLight */ dparam_char = (char *)&cp->dp[0]; for (i = 0; i < lengthof(cp->dp) * 4; i++) { - *dparam_char = NetworkRecv_uint8(p); + *dparam_char = NetworkRecv_uint8(cs, p); dparam_char++; } - callback = NetworkRecv_uint8(p); + callback = NetworkRecv_uint8(cs, p); + + if (cs->quited) + return; + + /* Check if cp->cmd is valid */ + if (!IsValidCommand(cp->cmd)) { + SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return; + } ci = DEREF_CLIENT_INFO(cs); // Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs @@ -814,7 +826,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) // 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 cp->frame = _frame_counter_max + 1; - cp->next = NULL; + cp->next = NULL; // Queue the command for the clients (are send at the end of the frame // if they can handle it ;)) @@ -826,6 +838,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) cp->callback = 0; else cp->callback = callback; + NetworkAddCommandQueue(new_cs, cp); } } @@ -847,7 +860,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR) // This packets means a client noticed an error and is reporting this // to us. Display the error and report it to the other clients NetworkClientState *new_cs; - byte errorno = NetworkRecv_uint8(p); + byte errorno = NetworkRecv_uint8(cs, p); char str[100]; char client_name[NETWORK_CLIENT_NAME_LENGTH]; @@ -888,7 +901,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT) return; } - NetworkRecv_string(p, str, 100); + NetworkRecv_string(cs, p, str, 100); NetworkGetClientName(client_name, sizeof(client_name), cs); @@ -906,7 +919,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK) { // The client received the frame, make note of it - cs->last_frame = NetworkRecv_uint32(p); + cs->last_frame = NetworkRecv_uint32(cs, p); // With those 2 values we can calculate the lag realtime cs->last_frame_server = _frame_counter; @@ -1018,12 +1031,12 @@ void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT) { - NetworkAction action = NetworkRecv_uint8(p); - DestType desttype = NetworkRecv_uint8(p); - int dest = NetworkRecv_uint8(p); + NetworkAction action = NetworkRecv_uint8(cs, p); + DestType desttype = NetworkRecv_uint8(cs, p); + int dest = NetworkRecv_uint8(cs, p); char msg[MAX_TEXT_MSG_LEN]; - NetworkRecv_string(p, msg, MAX_TEXT_MSG_LEN); + NetworkRecv_string(cs, p, msg, MAX_TEXT_MSG_LEN); NetworkServer_HandleChat(action, desttype, dest, msg, cs->index); } @@ -1033,7 +1046,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD) char password[NETWORK_PASSWORD_LENGTH]; NetworkClientInfo *ci; - NetworkRecv_string(p, password, sizeof(password)); + NetworkRecv_string(cs, p, password, sizeof(password)); ci = DEREF_CLIENT_INFO(cs); if (ci->client_playas <= MAX_PLAYERS) { @@ -1046,9 +1059,12 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME) char client_name[NETWORK_CLIENT_NAME_LENGTH]; NetworkClientInfo *ci; - NetworkRecv_string(p, client_name, sizeof(client_name)); + NetworkRecv_string(cs, p, client_name, sizeof(client_name)); ci = DEREF_CLIENT_INFO(cs); + if (cs->quited) + return; + if (ci != NULL) { // Display change if (NetworkFindName(client_name)) { @@ -1388,8 +1404,8 @@ bool NetworkServer_ReadPackets(NetworkClientState *cs) Packet *p; NetworkRecvStatus res; while((p = NetworkRecv_Packet(cs, &res)) != NULL) { - byte type = NetworkRecv_uint8(p); - if (type < PACKET_END && _network_server_packet[type] != NULL) + byte type = NetworkRecv_uint8(cs, p); + if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->quited) _network_server_packet[type](cs, p); else DEBUG(net, 0)("[NET][Server] Received invalid packet type %d", type); |