/// <summary> /// constructor that creates a new object and start listening to messages /// </summary> /// <param name="client">TcpClient object</param> /// <param name="username">the client's username</param> /// <param name="aes">AES crypto object</param> public SnifferLogs(TcpClient client, string username, AesCrypto aes) { this.client = client; this.username = username; this.aes = aes; // Read data from the client async data = new byte[client.ReceiveBufferSize]; // BeginRead will begin async read from the NetworkStream // This allows the server to remain responsive and continue accepting new connections from other clients // When reading complete control will be transfered to the ReviveMessage() function. client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(client.ReceiveBufferSize), ReceiveMessage, null); }
/// <summary> /// recursive method that recieves a message from the server and handles it according to the request or response number /// </summary> /// <param name="ar"></param> public void ReceiveMessage(IAsyncResult ar) { int bytesRead; try { lock (client.GetStream()) { // call EndRead to handle the end of an async read. bytesRead = client.GetStream().EndRead(ar); } Console.WriteLine("in receive server"); if (rsa == null) // RSA object wasn't initialized yet { string key = ByteConverter.GetString(data, 0, bytesRead).Split('#')[1]; // an Rsa crypto object is created rsa = new RsaCrypto(key); Console.WriteLine("created rsa object"); // sends the RSA object public key to the client string messageToSend = RSAPublicKeyTransfer + "#" + rsa.GetServerPublicKey() + "#" + rsa.GetServerPublicKey().Length; SendMessage(ByteConverter.GetBytes(messageToSend)); } else { byte[] arrived = new byte[bytesRead]; Array.Copy(data, arrived, bytesRead); string messageReceived = ""; int requestNumber; int keyLength, ivLength; byte[] key = null, iv = null; string details = null; string[] detailsArray = null; if (aes == null) // AES object wasn't initialized yet { byte[] decrypted = rsa.RSADecrypt(arrived); Console.WriteLine("AES details: " + BytesToString(decrypted)); AnalyzingAesKeyAndIvMessage(decrypted, out requestNumber, out keyLength, out ivLength, out key, out iv); } else { messageReceived = aes.DecryptStringFromBytes(arrived, aes.GetKey(), aes.GetIV()); Console.WriteLine("received: " + messageReceived); string[] arrayReceived = messageReceived.Split('#'); requestNumber = Convert.ToInt32(arrayReceived[0]); details = arrayReceived[1]; detailsArray = details.Split('/'); } string status = "ok"; if (requestNumber == signUpRequest) { detailsArray[1].Replace("\u200B", ""); //detailsArray[1].Replace(detailsArray[1], @"^[\s,]+|[\s,]+$"); // inserts to the SQL table bool b = sql.Insert(detailsArray[0], detailsArray[1], detailsArray[2], detailsArray[3], detailsArray[4], 0); if (!b) { status = "not ok"; SendAesEncryptedMessage(RegisterStatusResponse + "#" + status + "#" + status.Length); } else { // ok, email verification is needed name = detailsArray[0]; email = detailsArray[2]; string code = EmailVerification(email); SendAesEncryptedMessage(EmailRequest + "#" + code + "#" + code.Length); } } else if (requestNumber == signInRequest) { // checks if a player is in the table int check = sql.IsExist(detailsArray[0], detailsArray[1]); if (check == 0) { status = "not ok"; } else { name = detailsArray[0]; } Console.WriteLine(status + " 2"); if (check != 1) { SendAesEncryptedMessage(RegisterStatusResponse + "#" + status + "#" + status.Length); } else { string code = EmailVerification(sql.GetEmail(name)); SendAesEncryptedMessage(EmailRequest + "#" + code + "#" + code.Length); } if (check == 2) { //opens a new object that handles the logs of the sniffer SnifferLogs snifferLogs = new SnifferLogs(client, name, aes); return; } } else if (requestNumber == QuestionRequest) { string question = sql.GetQuestion(details); name = details; SendAesEncryptedMessage(QuestionResponse + "#" + question + "#" + question.Length); } else if (requestNumber == CodeResponse) { string originalCode = detailsArray[0].Trim(); string answer = detailsArray[1].Trim(); bool compare = originalCode.Equals(answer); if (compare) { sql.ChangeEmailConfirmed(name); SendAesEncryptedMessage(RegisterStatusResponse + "#" + "ok" + "#2"); //opens a new object that handles the logs of the sniffer SnifferLogs snifferLogs = new SnifferLogs(client, name, aes); return; } else { // sends another email string code = EmailVerification(sql.GetEmail(name)); SendAesEncryptedMessage(EmailRequest + "#" + code + "#" + code.Length); } } else if (requestNumber == AnswerResponse) { bool checkAnswer = sql.GetAnswer(name).Equals(details); if (checkAnswer) { //let the user invent a new password SendAesEncryptedMessage(PasswordRequest + "##0"); } else { // the answer was incorrect, the client need to try again string question = sql.GetQuestion(details); name = details; SendAesEncryptedMessage(QuestionResponse + "#" + question + "/" + "#" + question.Length); } } else if (requestNumber == PasswordResponse) { bool b = sql.SetPassword(name, details); string isChanged = "ok"; if (!b) { isChanged = "not ok"; } SendAesEncryptedMessage(PasswordChangeStatusResponse + "#" + isChanged + "#" + isChanged.Length); } else if (requestNumber == RSAPublicKeyTransfer) { // an Rsa crypto object is created rsa = new RsaCrypto(details); string messageToSend = RSAPublicKeyTransfer + "#" + rsa.GetServerPublicKey() + "#" + rsa.GetServerPublicKey().Length; SendMessage(ByteConverter.GetBytes(messageToSend)); } else if (requestNumber == AesKeyTransfer) { // initializes the AES object aes = new AesCrypto(key, iv); Console.WriteLine("received- Key: {0}\nIV: {1}", BytesToString(key), BytesToString(iv)); Console.WriteLine("aes object- Key: {0}\nIV: {1}", BytesToString(aes.GetKey()), BytesToString(aes.GetIV())); } } lock (client.GetStream()) { // continue reading from the client client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(client.ReceiveBufferSize), ReceiveMessage, null); } } catch (Exception ex) { Console.WriteLine("catch recieve"); Console.WriteLine(ex.ToString()); } }