From 8c875c42786408b5f2d127be1dd239f4ea7214e3 Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Tue, 23 Jul 2019 15:57:08 +0300 Subject: [PATCH] Changed Interfaces to provide handlers with reference to server directly through method calls --- MTSC-TestClient/Program.cs | 6 +- MTSC-TestServer/Program.cs | 6 +- MTSC/Client/Client.cs | 10 +- MTSC/Client/Handlers/BroadcastHandler.cs | 27 ++- MTSC/Client/Handlers/EncryptionHandler.cs | 272 +++++++++++----------- MTSC/Client/Handlers/HttpHandler.cs | 21 +- MTSC/Client/Handlers/IHandler.cs | 13 +- MTSC/Server/Handlers/BroadcastHandler.cs | 26 +-- MTSC/Server/Handlers/EncryptionHandler.cs | 211 ++++++++--------- MTSC/Server/Handlers/HttpHandler.cs | 21 +- MTSC/Server/Handlers/IHandler.cs | 18 +- MTSC/Server/Server.cs | 10 +- 12 files changed, 322 insertions(+), 319 deletions(-) diff --git a/MTSC-TestClient/Program.cs b/MTSC-TestClient/Program.cs index 2fd4eb8..1eef162 100644 --- a/MTSC-TestClient/Program.cs +++ b/MTSC-TestClient/Program.cs @@ -10,11 +10,11 @@ namespace MTSC_TestClient static void Main(string[] args) { Client client = new Client(true); - BroadcastHandler broadcastHandler = new BroadcastHandler(client); + BroadcastHandler broadcastHandler = new BroadcastHandler(); client .SetServerAddress("127.0.0.1") .SetPort(555) - .AddHandler(new EncryptionHandler(client)) + .AddHandler(new EncryptionHandler()) .AddHandler(broadcastHandler) .AddLogger(new ConsoleLogger()) .AddLogger(new DebugConsoleLogger()) @@ -22,7 +22,7 @@ namespace MTSC_TestClient while (true) { string line = Console.ReadLine(); - broadcastHandler.Broadcast(line); + broadcastHandler.Broadcast(client, line); } } } diff --git a/MTSC-TestServer/Program.cs b/MTSC-TestServer/Program.cs index e473888..51ace0a 100644 --- a/MTSC-TestServer/Program.cs +++ b/MTSC-TestServer/Program.cs @@ -16,14 +16,14 @@ namespace MTSC_TestServer X509Certificate2 certificate = new X509Certificate2("localhost.pfx", "psdsd"); Server server = new Server(555); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024); - EncryptionHandler encryptionHandler = new EncryptionHandler(rsa, server); + EncryptionHandler encryptionHandler = new EncryptionHandler(rsa); server //.AddHandler(encryptionHandler) .AddLogger(new ConsoleLogger()) .AddLogger(new DebugConsoleLogger()) .AddExceptionHandler(new ExceptionConsoleLogger()) - .AddHandler(new BroadcastHandler(server)) - .AddHandler(new HttpHandler(server)) + .AddHandler(new BroadcastHandler()) + .AddHandler(new HttpHandler()) .Run(); } diff --git a/MTSC/Client/Client.cs b/MTSC/Client/Client.cs index 0a50716..ab3d08e 100644 --- a/MTSC/Client/Client.cs +++ b/MTSC/Client/Client.cs @@ -166,7 +166,7 @@ namespace MTSC.Client } foreach (IHandler handler in handlers) { - if (!handler.InitializeConnection(tcpClient)) + if (!handler.InitializeConnection(this)) { return false; } @@ -232,7 +232,7 @@ namespace MTSC.Client for(int i = handlers.Count - 1; i >= 0; i--) { IHandler handler = handlers[i]; - handler.HandleSendMessage(tcpClient, ref sendMessage); + handler.HandleSendMessage(this, ref sendMessage); } CommunicationPrimitives.SendMessage(tcpClient, sendMessage, sslStream); } @@ -248,7 +248,7 @@ namespace MTSC.Client */ foreach (IHandler handler in handlers) { - if (handler.PreHandleReceivedMessage(tcpClient, ref message)) + if (handler.PreHandleReceivedMessage(this, ref message)) { break; } @@ -258,7 +258,7 @@ namespace MTSC.Client */ foreach (IHandler handler in handlers) { - if (handler.HandleReceivedMessage(tcpClient, message)) + if (handler.HandleReceivedMessage(this, message)) { break; } @@ -266,7 +266,7 @@ namespace MTSC.Client } foreach (IHandler handler in handlers) { - handler.Tick(tcpClient); + handler.Tick(this); } } catch(Exception e) diff --git a/MTSC/Client/Handlers/BroadcastHandler.cs b/MTSC/Client/Handlers/BroadcastHandler.cs index f1cd7e0..fe88a61 100644 --- a/MTSC/Client/Handlers/BroadcastHandler.cs +++ b/MTSC/Client/Handlers/BroadcastHandler.cs @@ -8,53 +8,52 @@ namespace MTSC.Client.Handlers public class BroadcastHandler : IHandler { private List buffer = new List(); - private Client managedClient; /// /// Creates a new instance of BroadcastHandler. /// - /// Client managed by the handler. - public BroadcastHandler(Client client) + public BroadcastHandler() { - this.managedClient = client; + } /// /// Broadcast a message to all other clients connected to the server. /// /// Message to be broadcasted. - public void Broadcast(string message) + /// Client object containing the communication channel. + public void Broadcast(Client client, string message) { - managedClient.QueueMessage(UnicodeEncoding.Unicode.GetBytes(message)); + client.QueueMessage(UnicodeEncoding.Unicode.GetBytes(message)); } - public void Disconnected(TcpClient client) + void IHandler.Disconnected(Client client) { } - public bool HandleReceivedMessage(TcpClient client, Message message) + bool IHandler.HandleReceivedMessage(Client client, Message message) { - managedClient.LogDebug("Broadcast: " + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); - managedClient.Log(">" + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); + client.LogDebug("Broadcast: " + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); + client.Log(">" + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); return false; } - public bool HandleSendMessage(TcpClient client, ref Message message) + bool IHandler.HandleSendMessage(Client client, ref Message message) { return false; } - public bool InitializeConnection(TcpClient client) + bool IHandler.InitializeConnection(Client client) { return true; } - public bool PreHandleReceivedMessage(TcpClient client, ref Message message) + bool IHandler.PreHandleReceivedMessage(Client client, ref Message message) { return false; } - public void Tick(TcpClient tcpClient) + void IHandler.Tick(Client client) { } diff --git a/MTSC/Client/Handlers/EncryptionHandler.cs b/MTSC/Client/Handlers/EncryptionHandler.cs index 59daf04..9e7ba6c 100644 --- a/MTSC/Client/Handlers/EncryptionHandler.cs +++ b/MTSC/Client/Handlers/EncryptionHandler.cs @@ -17,7 +17,6 @@ namespace MTSC.Client.Handlers NegotiatingSymKey, Encrypted } - private Client managedClient; #region Fields private ConnectionState connectionState = ConnectionState.Initial; private byte[] aesKey; @@ -27,144 +26,13 @@ namespace MTSC.Client.Handlers /// Creates an instance of EncryptionHandler. /// /// Client object that this handler manages. - public EncryptionHandler(Client client) - { - this.managedClient = client; - } - #endregion - #region Public Methods - /// - /// Tries to initialize an encrypted connection. - /// - /// TcpClient connection. - /// True if connection is successful. False otherwise. - public bool InitializeConnection(TcpClient client) - { - this.connectionState = ConnectionState.Initial; - return true; - } - /// - /// Handles the operations done after client disconnected. - /// - /// - public void Disconnected(TcpClient client) + public EncryptionHandler() { } - /// - /// Performs operations on the message before sending it. - /// - /// Client connection. - /// Message to be processed. - /// True if no other handler should process the message further. - public bool HandleSendMessage(TcpClient client, ref Message message) - { - if(connectionState == ConnectionState.Encrypted) - { - byte[] decryptedBytes = message.MessageBytes; - byte[] encryptedBytes = EncryptBytes(decryptedBytes); - message = CommunicationPrimitives.BuildMessage(encryptedBytes); - return true; - } - return false; - } - /// - /// Performs operations on the message buffer, modifying it. - /// - /// Client connection. - /// Message to be processed. - /// True if no other handler should process it further. - public bool PreHandleReceivedMessage(TcpClient client, ref Message message) - { - if(connectionState == ConnectionState.Encrypted) - { - byte[] encryptedBytes = message.MessageBytes; - byte[] decryptedBytes = DecryptBytes(encryptedBytes); - message = CommunicationPrimitives.BuildMessage(decryptedBytes); - return false; - } - return false; - } - /// - /// Handle the received message. - /// - /// Client connection. - /// Message. - /// True if no other handler should handle the message further. - public bool HandleReceivedMessage(TcpClient client, Message message) - { - if(connectionState == ConnectionState.RequestingPublicKey) - { - string ascii = ASCIIEncoding.ASCII.GetString(message.MessageBytes); - if (ascii.Contains(CommunicationPrimitives.SendPublicKey)) - { - byte[] publicKeyBytes = new byte[message.MessageLength - CommunicationPrimitives.SendPublicKey.Length - 1]; - Array.Copy(message.MessageBytes, CommunicationPrimitives.SendPublicKey.Length + 1, publicKeyBytes, 0, publicKeyBytes.Length); - string publicKey = ASCIIEncoding.ASCII.GetString(publicKeyBytes); - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024); - RSAParameters parameters = new RSAParameters(); - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(publicKey); - if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) - { - foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) - { - switch (node.Name) - { - case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - } - } - } - rsa.ImportParameters(parameters); - byte[] symkeyBytes = GetUniqueByteKey(32); - byte[] encryptedSymKey = rsa.Encrypt(symkeyBytes, false); - aesKey = symkeyBytes; - byte[] messageHeader = ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendEncryptionKey + ":"); - byte[] messageBytes = new byte[encryptedSymKey.Length + messageHeader.Length]; - Array.Copy(messageHeader, 0, messageBytes, 0, messageHeader.Length); - Array.Copy(encryptedSymKey, 0, messageBytes, messageHeader.Length, encryptedSymKey.Length); - managedClient.QueueMessage(messageBytes); - connectionState = ConnectionState.NegotiatingSymKey; - return true; - } - } - else if(connectionState == ConnectionState.NegotiatingSymKey) - { - string ascii = ASCIIEncoding.ASCII.GetString(DecryptBytes(message.MessageBytes)); - if(ascii == CommunicationPrimitives.AcceptEncryptionKey) - { - connectionState = ConnectionState.Encrypted; - return true; - } - else - { - connectionState = ConnectionState.Initial; - return false; - } - } - return false; - } - /// - /// Called on every tick by the client object. - /// Performs regular operations. - /// - /// Client connection. - public void Tick(TcpClient tcpClient) - { - if(connectionState == ConnectionState.Initial) - { + #endregion + #region Public Methods - managedClient.QueueMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.RequestPublicKey)); - this.connectionState = ConnectionState.RequestingPublicKey; - } - } #endregion #region Private Methods private string GetUniqueKey(int size) @@ -272,5 +140,139 @@ namespace MTSC.Client.Handlers return result; } #endregion + #region Interface Implementation + /// + /// Tries to initialize an encrypted connection. + /// + /// TcpClient connection. + /// True if connection is successful. False otherwise. + bool IHandler.InitializeConnection(Client client) + { + this.connectionState = ConnectionState.Initial; + return true; + } + /// + /// Handles the operations done after client disconnected. + /// + /// + void IHandler.Disconnected(Client client) + { + + } + /// + /// Performs operations on the message before sending it. + /// + /// Client connection. + /// Message to be processed. + /// True if no other handler should process the message further. + bool IHandler.HandleSendMessage(Client client, ref Message message) + { + if (connectionState == ConnectionState.Encrypted) + { + byte[] decryptedBytes = message.MessageBytes; + byte[] encryptedBytes = EncryptBytes(decryptedBytes); + message = CommunicationPrimitives.BuildMessage(encryptedBytes); + return true; + } + return false; + } + /// + /// Performs operations on the message buffer, modifying it. + /// + /// Client connection. + /// Message to be processed. + /// True if no other handler should process it further. + bool IHandler.PreHandleReceivedMessage(Client client, ref Message message) + { + if (connectionState == ConnectionState.Encrypted) + { + byte[] encryptedBytes = message.MessageBytes; + byte[] decryptedBytes = DecryptBytes(encryptedBytes); + message = CommunicationPrimitives.BuildMessage(decryptedBytes); + return false; + } + return false; + } + /// + /// Handle the received message. + /// + /// Client connection. + /// Message. + /// True if no other handler should handle the message further. + bool IHandler.HandleReceivedMessage(Client client, Message message) + { + if (connectionState == ConnectionState.RequestingPublicKey) + { + string ascii = ASCIIEncoding.ASCII.GetString(message.MessageBytes); + if (ascii.Contains(CommunicationPrimitives.SendPublicKey)) + { + byte[] publicKeyBytes = new byte[message.MessageLength - CommunicationPrimitives.SendPublicKey.Length - 1]; + Array.Copy(message.MessageBytes, CommunicationPrimitives.SendPublicKey.Length + 1, publicKeyBytes, 0, publicKeyBytes.Length); + string publicKey = ASCIIEncoding.ASCII.GetString(publicKeyBytes); + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024); + RSAParameters parameters = new RSAParameters(); + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(publicKey); + if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) + { + foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) + { + switch (node.Name) + { + case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + } + } + } + rsa.ImportParameters(parameters); + byte[] symkeyBytes = GetUniqueByteKey(32); + byte[] encryptedSymKey = rsa.Encrypt(symkeyBytes, false); + aesKey = symkeyBytes; + byte[] messageHeader = ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendEncryptionKey + ":"); + byte[] messageBytes = new byte[encryptedSymKey.Length + messageHeader.Length]; + Array.Copy(messageHeader, 0, messageBytes, 0, messageHeader.Length); + Array.Copy(encryptedSymKey, 0, messageBytes, messageHeader.Length, encryptedSymKey.Length); + client.QueueMessage(messageBytes); + connectionState = ConnectionState.NegotiatingSymKey; + return true; + } + } + else if (connectionState == ConnectionState.NegotiatingSymKey) + { + string ascii = ASCIIEncoding.ASCII.GetString(DecryptBytes(message.MessageBytes)); + if (ascii == CommunicationPrimitives.AcceptEncryptionKey) + { + connectionState = ConnectionState.Encrypted; + return true; + } + else + { + connectionState = ConnectionState.Initial; + return false; + } + } + return false; + } + /// + /// Called on every tick by the client object. + /// Performs regular operations. + /// + /// Client connection. + void IHandler.Tick(Client client) + { + if (connectionState == ConnectionState.Initial) + { + + client.QueueMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.RequestPublicKey)); + this.connectionState = ConnectionState.RequestingPublicKey; + } + } + #endregion } } diff --git a/MTSC/Client/Handlers/HttpHandler.cs b/MTSC/Client/Handlers/HttpHandler.cs index 8da3f34..7ac2dd7 100644 --- a/MTSC/Client/Handlers/HttpHandler.cs +++ b/MTSC/Client/Handlers/HttpHandler.cs @@ -13,13 +13,12 @@ namespace MTSC.Client.Handlers public class HttpHandler : IHandler { #region Fields - Client managedClient; List httpModules = new List(); #endregion #region Constructors - public HttpHandler(Client client) + public HttpHandler() { - managedClient = client; + } #endregion #region Public Methods @@ -27,9 +26,9 @@ namespace MTSC.Client.Handlers /// Send a request to the server. /// /// Request to be sent. - public void SendRequest(HttpMessage request) + public void SendRequest(Client client, HttpMessage request) { - managedClient.QueueMessage(request.GetRequest()); + client.QueueMessage(request.GetRequest()); } /// /// Add a http module. @@ -47,7 +46,7 @@ namespace MTSC.Client.Handlers /// Handler implementation /// /// - void IHandler.Disconnected(TcpClient client) + void IHandler.Disconnected(Client client) { } @@ -57,7 +56,7 @@ namespace MTSC.Client.Handlers /// /// /// False. - bool IHandler.HandleReceivedMessage(TcpClient client, Message message) + bool IHandler.HandleReceivedMessage(Client client, Message message) { HttpMessage httpMessage = new HttpMessage(); httpMessage.ParseResponse(message.MessageBytes); @@ -76,7 +75,7 @@ namespace MTSC.Client.Handlers /// /// /// False. - bool IHandler.HandleSendMessage(TcpClient client, ref Message message) + bool IHandler.HandleSendMessage(Client client, ref Message message) { return false; } @@ -85,7 +84,7 @@ namespace MTSC.Client.Handlers /// /// /// True. - bool IHandler.InitializeConnection(TcpClient client) + bool IHandler.InitializeConnection(Client client) { return true; } @@ -95,7 +94,7 @@ namespace MTSC.Client.Handlers /// /// /// False. - bool IHandler.PreHandleReceivedMessage(TcpClient client, ref Message message) + bool IHandler.PreHandleReceivedMessage(Client client, ref Message message) { return false; } @@ -103,7 +102,7 @@ namespace MTSC.Client.Handlers /// Handler implementation. /// /// - void IHandler.Tick(TcpClient tcpClient) + void IHandler.Tick(Client tcpClient) { } diff --git a/MTSC/Client/Handlers/IHandler.cs b/MTSC/Client/Handlers/IHandler.cs index 91b7e7f..069a282 100644 --- a/MTSC/Client/Handlers/IHandler.cs +++ b/MTSC/Client/Handlers/IHandler.cs @@ -16,14 +16,14 @@ namespace MTSC.Client.Handlers /// Client object. /// True if the initialization is successful. /// If this method returns false, the connection will fail and return false. - bool InitializeConnection(TcpClient client); + bool InitializeConnection(Client client); /// /// Called when a message is being sent to the server. /// /// Client socket. /// Message to be sent. /// - bool HandleSendMessage(TcpClient client, ref Message message); + bool HandleSendMessage(Client client, ref Message message); /// /// Called before the message is handled. /// Use this method to modify the message if necesarry. @@ -31,24 +31,23 @@ namespace MTSC.Client.Handlers /// Client object. /// Message to be preprocessed. /// True if the message has been preprocessed and no other handler should modify the message. - bool PreHandleReceivedMessage(TcpClient client, ref Message message); + bool PreHandleReceivedMessage(Client client, ref Message message); /// /// Called when a message has been received. /// /// Client object. /// Message to be handled. /// True if the message has been handled and no other handler should process it. - bool HandleReceivedMessage(TcpClient client, Message message); + bool HandleReceivedMessage(Client client, Message message); /// /// Called every cycle. This method should perform regular actions on the connection. /// /// Client object. - /// TcpClient connection. - void Tick(TcpClient tcpClient); + void Tick(Client client); /// /// Called when the client is disconnected. /// /// Client object. - void Disconnected(TcpClient client); + void Disconnected(Client client); } } diff --git a/MTSC/Server/Handlers/BroadcastHandler.cs b/MTSC/Server/Handlers/BroadcastHandler.cs index fbf7991..7042d42 100644 --- a/MTSC/Server/Handlers/BroadcastHandler.cs +++ b/MTSC/Server/Handlers/BroadcastHandler.cs @@ -9,45 +9,43 @@ namespace MTSC.Server.Handlers /// public class BroadcastHandler : IHandler { - private Server managedServer; - - public BroadcastHandler(Server server) + public BroadcastHandler() { - this.managedServer = server; + } - public void ClientRemoved(ClientStruct client) + void IHandler.ClientRemoved(Server server, ClientStruct client) { } - public bool HandleClient(ClientStruct client) + bool IHandler.HandleClient(Server server, ClientStruct client) { return false; } - public bool HandleReceivedMessage(ClientStruct client, Message message) + bool IHandler.HandleReceivedMessage(Server server, ClientStruct client, Message message) { - managedServer.LogDebug("Broadcast: " + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); - managedServer.LogDebug("From: " + client.TcpClient.Client.RemoteEndPoint.ToString()); - foreach(ClientStruct clientStruct in managedServer.Clients) + server.LogDebug("Broadcast: " + UnicodeEncoding.Unicode.GetString(message.MessageBytes)); + server.LogDebug("From: " + client.TcpClient.Client.RemoteEndPoint.ToString()); + foreach(ClientStruct clientStruct in server.Clients) { - managedServer.QueueMessage(clientStruct, message.MessageBytes); + server.QueueMessage(clientStruct, message.MessageBytes); } return false; } - public bool HandleSendMessage(ClientStruct client, ref Message message) + bool IHandler.HandleSendMessage(Server server, ClientStruct client, ref Message message) { return false; } - public bool PreHandleReceivedMessage(ClientStruct client, ref Message message) + bool IHandler.PreHandleReceivedMessage(Server server, ClientStruct client, ref Message message) { return false; } - public void Tick() + void IHandler.Tick(Server server) { } diff --git a/MTSC/Server/Handlers/EncryptionHandler.cs b/MTSC/Server/Handlers/EncryptionHandler.cs index ac45f39..d240bc9 100644 --- a/MTSC/Server/Handlers/EncryptionHandler.cs +++ b/MTSC/Server/Handlers/EncryptionHandler.cs @@ -27,7 +27,6 @@ namespace MTSC.Server.Handlers private Dictionary additionalData; private RSACryptoServiceProvider rsa; private string privateKey, publicKey; - private Server managedServer; #endregion #region Properties #endregion @@ -37,9 +36,8 @@ namespace MTSC.Server.Handlers /// /// Symmetrical algorithm to be used for end-to-end encryption. /// Server object managed by the handler. - public EncryptionHandler(RSACryptoServiceProvider rsa, Server server) + public EncryptionHandler(RSACryptoServiceProvider rsa) { - managedServer = server; additionalData = new Dictionary(); this.rsa = rsa; privateKey = HelperFunctions.ToXmlString(rsa, true); @@ -47,108 +45,7 @@ namespace MTSC.Server.Handlers } #endregion #region Public Methods - /// - /// Called when a client is being removed. - /// - /// Client to be removed. - public void ClientRemoved(ClientStruct client) - { - additionalData.Remove(client); - } - /// - /// Handle a new client connection. - /// - /// New client connection. - /// False if an error occurred. - public bool HandleClient(ClientStruct client) - { - additionalData.Add(client, new AdditionalData()); - return false; - } - /// - /// Handle a received message. - /// - /// Client connection. - /// Received message. - /// True if no other handler should handle current message. - public bool HandleReceivedMessage(ClientStruct client, Message message) - { - if (additionalData[client].ClientState == ClientState.Initial || additionalData[client].ClientState == ClientState.Negotiating) - { - string asciiMessage = ASCIIEncoding.ASCII.GetString(message.MessageBytes); - if (asciiMessage == CommunicationPrimitives.RequestPublicKey) - { - managedServer.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendPublicKey + ":" + publicKey)); - additionalData[client].ClientState = ClientState.Negotiating; - return true; - } - else if (asciiMessage.Contains(CommunicationPrimitives.SendEncryptionKey)) - { - byte[] encryptedKey = new byte[message.MessageLength - CommunicationPrimitives.SendEncryptionKey.Length - 1]; - Array.Copy(message.MessageBytes, CommunicationPrimitives.SendEncryptionKey.Length + 1, encryptedKey, 0, encryptedKey.Length); - byte[] decryptedKey = rsa.Decrypt(encryptedKey, false); - additionalData[client].Key = decryptedKey; - managedServer.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.AcceptEncryptionKey)); - additionalData[client].ClientState = ClientState.Encrypted; - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - /// - /// Perform transformative operations on the message. - /// - /// Client connection. - /// Message to be processed. - /// True if no other handlers should perform operations on current message. - public bool PreHandleReceivedMessage(ClientStruct client, ref Message message) - { - if(additionalData[client].ClientState == ClientState.Encrypted) - { - /* - * Decrypt message before returning. - */ - byte[] encryptedBytes = message.MessageBytes; - byte[] decryptedBytes = DecryptBytes(additionalData[client].Key, encryptedBytes); - message = new Message((uint)decryptedBytes.Length, decryptedBytes); - return false; - } - else - { - /* - * If the state of the client is not encrypted, there's nothing to decrypt. - */ - return false; - } - } - /// - /// Performs periodic operations on the server. - /// - public void Tick() - { - - } - /// - /// Encrypts the message before sending. - /// - /// Client object. - /// Message to be processed. - /// True if no other handler should process this message. - public bool HandleSendMessage(ClientStruct client, ref Message message) - { - if(additionalData[client].ClientState == ClientState.Encrypted) - { - message = CommunicationPrimitives.BuildMessage(EncryptBytes(additionalData[client].Key, message.MessageBytes)); - } - return false; - } + #endregion #region Private Methods private byte[] EncryptBytes(byte[] clientKey, byte[] bytesToBeEncrypted) @@ -221,5 +118,109 @@ namespace MTSC.Server.Handlers return decryptedBytes; } #endregion + #region Handler Implementation + /// + /// Called when a client is being removed. + /// + /// Client to be removed. + void IHandler.ClientRemoved(Server server, ClientStruct client) + { + additionalData.Remove(client); + } + /// + /// Handle a new client connection. + /// + /// New client connection. + /// False if an error occurred. + bool IHandler.HandleClient(Server server, ClientStruct client) + { + additionalData.Add(client, new AdditionalData()); + return false; + } + /// + /// Handle a received message. + /// + /// Client connection. + /// Received message. + /// True if no other handler should handle current message. + bool IHandler.HandleReceivedMessage(Server server, ClientStruct client, Message message) + { + if (additionalData[client].ClientState == ClientState.Initial || additionalData[client].ClientState == ClientState.Negotiating) + { + string asciiMessage = ASCIIEncoding.ASCII.GetString(message.MessageBytes); + if (asciiMessage == CommunicationPrimitives.RequestPublicKey) + { + server.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendPublicKey + ":" + publicKey)); + additionalData[client].ClientState = ClientState.Negotiating; + return true; + } + else if (asciiMessage.Contains(CommunicationPrimitives.SendEncryptionKey)) + { + byte[] encryptedKey = new byte[message.MessageLength - CommunicationPrimitives.SendEncryptionKey.Length - 1]; + Array.Copy(message.MessageBytes, CommunicationPrimitives.SendEncryptionKey.Length + 1, encryptedKey, 0, encryptedKey.Length); + byte[] decryptedKey = rsa.Decrypt(encryptedKey, false); + additionalData[client].Key = decryptedKey; + server.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.AcceptEncryptionKey)); + additionalData[client].ClientState = ClientState.Encrypted; + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + /// + /// Perform transformative operations on the message. + /// + /// Client connection. + /// Message to be processed. + /// True if no other handlers should perform operations on current message. + bool IHandler.PreHandleReceivedMessage(Server server, ClientStruct client, ref Message message) + { + if (additionalData[client].ClientState == ClientState.Encrypted) + { + /* + * Decrypt message before returning. + */ + byte[] encryptedBytes = message.MessageBytes; + byte[] decryptedBytes = DecryptBytes(additionalData[client].Key, encryptedBytes); + message = new Message((uint)decryptedBytes.Length, decryptedBytes); + return false; + } + else + { + /* + * If the state of the client is not encrypted, there's nothing to decrypt. + */ + return false; + } + } + /// + /// Performs periodic operations on the server. + /// + void IHandler.Tick(Server server) + { + + } + /// + /// Encrypts the message before sending. + /// + /// Client object. + /// Message to be processed. + /// True if no other handler should process this message. + bool IHandler.HandleSendMessage(Server server, ClientStruct client, ref Message message) + { + if (additionalData[client].ClientState == ClientState.Encrypted) + { + message = CommunicationPrimitives.BuildMessage(EncryptBytes(additionalData[client].Key, message.MessageBytes)); + } + return false; + } + #endregion } } diff --git a/MTSC/Server/Handlers/HttpHandler.cs b/MTSC/Server/Handlers/HttpHandler.cs index 235ed81..45c1662 100644 --- a/MTSC/Server/Handlers/HttpHandler.cs +++ b/MTSC/Server/Handlers/HttpHandler.cs @@ -13,13 +13,12 @@ namespace MTSC.Server.Handlers public class HttpHandler : IHandler { #region Fields - Server managedServer; List httpModules = new List(); #endregion #region Constructors - public HttpHandler(Server server) + public HttpHandler() { - this.managedServer = server; + } #endregion #region Public Methods @@ -37,10 +36,10 @@ namespace MTSC.Server.Handlers /// Send a response back to the client. /// /// Message containing the response. - public void SendResponse(ClientStruct client, HttpMessage response) + public void SendResponse(Server server, ClientStruct client, HttpMessage response) { byte[] responseBytes = response.GetResponse(); - managedServer.QueueMessage(client, responseBytes); + server.QueueMessage(client, responseBytes); } #endregion #region Interface Implementation @@ -48,7 +47,7 @@ namespace MTSC.Server.Handlers /// Handler interface implementation. /// /// - void IHandler.ClientRemoved(ClientStruct client) + void IHandler.ClientRemoved(Server server, ClientStruct client) { } @@ -57,7 +56,7 @@ namespace MTSC.Server.Handlers /// /// /// - bool IHandler.HandleClient(ClientStruct client) + bool IHandler.HandleClient(Server server, ClientStruct client) { return false; } @@ -67,7 +66,7 @@ namespace MTSC.Server.Handlers /// /// /// - bool IHandler.HandleReceivedMessage(ClientStruct client, Message message) + bool IHandler.HandleReceivedMessage(Server server, ClientStruct client, Message message) { HttpMessage httpMessage = new HttpMessage(); httpMessage.ParseRequest(message.MessageBytes); @@ -86,7 +85,7 @@ namespace MTSC.Server.Handlers /// /// /// - bool IHandler.HandleSendMessage(ClientStruct client, ref Message message) + bool IHandler.HandleSendMessage(Server server, ClientStruct client, ref Message message) { return false; } @@ -96,14 +95,14 @@ namespace MTSC.Server.Handlers /// /// /// - bool IHandler.PreHandleReceivedMessage(ClientStruct client, ref Message message) + bool IHandler.PreHandleReceivedMessage(Server server, ClientStruct client, ref Message message) { return false; } /// /// Handler interface implementation. /// - void IHandler.Tick() + void IHandler.Tick(Server server) { } diff --git a/MTSC/Server/Handlers/IHandler.cs b/MTSC/Server/Handlers/IHandler.cs index c69c2c4..ed0a46b 100644 --- a/MTSC/Server/Handlers/IHandler.cs +++ b/MTSC/Server/Handlers/IHandler.cs @@ -14,37 +14,43 @@ namespace MTSC.Server.Handlers /// Handles a new client. /// /// Client to be handled. + /// Server calling the handler. /// True if the handler processed the client. - bool HandleClient(ClientStruct client); + bool HandleClient(Server server, ClientStruct client); /// /// Handles a message before sending. /// /// Client object. /// Message to be processed. + /// Server calling the handler. /// True if no other handler should handle this message. - bool HandleSendMessage(ClientStruct client, ref Message message); + bool HandleSendMessage(Server server, ClientStruct client, ref Message message); /// /// Called before the message handling. /// Perform here any processing of the message. /// /// Client structure. /// Message to be preprocessed. + /// Server calling the handler. /// True if the message has been preprocessed and no other handler should handle it anymore. - bool PreHandleReceivedMessage(ClientStruct client, ref Message message); + bool PreHandleReceivedMessage(Server server, ClientStruct client, ref Message message); /// /// Handles the received message. /// /// Message to be handled. + /// Server calling the handler. /// True if the message has been handled, false if the message has not been handled. - bool HandleReceivedMessage(ClientStruct client, Message message); + bool HandleReceivedMessage(Server server, ClientStruct client, Message message); /// /// Handles the removal of a client from the server. /// /// Client about to be removed. - void ClientRemoved(ClientStruct client); + /// Server calling the handler. + void ClientRemoved(Server server, ClientStruct client); /// /// Method performs regular operations onto the server. /// - void Tick(); + /// Server calling the handler. + void Tick(Server server); } } diff --git a/MTSC/Server/Server.cs b/MTSC/Server/Server.cs index e0146b6..ed1c69e 100644 --- a/MTSC/Server/Server.cs +++ b/MTSC/Server/Server.cs @@ -165,7 +165,7 @@ namespace MTSC.Server for(int i = handlers.Count - 1; i >= 0; i--) { IHandler handler = handlers[i]; - handler.HandleSendMessage(queuedOrder.Item1, ref sendMessage); + handler.HandleSendMessage(this, queuedOrder.Item1, ref sendMessage); } CommunicationPrimitives.SendMessage(queuedOrder.Item1.TcpClient, sendMessage, queuedOrder.Item1.SslStream); } @@ -190,7 +190,7 @@ namespace MTSC.Server } foreach (IHandler handler in handlers) { - if (handler.HandleClient(clientStruct)) + if (handler.HandleClient(this, clientStruct)) { break; } @@ -225,14 +225,14 @@ namespace MTSC.Server "\nMessage length: " + message.MessageLength); foreach (IHandler handler in handlers) { - if (handler.PreHandleReceivedMessage(client, ref message)) + if (handler.PreHandleReceivedMessage(this, client, ref message)) { break; } } foreach (IHandler handler in handlers) { - if (handler.HandleReceivedMessage(client, message)) + if (handler.HandleReceivedMessage(this, client, message)) { break; } @@ -271,7 +271,7 @@ namespace MTSC.Server { foreach(IHandler handler in handlers) { - handler.ClientRemoved(client); + handler.ClientRemoved(this, client); } client.SslStream?.Dispose(); client.TcpClient?.Dispose();