/// <summary> /// Received network packet (contains entity name, message, /// </summary> /// <returns>The entity.</returns> /// <param name="packet">Packet.</param> public ValidationError ValidateEntity(ClientMessage packet, byte[] hmac, byte[] packetRaw, bool ignoreConnected = false) { string ts = Helpers.GetTimestamp(DateTime.Now); if (ts != packet.Timestamp) { return(ValidationError.InvalidTime); } byte[] key = GenKey(seed1, selector); byte[] iv = GenIV(seed2, selector); if (entities == null) { return(ValidationError.NotFound); } bool dbValidation = ValidateDecryption(entities, key, iv); if (!dbValidation) { return(ValidationError.NotFound); } if (ignoreConnected) { if (Program.server.clientHandlers.Contains(packet.Entity)) { return(ValidationError.AlreadyConnected); } } byte[] decripted = DecryptData(entities, key, iv); List <EntityClass> _entities = Helpers.FromByteArray <List <EntityClass> >(decripted); decripted = null; if (_entities.Any(m => m.EntityName == packet.Entity)) { EntityClass storedEntity = _entities.First(m => m.EntityName == packet.Entity); byte[] calcHMAC = SHA256hmac.ComputeHMAC(packetRaw, storedEntity.Key); return(!SHA256hmac.CompareHMAC(hmac, calcHMAC) ? ValidationError.InvalidKey : ValidationError.NoError); } _entities = null; return(ValidationError.NotFound); }
/// <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); } }