private int ExtractEmail(NetworkTcpSession tcpSession, TcpPacket tcpPacket, int emailStartIndex, int length) { Utils.StreamReassembler reassembler; if (this.emailReassemblers.ContainsKey(tcpSession)) { reassembler = this.emailReassemblers[tcpSession]; } else { reassembler = new Utils.StreamReassembler(Pop3Packet.MULTILINE_RESPONSE_TERMINATOR, 2);//include the first 2 bytes of the terminator to get a CR-LF at the end of the extracted data this.emailReassemblers.Add(tcpSession, reassembler); } //add all data after the POP3 response header (after +OK or +ERR) int addedBytes = reassembler.AddData(tcpPacket.ParentFrame.Data, emailStartIndex, length); if (reassembler.TerminatorFound) { //I'm assuming the email is going from server to client Mime.Email email = new Mime.Email(reassembler.DataStream, base.MainPacketHandler, tcpPacket, false, tcpSession, ApplicationLayerProtocol.Pop3, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.source); //remove the last command since we don't wanna reassemble any more for this RETR command if (this.pop3LastCommand.ContainsKey(tcpSession)) { this.pop3LastCommand.Remove(tcpSession); } this.emailReassemblers.Remove(tcpSession); } return(addedBytes); }
//public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<PacketParser.Packets.AbstractPacket> packetList) { public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList) { /* * NetworkHost sourceHost, destinationHost; * if (transferIsClientToServer) { * sourceHost = tcpSession.Flow.FiveTuple.ClientHost; * destinationHost = tcpSession.Flow.FiveTuple.ServerHost; * } * else { * sourceHost = tcpSession.Flow.FiveTuple.ServerHost; * destinationHost = tcpSession.Flow.FiveTuple.ClientHost; * }*/ SmtpSession smtpSession; if (this.smtpSessionList.ContainsKey(tcpSession)) { smtpSession = this.smtpSessionList[tcpSession]; } else { smtpSession = new SmtpSession(); this.smtpSessionList.Add(tcpSession, smtpSession); } Packets.TcpPacket tcpPacket = null; Packets.SmtpPacket smtpPacket = null; foreach (Packets.AbstractPacket p in packetList) { if (p.GetType() == typeof(Packets.TcpPacket)) { tcpPacket = (Packets.TcpPacket)p; } else if (p.GetType() == typeof(Packets.SmtpPacket)) { smtpPacket = (Packets.SmtpPacket)p; } } if (smtpPacket != null) { if (smtpPacket.ClientToServer) { if (smtpSession.State == SmtpSession.SmtpState.Username) { string base64Username = smtpPacket.ReadLine().Trim(); try { byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Password) { string base64Password = smtpPacket.ReadLine().Trim(); try { byte[] passwordBytes = System.Convert.FromBase64String(base64Password); smtpSession.Password = System.Text.ASCIIEncoding.ASCII.GetString(passwordBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Data) { //write data to file until we receive "\n.\n" could also be \r\n.\r\n smtpSession.AddData(smtpPacket.ParentFrame.Data, smtpPacket.PacketStartIndex, smtpPacket.PacketLength); //check if state has transitioned over to footer if (smtpSession.State == SmtpSession.SmtpState.Footer) { Mime.Email email = new Mime.Email(smtpSession.DataStream, base.MainPacketHandler, tcpPacket, transferIsClientToServer, tcpSession, ApplicationLayerProtocol.Smtp, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination); } } else { foreach (KeyValuePair <string, string> requestCommandAndArgument in smtpPacket.RequestCommandsAndArguments) { if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.Trim().StartsWith("LOGIN", StringComparison.InvariantCultureIgnoreCase)) { //if (requestCommandAndArgument.Value.ToUpper().Contains("LOGIN")) { smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "LOGIN ".Length) { try { string base64Username = requestCommandAndArgument.Value.Substring("LOGIN ".Length).Trim(); byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (ArgumentException) { } } } else if (requestCommandAndArgument.Value.Trim().StartsWith("PLAIN", StringComparison.InvariantCultureIgnoreCase)) { //AUTH PLAIN <base64-encoded username and password> smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "PLAIN ".Length) { try { string base64 = requestCommandAndArgument.Value.Substring("PLAIN ".Length).Trim(); NetworkCredential cred = SmtpPacketHandler.ExtractBase64EncodedAuthPlainCredential(base64, smtpPacket.ParentFrame, tcpSession, ApplicationLayerProtocol.Smtp); if (cred != null) { //this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); this.MainPacketHandler.AddCredential(cred); } } catch (ArgumentException) { } } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.MailFrom = requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim(); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.AddRecipient(requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim()); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.Data; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.STARTTLS.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.StartTlsRequested; } } } } else //server to client { foreach (KeyValuePair <int, string> replyCodeAndArgument in smtpPacket.Replies) { if (replyCodeAndArgument.Key == 334) //AUTH LOGIN { if (replyCodeAndArgument.Value.Equals("VXNlcm5hbWU6")) { smtpSession.State = SmtpSession.SmtpState.Username; } else if (replyCodeAndArgument.Value.Equals("UGFzc3dvcmQ6")) { smtpSession.State = SmtpSession.SmtpState.Password; } } else if (replyCodeAndArgument.Key == 235) //AUTHENTICATION SUCCESSFUL { base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, smtpPacket.PacketTypeDescription, smtpSession.Username, smtpSession.Password, smtpPacket.ParentFrame.Timestamp)); smtpSession.State = SmtpSession.SmtpState.Authenticated; } else if (replyCodeAndArgument.Key >= 500) //error { smtpSession.State = SmtpSession.SmtpState.None; } else if (replyCodeAndArgument.Key == 354) //DATA "Start mail input; end with <CRLF>.<CRLF>" { smtpSession.State = SmtpSession.SmtpState.Data; } else if (replyCodeAndArgument.Key == 250) //"Requested mail action okay, completed" { if (smtpSession.State == SmtpSession.SmtpState.Footer) { //smtpSession.DataStream.Seek(0, System.IO.SeekOrigin.Begin); smtpSession.DataStream = new System.IO.MemoryStream(); //System.Diagnostics.Debugger.Break(); } smtpSession.State = SmtpSession.SmtpState.None;//Added in order to reset state when multiple SMTP sessions are sent within the same TCP session } else if (replyCodeAndArgument.Key == 220) { if (smtpSession.State == SmtpSession.SmtpState.StartTlsRequested) { tcpSession.ProtocolFinder.SetConfirmedApplicationLayerProtocol(ApplicationLayerProtocol.Ssl, false); } } } } //There was a SMTP packet, so treat this as a sucsessfull extraction return(tcpPacket.PayloadDataLength); } else //smtpPacket == null { return(0); } }
private int ExtractEmail(NetworkTcpSession tcpSession, TcpPacket tcpPacket, int emailStartIndex, int length, int totalLength = 0, bool clientToServer = false) { System.IO.MemoryStream reassembler; if (this.serverToClientEmailReassemblers.ContainsKey(tcpSession)) { reassembler = this.serverToClientEmailReassemblers[tcpSession]; clientToServer = false; } else if (this.clientToServerEmailReassemblers.ContainsKey(tcpSession)) { reassembler = this.clientToServerEmailReassemblers[tcpSession]; clientToServer = true; } else if (totalLength > 0) { //reassembler = new Utils.StreamReassembler(Pop3Packet.MULTILINE_RESPONSE_TERMINATOR, 2);//include the first 2 bytes of the terminator to get a CR-LF at the end of the extracted data reassembler = new System.IO.MemoryStream(totalLength); if (clientToServer) { this.clientToServerEmailReassemblers.Add(tcpSession, reassembler); } else { this.serverToClientEmailReassemblers.Add(tcpSession, reassembler); } } else { return(0); } if (reassembler.Capacity < reassembler.Position + length) { length = (int)(reassembler.Capacity - reassembler.Position); } reassembler.Write(tcpPacket.ParentFrame.Data, emailStartIndex, length); if (reassembler.Position == reassembler.Capacity) { FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation assemblyLocation; if (clientToServer) { assemblyLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination; } else { assemblyLocation = FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.source; //remove the last command since we don't wanna reassemble any more for this command if (this.lastCommand.ContainsKey(tcpSession)) { this.lastCommand.Remove(tcpSession); } } Mime.Email email = new Mime.Email(reassembler, base.MainPacketHandler, tcpPacket, clientToServer, tcpSession, ApplicationLayerProtocol.Imap, assemblyLocation); /* * if (clientToServer) { * email = new Mime.Email(reassembler, base.MainPacketHandler, tcpPacket, tcpSession.ClientHost, tcpSession.ServerHost, tcpSession, ApplicationLayerProtocol.Imap, !clientToServer); * this.clientToServerEmailReassemblers.Remove(tcpSession); * } * else { * email = new Mime.Email(reassembler, base.MainPacketHandler, tcpPacket, tcpSession.ServerHost, tcpSession.ClientHost, tcpSession, ApplicationLayerProtocol.Imap, !clientToServer); * this.serverToClientEmailReassemblers.Remove(tcpSession); * //remove the last command since we don't wanna reassemble any more for this command * if (this.lastCommand.ContainsKey(tcpSession)) * this.lastCommand.Remove(tcpSession); * } */ } return(length); }