/// <summary> /// ClientConnected handler, handles the first connection of a client. /// </summary> /// <param name="m">Packet without the packet length</param> /// <param name="socket">Socket.</param> /// <param name="e">E.</param> static void Server_ClientConnected(byte[] m, TcpClient socket, EventArgs e) { IPAddress ip = ((IPEndPoint)socket.Client.RemoteEndPoint).Address; IPAddress local = ((IPEndPoint)socket.Client.LocalEndPoint).Address; PacketType packetType = Server.DecodePacketType(m); Server.DeconstructPacket(m, out byte[] hmac, out ClientMessage message, out byte[] raw); if (enableDebug) { ReplaceWith(""); } ProcessDebugMessage(string.Format("New entity is trying to connect: {0} ({1})", message.Entity, ip)); Database.ValidationError validation = database.ValidateEntity(message, hmac, raw); switch (validation) { case Database.ValidationError.NotFound: server.DennyClient(message.Entity, ServerMessages.EntityNotFound, socket, DEFAULT_KEY.FromHexToByteArray()); ProcessDebugMessage(string.Format("Connection from entity {0} ({1}) refused! Entity not found!", message.Entity, ip)); break; case Database.ValidationError.InvalidKey: server.DennyClient(message.Entity, ServerMessages.InvalidKey, socket, DEFAULT_KEY.FromHexToByteArray()); ProcessDebugMessage(string.Format("Connection from entity {0} ({1}) refused! Invalid key or message tempered!", message.Entity, ip)); break; case Database.ValidationError.AlreadyConnected: server.DennyClient(message.Entity, ServerMessages.EntityAlreadyConnected, socket, DEFAULT_KEY.FromHexToByteArray()); ProcessDebugMessage(string.Format("Connection from entity {0} ({1}) refused! Entity already connected!", message.Entity, ip)); break; case Database.ValidationError.NoError: ProcessDebugMessage(string.Format("Connection from entity {0} ({1}) accepted!", message.Entity, ip)); server.AcceptClient(message.Entity, socket, database.RetreiveEntityKey(message.Entity), enableSpy, local.ToString()); break; case Database.ValidationError.InvalidTime: ProcessDebugMessage(string.Format("Connection from entity {0} ({1}) refused! Invalid time matching!", message.Entity, ip)); break; } if (enableDebug) { Console.WriteLine(""); Console.Write("\r" + menuManager.commandPrefix); } }
/// <summary> /// Handles all messages received by the client (except the first one) /// </summary> /// <param name="m">Packet without the byte length</param> /// <param name="clientHandler">Client handler.</param> static void Server_MessageReceived(byte[] m, ClientHandler clientHandler) { IPAddress ip = ((IPEndPoint)clientHandler.Socket.Client.RemoteEndPoint).Address; PacketType packetType = Server.DecodePacketType(m); Server.DeconstructPacket(m, out byte[] hmac, out ClientMessage message, out byte[] raw); if (enableDebug) { ReplaceWith(""); } ProcessDebugMessage(string.Format("Message received from {0} ({1})", message.Entity, ip)); // This step allows the verification of: // 1. if the entity is still accepted by the server // 2. if the hmac is corect Database.ValidationError validation = database.ValidateEntity(message, hmac, raw); switch (validation) { case Database.ValidationError.NoError: if (ClientOperations.RequestConnectedEntities.Value == message.Operation) { RequestedEntitiesList(clientHandler); } else if (ClientOperations.Disconnect.Value == message.Operation) { server.UserDisconnected(clientHandler.Entity); } else if (ClientOperations.RequestKeyNegotiation.Value == message.Operation) { NegotiateKey(message, clientHandler); } else { ServerCommand sv_cmd_invalid_operation = new ServerCommand { Command = ServerOperations.InvalidComand.Value }; server.SendMessage(sv_cmd_invalid_operation, PacketType.ServerCommand, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); } break; case Database.ValidationError.InvalidKey: ProcessDebugMessage(string.Format("HMAC for message from {0} ({1}) failed!", message.Entity, ip)); ServerCommand sv_cmd_invalid_hmac = new ServerCommand { Command = ServerOperations.InvalidHMAC.Value, Message = string.Format("RECEIVED_HMAC={0}|COMPUTED_HMAC={1}", hmac.FromByteArrayToHex(), SHA256hmac.ComputeHMAC(raw, database.RetreiveEntityKey(clientHandler.Entity)).FromByteArrayToHex()) }; server.SendMessage(sv_cmd_invalid_hmac, PacketType.ServerCommand, DEFAULT_KEY.FromHexToByteArray(), clientHandler.Socket); break; case Database.ValidationError.NotFound: ProcessDebugMessage(string.Format("Entity {0} at {1} not found!", message.Entity, ip)); ServerCommand sv_cmd_entity_not_found = new ServerCommand { Command = ServerOperations.EntityNoLongerAvailable.Value }; server.SendMessage(sv_cmd_entity_not_found, PacketType.ServerCommand, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); break; case Database.ValidationError.InvalidTime: ProcessDebugMessage("Packet time missmatch"); ServerCommand sv_cmd_ts_missmatch = new ServerCommand { Command = ServerOperations.InvalidTime.Value }; server.SendMessage(sv_cmd_ts_missmatch, PacketType.ClientMessage, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); break; } if (enableDebug) { Console.WriteLine(""); Console.Write("\r" + menuManager.commandPrefix); } }