1 /* packet-smtp.c
2  * Routines for SMTP packet disassembly
3  *
4  * Copyright (c) 2000 by Richard Sharpe <rsharpe@ns.aus.com>
5  *
6  * Added RFC 4954 SMTP Authentication
7  *     Michael Mann * Copyright 2012
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1999 Gerald Combs
12  *
13  * SPDX-License-Identifier: GPL-2.0-or-later
14  */
15 
16 #include "config.h"
17 
18 #include <stdlib.h>
19 
20 #include <epan/packet.h>
21 #include <epan/conversation.h>
22 #include <epan/prefs.h>
23 #include <epan/strutil.h>
24 #include <epan/reassemble.h>
25 #include <epan/proto_data.h>
26 
27 #include <ui/tap-credentials.h>
28 #include <tap.h>
29 
30 #include <wsutil/str_util.h>
31 #include "packet-tls.h"
32 #include "packet-tls-utils.h"
33 
34 /* RFC 2821 */
35 #define TCP_PORT_SMTP      "25"
36 #define TCP_PORT_SSL_SMTP 465
37 
38 /* RFC 4409 */
39 #define TCP_PORT_SUBMISSION 587
40 
41 void proto_register_smtp(void);
42 void proto_reg_handoff_smtp(void);
43 
44 static int proto_smtp = -1;
45 
46 static int credentials_tap = -1;
47 
48 static int hf_smtp_req = -1;
49 static int hf_smtp_rsp = -1;
50 static int hf_smtp_message = -1;
51 static int hf_smtp_command_line = -1;
52 static int hf_smtp_req_command = -1;
53 static int hf_smtp_req_parameter = -1;
54 static int hf_smtp_response = -1;
55 static int hf_smtp_rsp_code = -1;
56 static int hf_smtp_rsp_parameter = -1;
57 static int hf_smtp_username = -1;
58 static int hf_smtp_password = -1;
59 static int hf_smtp_username_password = -1;
60 static int hf_smtp_eom = -1;
61 
62 static int hf_smtp_data_fragments = -1;
63 static int hf_smtp_data_fragment = -1;
64 static int hf_smtp_data_fragment_overlap = -1;
65 static int hf_smtp_data_fragment_overlap_conflicts = -1;
66 static int hf_smtp_data_fragment_multiple_tails = -1;
67 static int hf_smtp_data_fragment_too_long_fragment = -1;
68 static int hf_smtp_data_fragment_error = -1;
69 static int hf_smtp_data_fragment_count = -1;
70 static int hf_smtp_data_reassembled_in = -1;
71 static int hf_smtp_data_reassembled_length = -1;
72 
73 static int ett_smtp = -1;
74 static int ett_smtp_cmdresp = -1;
75 
76 static gint ett_smtp_data_fragment = -1;
77 static gint ett_smtp_data_fragments = -1;
78 
79 static expert_field ei_smtp_base64_decode = EI_INIT;
80 static expert_field ei_smtp_rsp_code = EI_INIT;
81 
82 static gboolean    smtp_auth_parameter_decoding_enabled     = FALSE;
83 /* desegmentation of SMTP command and response lines */
84 static gboolean    smtp_desegment              = TRUE;
85 static gboolean    smtp_data_desegment         = TRUE;
86 
87 static reassembly_table smtp_data_reassembly_table;
88 
89 static const fragment_items smtp_data_frag_items = {
90   /* Fragment subtrees */
91   &ett_smtp_data_fragment,
92   &ett_smtp_data_fragments,
93   /* Fragment fields */
94   &hf_smtp_data_fragments,
95   &hf_smtp_data_fragment,
96   &hf_smtp_data_fragment_overlap,
97   &hf_smtp_data_fragment_overlap_conflicts,
98   &hf_smtp_data_fragment_multiple_tails,
99   &hf_smtp_data_fragment_too_long_fragment,
100   &hf_smtp_data_fragment_error,
101   &hf_smtp_data_fragment_count,
102   /* Reassembled in field */
103   &hf_smtp_data_reassembled_in,
104   /* Reassembled length field */
105   &hf_smtp_data_reassembled_length,
106   /* Reassembled data field */
107   NULL,
108   /* Tag */
109   "DATA fragments"
110 };
111 
112 static  dissector_handle_t smtp_handle;
113 static  dissector_handle_t tls_handle;
114 static  dissector_handle_t imf_handle;
115 static  dissector_handle_t ntlmssp_handle;
116 static  dissector_handle_t data_text_lines_handle;
117 
118 /*
119  * A CMD is an SMTP command, MESSAGE is the message portion, and EOM is the
120  * last part of a message
121  */
122 #define SMTP_PDU_CMD     0
123 #define SMTP_PDU_MESSAGE 1
124 #define SMTP_PDU_EOM     2
125 
126 struct smtp_proto_data {
127   guint16 pdu_type;
128   guint16 conversation_id;
129   gboolean more_frags;
130 };
131 
132 /*
133  * State information stored with a conversation.
134  */
135 typedef enum {
136   SMTP_STATE_START,                     /* Start of SMTP conversion */
137   SMTP_STATE_READING_CMDS,              /* reading commands */
138   SMTP_STATE_READING_DATA,              /* reading message data */
139   SMTP_STATE_AWAITING_STARTTLS_RESPONSE /* sent STARTTLS, awaiting response */
140 } smtp_state_t;
141 
142 typedef enum {
143   SMTP_AUTH_STATE_NONE,               /*  No authentication seen or used */
144   SMTP_AUTH_STATE_START,              /* Authentication started, waiting for username */
145   SMTP_AUTH_STATE_USERNAME_REQ,       /* Received username request from server */
146   SMTP_AUTH_STATE_USERNAME_RSP,       /* Received username response from client */
147   SMTP_AUTH_STATE_PASSWORD_REQ,       /* Received password request from server */
148   SMTP_AUTH_STATE_PASSWORD_RSP,       /* Received password request from server */
149   SMTP_AUTH_STATE_PLAIN_START_REQ,    /* Received AUTH PLAIN command from client*/
150   SMTP_AUTH_STATE_PLAIN_CRED_REQ,     /* Received AUTH PLAIN command including creds from client*/
151   SMTP_AUTH_STATE_PLAIN_REQ,          /* Received AUTH PLAIN request from server */
152   SMTP_AUTH_STATE_PLAIN_RSP,          /* Received AUTH PLAIN response from client */
153   SMTP_AUTH_STATE_NTLM_REQ,           /* Received ntlm negotiate request from client */
154   SMTP_AUTH_STATE_NTLM_CHALLANGE,     /* Received ntlm challange request from server */
155   SMTP_AUTH_STATE_NTLM_RSP,           /* Received ntlm auth request from client */
156   SMTP_AUTH_STATE_SUCCESS,            /* Password received, authentication successful, start decoding */
157   SMTP_AUTH_STATE_FAILED              /* authentication failed, no decoding */
158 } smtp_auth_state_t;
159 
160 typedef enum {
161   SMTP_MULTILINE_NONE,
162   SMTP_MULTILINE_START,
163   SMTP_MULTILINE_CONTINUE,
164   SMTP_MULTILINE_END
165 
166 } smtp_multiline_state_t;
167 
168 struct smtp_session_state {
169   smtp_state_t smtp_state;      /* Current state */
170   smtp_auth_state_t auth_state; /* Current authentication state */
171   /* Values that need to be saved because state machine can't be used during tree dissection */
172   guint32  first_auth_frame;    /* First frame involving authentication. */
173   guint32  username_frame;      /* Frame containing client username */
174   guint32  password_frame;      /* Frame containing client password */
175   guint32  last_auth_frame;     /* Last frame involving authentication. */
176   guint8*  username;            /* The username in the authentication. */
177   gboolean crlf_seen;           /* Have we seen a CRLF on the end of a packet */
178   gboolean data_seen;           /* Have we seen a DATA command yet */
179   guint32  msg_read_len;        /* Length of BDAT message read so far */
180   guint32  msg_tot_len;         /* Total length of BDAT message */
181   gboolean msg_last;            /* Is this the last BDAT chunk */
182   guint32  username_cmd_frame;  /* AUTH command contains username */
183   guint32  user_pass_cmd_frame; /* AUTH command contains username and password */
184   guint32  user_pass_frame;     /* Frame contains username and password */
185   guint32  ntlm_req_frame;      /* Frame containing NTLM request */
186   guint32  ntlm_cha_frame;      /* Frame containing NTLM challange. */
187   guint32  ntlm_rsp_frame;      /* Frame containing NTLM response. */
188 };
189 
190 /*
191  * See
192  *
193  *      http://support.microsoft.com/default.aspx?scid=kb;[LN];812455
194  *
195  * for the Exchange extensions.
196  */
197 static const struct {
198   const char *command;
199   int len;
200 } commands[] = {
201   { "STARTTLS", 8 },            /* RFC 2487 */
202   { "X-EXPS", 6 },              /* Microsoft Exchange */
203   { "X-LINK2STATE", 12 },       /* Microsoft Exchange */
204   { "XEXCH50", 7 }              /* Microsoft Exchange */
205 };
206 
207 #define NCOMMANDS       (sizeof commands / sizeof commands[0])
208 
209 /* The following were copied from RFC 2821 */
210 static const value_string response_codes_vs[] = {
211   { 211, "System status, or system help reply" },
212   { 214, "Help message" },
213   { 220, "<domain> Service ready" },
214   { 221, "<domain> Service closing transmission channel" },
215   { 235, "Authentication successful" },
216   { 250, "Requested mail action okay, completed" },
217   { 251, "User not local; will forward to <forward-path>" },
218   { 252, "Cannot VRFY user, but will accept message and attempt delivery" },
219   { 334, "AUTH input" },
220   { 354, "Start mail input; end with <CRLF>.<CRLF>" },
221   { 421, "<domain> Service not available, closing transmission channel" },
222   { 432, "A password transition is needed" },
223   { 450, "Requested mail action not taken: mailbox unavailable" },
224   { 451, "Requested action aborted: local error in processing" },
225   { 452, "Requested action not taken: insufficient system storage" },
226   { 454, "Temporary authentication failed" },
227   { 500, "Syntax error, command unrecognized" },
228   { 501, "Syntax error in parameters or arguments" },
229   { 502, "Command not implemented" },
230   { 503, "Bad sequence of commands" },
231   { 504, "Command parameter not implemented" },
232   { 530, "Authentication required" },
233   { 534, "Authentication mechanism is too weak" },
234   { 535, "Authentication credentials invalid" },
235   { 538, "Encryption required for requested authentication mechanism" },
236   { 550, "Requested action not taken: mailbox unavailable" },
237   { 551, "User not local; please try <forward-path>" },
238   { 552, "Requested mail action aborted: exceeded storage allocation" },
239   { 553, "Requested action not taken: mailbox name not allowed" },
240   { 554, "Transaction failed" },
241   { 0, NULL }
242 };
243 static value_string_ext response_codes_vs_ext = VALUE_STRING_EXT_INIT(response_codes_vs);
244 
245 static gboolean
line_is_smtp_command(const guchar * command,int commandlen)246 line_is_smtp_command(const guchar *command, int commandlen)
247 {
248   size_t i;
249 
250   /*
251    * To quote RFC 821, "Command codes are four alphabetic
252    * characters".
253    *
254    * However, there are some SMTP extensions that involve commands
255    * longer than 4 characters and/or that contain non-alphabetic
256    * characters; we treat them specially.
257    *
258    * XXX - should we just have a table of known commands?  Or would
259    * that fail to catch some extensions we don't know about?
260    */
261   if (commandlen == 4 && g_ascii_isalpha(command[0]) &&
262       g_ascii_isalpha(command[1]) && g_ascii_isalpha(command[2]) &&
263       g_ascii_isalpha(command[3])) {
264     /* standard 4-alphabetic command */
265     return TRUE;
266   }
267 
268   /*
269    * Check the list of non-4-alphabetic commands.
270    */
271   for (i = 0; i < NCOMMANDS; i++) {
272     if (commandlen == commands[i].len &&
273         g_ascii_strncasecmp(command, commands[i].command, commands[i].len) == 0)
274       return TRUE;
275   }
276   return FALSE;
277 }
278 
279 static void
dissect_smtp_data(tvbuff_t * tvb,int offset,proto_tree * smtp_tree)280 dissect_smtp_data(tvbuff_t *tvb, int offset, proto_tree *smtp_tree)
281 {
282   gint next_offset;
283 
284   if (smtp_tree) {
285     while (tvb_offset_exists(tvb, offset)) {
286       /*
287        * Find the end of the line.
288        */
289       tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
290 
291       /*
292        * Put this line.
293        */
294       proto_tree_add_item(smtp_tree, hf_smtp_message, tvb,
295                           offset, next_offset - offset, ENC_ASCII|ENC_NA);
296 
297       /*
298        * Step to the next line.
299        */
300       offset = next_offset;
301     }
302   }
303 }
304 
305 static void
dissect_ntlm_auth(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,const char * line)306 dissect_ntlm_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
307                   const char *line)
308 {
309     tvbuff_t *ntlm_tvb;
310 
311     ntlm_tvb = base64_to_tvb(tvb, line);
312     if(tvb_strneql(ntlm_tvb, 0, "NTLMSSP", 7) == 0) {
313       add_new_data_source(pinfo, ntlm_tvb, "NTLMSSP Data");
314       call_dissector(ntlmssp_handle, ntlm_tvb, pinfo, tree);
315     }
316 }
317 
318 static void
decode_plain_auth(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint a_offset,int a_linelen)319 decode_plain_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
320                   gint a_offset, int a_linelen)
321 {
322   gint                       returncode;
323   gint                       length_user1;
324   gint                       length_user2;
325   gint                       length_pass;
326   guint8                    *decrypt   = NULL;
327   proto_item                *ti;
328   gsize                      len = 0;
329 
330   decrypt = tvb_get_string_enc(pinfo->pool, tvb, a_offset, a_linelen, ENC_ASCII);
331   if (smtp_auth_parameter_decoding_enabled) {
332     if (strlen(decrypt) > 1) {
333       g_base64_decode_inplace(decrypt, &len);
334       decrypt[len] = 0;
335     }
336     returncode = (gint)len;
337     if (returncode) {
338       gchar* username;
339       length_user1 = (gint)strlen(decrypt);
340       if (returncode >= (length_user1 + 1)) {
341         length_user2 = (gint)strlen(decrypt + length_user1 + 1);
342         proto_tree_add_string(tree, hf_smtp_username, tvb,
343                               a_offset, a_linelen, decrypt + length_user1 + 1);
344         username = format_text(pinfo->pool, decrypt + length_user1 + 1, length_user2);
345         col_append_fstr(pinfo->cinfo, COL_INFO, "User: %s", username);
346 
347         if (returncode >= (length_user1 + 1 + length_user2 + 1)) {
348           length_pass = (gint)strlen(decrypt + length_user1 + length_user2 + 2);
349           proto_tree_add_string(tree, hf_smtp_password, tvb,
350                                 a_offset, length_pass, decrypt + length_user1 + length_user2 + 2);
351           col_append_str(pinfo->cinfo, COL_INFO, " ");
352           col_append_fstr(pinfo->cinfo, COL_INFO, " Pass: %s",
353                           format_text(pinfo->pool, decrypt + length_user1 + length_user2 + 2, length_pass));
354 
355           tap_credential_t* auth = wmem_new0(pinfo->pool, tap_credential_t);
356           auth->num = pinfo->num;
357           auth->username_num = pinfo->num;
358           auth->password_hf_id = hf_smtp_password;
359           auth->username = username;
360           auth->proto = "SMTP";
361           tap_queue_packet(credentials_tap, pinfo, auth);
362         }
363       }
364     }
365   }
366   else {
367     ti = proto_tree_add_item(tree, hf_smtp_username_password, tvb,
368                           a_offset, a_linelen, ENC_ASCII|ENC_NA);
369     expert_add_info(pinfo, ti, &ei_smtp_base64_decode);
370     col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, decrypt, a_linelen));
371   }
372 }
373 
374 static int
dissect_smtp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)375 dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
376 {
377   struct smtp_proto_data    *spd_frame_data;
378   proto_tree                *smtp_tree = NULL;
379   proto_tree                *cmdresp_tree = NULL;
380   proto_item                *ti, *hidden_item;
381   int                        offset    = 0;
382   int                        request   = 0;
383   conversation_t            *conversation;
384   struct smtp_session_state *session_state;
385   const guchar              *line, *linep, *lineend;
386   guint32                    code;
387   int                        linelen   = 0;
388   gint                       length_remaining;
389   gboolean                   eom_seen  = FALSE;
390   gint                       next_offset;
391   gint                       loffset   = 0;
392   int                        cmdlen;
393   fragment_head             *frag_msg  = NULL;
394   tvbuff_t                  *next_tvb;
395   guint8                    *decrypt   = NULL;
396   gsize                      decrypt_len  = 0;
397   guint8                    *base64_string   = NULL;
398   guint8                     line_code[3];
399 
400   /* As there is no guarantee that we will only see frames in the
401    * the SMTP conversation once, and that we will see them in
402    * order - in Wireshark, the user could randomly click on frames
403    * in the conversation in any order in which they choose - we
404    * have to store information with each frame indicating whether
405    * it contains commands or data or an EOM indication.
406    *
407    * XXX - what about frames that contain *both*?  TCP is a
408    * byte-stream protocol, and there are no guarantees that
409    * TCP segment boundaries will correspond to SMTP commands
410    * or EOM indications.
411    *
412    * We only need that for the client->server stream; responses
413    * are easy to manage.
414    *
415    * If we have per frame data, use that, else, we must be on the first
416    * pass, so we figure it out on the first pass.
417    */
418 
419   /*
420    * Find or create the conversation for this.
421    */
422   conversation = find_or_create_conversation(pinfo);
423 
424   /*
425    * Is there a request structure attached to this conversation?
426    */
427   session_state = (struct smtp_session_state *)conversation_get_proto_data(conversation, proto_smtp);
428   if (!session_state) {
429     /*
430      * No - create one and attach it.
431      */
432     session_state                    = wmem_new0(wmem_file_scope(), struct smtp_session_state);
433     session_state->smtp_state        = SMTP_STATE_START;
434     session_state->auth_state        = SMTP_AUTH_STATE_NONE;
435     session_state->msg_last          = TRUE;
436 
437     conversation_add_proto_data(conversation, proto_smtp, session_state);
438   }
439 
440   /* Is this a request or a response? */
441   request = pinfo->destport == pinfo->match_uint;
442 
443   /*
444    * Is there any data attached to this frame?
445    */
446   spd_frame_data = (struct smtp_proto_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smtp, 0);
447 
448   if (!spd_frame_data) {
449 
450     /*
451      * No frame data.
452      */
453     if (request) {
454 
455       /*
456        * Create a frame data structure and attach it to the packet.
457        */
458       spd_frame_data = wmem_new0(wmem_file_scope(), struct smtp_proto_data);
459 
460       spd_frame_data->conversation_id = conversation->conv_index;
461       spd_frame_data->more_frags = TRUE;
462 
463       p_add_proto_data(wmem_file_scope(), pinfo, proto_smtp, 0, spd_frame_data);
464 
465     }
466 
467     /*
468      * Get the first line from the buffer.
469      *
470      * Note that "tvb_find_line_end()" will, if it doesn't return
471      * -1, return a value that is not longer than what's in the buffer,
472      * and "tvb_find_line_end()" will always return a value that is not
473      * longer than what's in the buffer, so the "tvb_get_ptr()" call
474      * won't throw an exception.
475      */
476     loffset = offset;
477     while (tvb_offset_exists(tvb, loffset)) {
478       linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset,
479                                   smtp_desegment && pinfo->can_desegment);
480       if (linelen == -1) {
481         if (offset == loffset) {
482           /*
483            * We didn't find a line ending, and we're doing desegmentation;
484            * tell the TCP dissector where the data for this message starts
485            * in the data it handed us, and tell it we need more bytes
486            */
487           pinfo->desegment_offset = loffset;
488           pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
489           return tvb_captured_length(tvb);
490         } else {
491           linelen = tvb_reported_length_remaining(tvb, loffset);
492           next_offset = loffset + linelen;
493         }
494       }
495 
496       /*
497        * Check whether or not this packet is an end of message packet
498        * We should look for CRLF.CRLF and they may be split.
499        * We have to keep in mind that we may see what we want on
500        * two passes through here ...
501        */
502       if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
503         /*
504          * The order of these is important ... We want to avoid
505          * cases where there is a CRLF at the end of a packet and a
506          * .CRLF at the beginning of the same packet.
507          */
508         if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) ||
509             tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0)
510           eom_seen = TRUE;
511 
512         length_remaining = tvb_captured_length_remaining(tvb, loffset);
513         if (length_remaining == tvb_reported_length_remaining(tvb, loffset) &&
514             tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0)
515           session_state->crlf_seen = TRUE;
516         else
517           session_state->crlf_seen = FALSE;
518       }
519 
520       /*
521        * OK, Check if we have seen a DATA request. We do it here for
522        * simplicity, but we have to be careful below.
523        */
524       if (request) {
525         if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
526           /*
527            * This is message data.
528            */
529           if (eom_seen) { /* Seen the EOM */
530             /*
531              * EOM.
532              * Everything that comes after it is commands.
533              */
534             spd_frame_data->pdu_type = SMTP_PDU_EOM;
535             session_state->smtp_state = SMTP_STATE_READING_CMDS;
536             break;
537           } else {
538             /*
539              * Message data with no EOM.
540              */
541             spd_frame_data->pdu_type = SMTP_PDU_MESSAGE;
542 
543             if (session_state->msg_tot_len > 0) {
544               /*
545                * We are handling a BDAT message.
546                * Check if we have reached end of the data chunk.
547                */
548               session_state->msg_read_len += tvb_reported_length_remaining(tvb, loffset);
549               /*
550                * Since we're grabbing the rest of the packet, update the offset accordingly
551                */
552               next_offset = tvb_reported_length(tvb);
553 
554               if (session_state->msg_read_len == session_state->msg_tot_len) {
555                 /*
556                  * We have reached end of BDAT data chunk.
557                  * Everything that comes after this is commands.
558                  */
559                 session_state->smtp_state = SMTP_STATE_READING_CMDS;
560 
561                 if (session_state->msg_last) {
562                   /*
563                    * We have found the LAST data chunk.
564                    * The message can now be reassembled.
565                    */
566                   spd_frame_data->more_frags = FALSE;
567                 }
568 
569                 break; /* no need to go through the remaining lines */
570               }
571             }
572           }
573         } else {
574           /*
575            * This is commands - unless the capture started in the
576            * middle of a session, and we're in the middle of data.
577            *
578            * Commands are not necessarily 4 characters; look
579            * for a space or the end of the line to see where
580            * the putative command ends.
581            */
582           if ((session_state->auth_state != SMTP_AUTH_STATE_NONE) &&
583               (pinfo->num >= session_state->first_auth_frame) &&
584               ((session_state->last_auth_frame == 0) || (pinfo->num <= session_state->last_auth_frame))) {
585             decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
586             if ((smtp_auth_parameter_decoding_enabled) &&
587                 (strlen(decrypt) > 1) &&
588                 (g_base64_decode_inplace(decrypt, &decrypt_len)) &&
589                 (decrypt_len > 0)) {
590               decrypt[decrypt_len] = 0;
591               line = decrypt;
592               linelen = (int)decrypt_len;
593             } else {
594               line = tvb_get_ptr(tvb, loffset, linelen);
595               decrypt_len = linelen;
596             }
597           } else {
598             line = tvb_get_ptr(tvb, loffset, linelen);
599           }
600 
601           linep = line;
602           lineend = line + linelen;
603           while (linep < lineend && *linep != ' ')
604             linep++;
605           cmdlen = (int)(linep - line);
606           if (line_is_smtp_command(line, cmdlen)) {
607             if (g_ascii_strncasecmp(line, "DATA", 4) == 0) {
608               /*
609                * DATA command.
610                * This is a command, but everything that comes after it,
611                * until an EOM, is data.
612                */
613               spd_frame_data->pdu_type = SMTP_PDU_CMD;
614               session_state->smtp_state = SMTP_STATE_READING_DATA;
615               session_state->data_seen = TRUE;
616             } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) {
617               /*
618                * BDAT command.
619                * This is a command, but everything that comes after it,
620                * until given length is received, is data.
621                */
622               guint32 msg_len;
623 
624               msg_len = (guint32)strtoul (line+5, NULL, 10);
625 
626               spd_frame_data->pdu_type = SMTP_PDU_CMD;
627               session_state->data_seen = TRUE;
628               session_state->msg_tot_len += msg_len;
629 
630               if (msg_len == 0) {
631                 /* No data to read, next will be a command */
632                 session_state->smtp_state = SMTP_STATE_READING_CMDS;
633               } else {
634                 session_state->smtp_state = SMTP_STATE_READING_DATA;
635               }
636 
637               if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) {
638                 /*
639                  * This is the last data chunk.
640                  */
641                 session_state->msg_last = TRUE;
642 
643                 if (msg_len == 0) {
644                   /*
645                    * No more data to expect.
646                    * The message can now be reassembled.
647                    */
648                   spd_frame_data->more_frags = FALSE;
649                 }
650               } else {
651                 session_state->msg_last = FALSE;
652               }
653             } else if ((g_ascii_strncasecmp(line, "AUTH LOGIN", 10) == 0) && (linelen <= 11)) {
654               /*
655                * AUTH LOGIN command.
656                * Username is in a separate frame
657                */
658               spd_frame_data->pdu_type        = SMTP_PDU_CMD;
659               session_state->smtp_state       = SMTP_STATE_READING_CMDS;
660               session_state->auth_state       = SMTP_AUTH_STATE_START;
661               session_state->first_auth_frame = pinfo->num;
662             } else if ((g_ascii_strncasecmp(line, "AUTH LOGIN", 10) == 0) && (linelen > 11)) {
663               /*
664                * AUTH LOGIN command.
665                * Username follows the 'AUTH LOGIN' string
666                */
667               spd_frame_data->pdu_type        = SMTP_PDU_CMD;
668               session_state->smtp_state       = SMTP_STATE_READING_CMDS;
669               session_state->auth_state       = SMTP_AUTH_STATE_USERNAME_RSP;
670               session_state->first_auth_frame = pinfo->num;
671               session_state->username_cmd_frame = pinfo->num;
672             } else if ((g_ascii_strncasecmp(line, "AUTH PLAIN", 10) == 0) && (linelen <= 11)) {
673               /*
674                * AUTH PLAIN command.
675                * Username and Password is in one separate frame
676                */
677               spd_frame_data->pdu_type        = SMTP_PDU_CMD;
678               session_state->smtp_state       = SMTP_STATE_READING_CMDS;
679               session_state->auth_state       = SMTP_AUTH_STATE_PLAIN_START_REQ;
680               session_state->first_auth_frame = pinfo->num;
681             } else if ((g_ascii_strncasecmp(line, "AUTH PLAIN", 10) == 0) && (linelen > 11)) {
682               /*
683                * AUTH PLAIN command.
684                * Username and Password follows the 'AUTH PLAIN' string
685                */
686               spd_frame_data->pdu_type        = SMTP_PDU_CMD;
687               session_state->smtp_state       = SMTP_STATE_READING_CMDS;
688               session_state->auth_state       = SMTP_AUTH_STATE_PLAIN_CRED_REQ;
689               session_state->first_auth_frame = pinfo->num;
690               session_state->user_pass_cmd_frame = pinfo->num;
691             } else if ((g_ascii_strncasecmp(line, "AUTH NTLM", 9) == 0) && (linelen > 10)) {
692               /*
693                * AUTH NTLM command with nlmssp request
694                */
695               spd_frame_data->pdu_type        = SMTP_PDU_CMD;
696               session_state->smtp_state       = SMTP_STATE_READING_CMDS;
697               session_state->auth_state       = SMTP_AUTH_STATE_NTLM_REQ;
698               session_state->ntlm_req_frame = pinfo->num;
699             } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) {
700               /*
701                * STARTTLS command.
702                * This is a command, but if the response is 220,
703                * everything after the response is TLS.
704                */
705               session_state->smtp_state = SMTP_STATE_AWAITING_STARTTLS_RESPONSE;
706               spd_frame_data->pdu_type = SMTP_PDU_CMD;
707             } else {
708               /*
709                * Regular command.
710                */
711               spd_frame_data->pdu_type = SMTP_PDU_CMD;
712             }
713           } else if (session_state->auth_state == SMTP_AUTH_STATE_USERNAME_REQ) {
714               session_state->auth_state = SMTP_AUTH_STATE_USERNAME_RSP;
715               session_state->username_frame = pinfo->num;
716           } else if (session_state->auth_state == SMTP_AUTH_STATE_PASSWORD_REQ) {
717               session_state->auth_state = SMTP_AUTH_STATE_PASSWORD_RSP;
718               session_state->password_frame = pinfo->num;
719           } else if (session_state->auth_state == SMTP_AUTH_STATE_PLAIN_REQ) {
720               session_state->auth_state = SMTP_AUTH_STATE_PLAIN_RSP;
721               session_state->user_pass_frame = pinfo->num;
722           } else if (session_state->auth_state == SMTP_AUTH_STATE_NTLM_CHALLANGE) {
723               session_state->auth_state = SMTP_AUTH_STATE_NTLM_RSP;
724               session_state->ntlm_rsp_frame = pinfo->num;
725           }
726           else {
727 
728             /*
729              * Assume it's message data.
730              */
731             spd_frame_data->pdu_type = (session_state->data_seen || (session_state->smtp_state == SMTP_STATE_START)) ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD;
732           }
733         }
734       }
735 
736       /*
737        * Step past this line.
738        */
739       loffset = next_offset;
740     }
741   }
742 
743 
744   /*
745    * From here, we simply add items to the tree and info to the info
746    * fields ...
747    */
748 
749   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP");
750   col_clear(pinfo->cinfo, COL_INFO);
751 
752   ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, ENC_NA);
753   smtp_tree = proto_item_add_subtree(ti, ett_smtp);
754 
755   if (request) {
756     /*
757      * Check out whether or not we can see a command in there ...
758      * What we are looking for is not data_seen and the word DATA
759      * and not eom_seen.
760      *
761      * We will see DATA and session_state->data_seen when we process the
762      * tree view after we have seen a DATA packet when processing
763      * the packet list pane.
764      *
765      * On the first pass, we will not have any info on the packets
766      * On second and subsequent passes, we will.
767      */
768     switch (spd_frame_data->pdu_type) {
769 
770     case SMTP_PDU_MESSAGE:
771       /* Column Info */
772       length_remaining = tvb_reported_length_remaining(tvb, offset);
773       col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body");
774       col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining,
775                         plurality (length_remaining, "", "s"));
776 
777       if (smtp_data_desegment) {
778         frag_msg = fragment_add_seq_next(&smtp_data_reassembly_table, tvb, 0,
779                                          pinfo, spd_frame_data->conversation_id, NULL,
780                                          tvb_reported_length(tvb),
781                                          spd_frame_data->more_frags);
782         /* Show the text lines within this PDU fragment */
783         call_dissector(data_text_lines_handle, tvb, pinfo, smtp_tree);
784       } else {
785         /*
786          * Message body.
787          * Put its lines into the protocol tree, a line at a time.
788          */
789         dissect_smtp_data(tvb, offset, smtp_tree);
790       }
791       break;
792 
793     case SMTP_PDU_EOM:
794       /*
795        * End-of-message-body indicator.
796        *
797        * XXX - what about stuff after the first line?
798        * Unlikely, as the client should wait for a response to the
799        * DATA command this terminates before sending another
800        * request, but we should probably handle it.
801        */
802       col_set_str(pinfo->cinfo, COL_INFO, "C: .");
803 
804       proto_tree_add_none_format(smtp_tree, hf_smtp_eom, tvb, offset, linelen, "C: .");
805 
806       if (smtp_data_desegment) {
807         /* add final data segment */
808         if (loffset)
809           fragment_add_seq_next(&smtp_data_reassembly_table, tvb, 0,
810                                 pinfo, spd_frame_data->conversation_id, NULL,
811                                 loffset, spd_frame_data->more_frags);
812 
813         /* terminate the desegmentation */
814         frag_msg = fragment_end_seq_next(&smtp_data_reassembly_table,
815                                          pinfo, spd_frame_data->conversation_id, NULL);
816       }
817       break;
818 
819     case SMTP_PDU_CMD:
820       /*
821        * Command.
822        *
823        * XXX - what about stuff after the first line?
824        * Unlikely, as the client should wait for a response to the
825        * previous command before sending another request, but we
826        * should probably handle it.
827        */
828 
829       loffset = offset;
830       while (tvb_offset_exists(tvb, loffset)) {
831         /*
832          * Find the end of the line.
833          */
834         linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
835 
836         /* Column Info */
837         if (loffset == offset)
838             col_append_str(pinfo->cinfo, COL_INFO, "C: ");
839         else
840             col_append_str(pinfo->cinfo, COL_INFO, " | ");
841 
842         hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb,
843                                              0, 0, TRUE);
844         proto_item_set_hidden(hidden_item);
845 
846         if (session_state->username_frame == pinfo->num) {
847           if (decrypt == NULL) {
848             /* This line wasn't already decrypted through the state machine */
849             decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
850             decrypt_len = linelen;
851             if (smtp_auth_parameter_decoding_enabled) {
852               if (strlen(decrypt) > 1) {
853                 g_base64_decode_inplace(decrypt, &decrypt_len);
854                 decrypt[decrypt_len] = 0;
855               } else {
856                 decrypt_len = 0;
857               }
858               if (decrypt_len == 0) {
859                 /* Go back to the original string */
860                 decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
861                 decrypt_len = linelen;
862               }
863             }
864           }
865 
866           if (!session_state->username)
867             session_state->username = wmem_strdup(wmem_file_scope(), decrypt);
868           proto_tree_add_string(smtp_tree, hf_smtp_username, tvb,
869                                 loffset, linelen, decrypt);
870           col_append_fstr(pinfo->cinfo, COL_INFO, "User: %s", format_text(pinfo->pool, decrypt, decrypt_len));
871         } else if (session_state->password_frame == pinfo->num) {
872           if (decrypt == NULL) {
873             /* This line wasn't already decrypted through the state machine */
874             decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
875             decrypt_len = linelen;
876             if (smtp_auth_parameter_decoding_enabled) {
877               if (strlen(decrypt) > 1) {
878                 g_base64_decode_inplace(decrypt, &decrypt_len);
879                 decrypt[decrypt_len] = 0;
880               } else {
881                 decrypt_len = 0;
882               }
883               if (decrypt_len == 0) {
884                 /* Go back to the original string */
885                 decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
886                 decrypt_len = linelen;
887               }
888             }
889           }
890           proto_tree_add_string(smtp_tree, hf_smtp_password, tvb,
891                                 loffset, linelen, decrypt);
892           col_append_fstr(pinfo->cinfo, COL_INFO, "Pass: %s", format_text(pinfo->pool, decrypt, decrypt_len));
893 
894           tap_credential_t* auth = wmem_new0(pinfo->pool, tap_credential_t);
895           auth->num = pinfo->num;
896           auth->username_num = session_state->username_frame;
897           auth->password_hf_id = hf_smtp_password;
898           auth->username = session_state->username;
899           auth->proto = "SMTP";
900           auth->info = wmem_strdup_printf(pinfo->pool, "Username in packet %u", auth->username_num);
901           tap_queue_packet(credentials_tap, pinfo, auth);
902         } else if (session_state->ntlm_rsp_frame == pinfo->num) {
903           decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
904           decrypt_len = linelen;
905           if (smtp_auth_parameter_decoding_enabled) {
906             if (strlen(decrypt) > 1) {
907               g_base64_decode_inplace(decrypt, &decrypt_len);
908               decrypt[decrypt_len] = 0;
909             } else {
910               decrypt_len = 0;
911             }
912             if (decrypt_len == 0) {
913               /* Go back to the original string */
914               decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
915               decrypt_len = linelen;
916               col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, decrypt, linelen));
917               proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb,
918                                   loffset, linelen, ENC_ASCII|ENC_NA);
919             }
920             else {
921               base64_string = tvb_get_string_enc(pinfo->pool, tvb, loffset, linelen, ENC_ASCII);
922               dissect_ntlm_auth(tvb, pinfo, smtp_tree, base64_string);
923             }
924           }
925           else {
926             col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, decrypt, linelen));
927             proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb,
928                                 loffset, linelen, ENC_ASCII|ENC_NA);
929           }
930         } else if (session_state->user_pass_frame == pinfo->num) {
931           decode_plain_auth(tvb, pinfo, smtp_tree, loffset, linelen);
932         } else {
933 
934           if (linelen >= 4)
935             cmdlen = 4;
936           else
937             cmdlen = linelen;
938 
939           /*
940            * Put the command line into the protocol tree.
941            */
942           ti =  proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb,
943                           loffset, next_offset - loffset, ENC_ASCII|ENC_NA);
944           cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
945 
946           proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
947                             loffset, cmdlen, ENC_ASCII|ENC_NA);
948 
949           if ((linelen > 5) && (session_state->username_cmd_frame == pinfo->num) ) {
950             proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
951                               loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
952 
953             if (linelen >= 11) {
954               if (decrypt == NULL) {
955                 /* This line wasn't already decrypted through the state machine */
956                  decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset + 11, linelen - 11, ENC_ASCII);
957                  decrypt_len = linelen - 11;
958                  if (smtp_auth_parameter_decoding_enabled) {
959                    if (strlen(decrypt) > 1) {
960                      g_base64_decode_inplace(decrypt, &decrypt_len);
961                      decrypt[decrypt_len] = 0;
962                    } else {
963                      decrypt_len = 0;
964                    }
965                    if (decrypt_len == 0) {
966                      /* Go back to the original string */
967                      decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset + 11, linelen - 11, ENC_ASCII);
968                      decrypt_len = linelen - 11;
969                    }
970                  }
971               }
972               proto_tree_add_string(cmdresp_tree, hf_smtp_username, tvb, loffset + 11, linelen - 11, decrypt);
973               col_append_str(pinfo->cinfo, COL_INFO,
974                              tvb_format_text(pinfo->pool, tvb, loffset, 11));
975               col_append_fstr(pinfo->cinfo, COL_INFO, "User: %s", format_text(pinfo->pool, decrypt, decrypt_len));
976             }
977           }
978           else if ((linelen > 5) && (session_state->ntlm_req_frame == pinfo->num) ) {
979             proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
980                               loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
981             if (linelen >= 10) {
982               decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset + 10, linelen - 10, ENC_ASCII);
983               decrypt_len = linelen - 10;
984               if (smtp_auth_parameter_decoding_enabled) {
985                 if (strlen(decrypt) > 1) {
986                   g_base64_decode_inplace(decrypt, &decrypt_len);
987                   decrypt[decrypt_len] = 0;
988                 } else {
989                   decrypt_len = 0;
990                 }
991                 if (decrypt_len == 0) {
992                   /* Go back to the original string */
993                   decrypt = tvb_get_string_enc(pinfo->pool, tvb, loffset + 10, linelen - 10, ENC_ASCII);
994                   decrypt_len = linelen - 10;
995                   col_append_str(pinfo->cinfo, COL_INFO,
996                                  tvb_format_text(pinfo->pool, tvb, loffset, 10));
997                   col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, decrypt, linelen - 10));
998                 }
999                 else {
1000                   base64_string = tvb_get_string_enc(pinfo->pool, tvb, loffset + 10, linelen - 10, ENC_ASCII);
1001                   col_append_str(pinfo->cinfo, COL_INFO,
1002                                  tvb_format_text(pinfo->pool, tvb, loffset, 10));
1003                   dissect_ntlm_auth(tvb, pinfo, cmdresp_tree, format_text(pinfo->pool, base64_string, linelen - 10));
1004                 }
1005               }
1006               else {
1007                 col_append_str(pinfo->cinfo, COL_INFO,
1008                                tvb_format_text(pinfo->pool, tvb, loffset, 10));
1009                 col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, decrypt, linelen - 10));
1010               }
1011             }
1012           }
1013           else if ((linelen > 5) && (session_state->user_pass_cmd_frame == pinfo->num) ) {
1014             proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
1015                               loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
1016             col_append_str(pinfo->cinfo, COL_INFO,
1017                            tvb_format_text(pinfo->pool, tvb, loffset, 11));
1018             decode_plain_auth(tvb, pinfo, cmdresp_tree, loffset + 11, linelen - 11);
1019           }
1020           else if (linelen > 5) {
1021             proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
1022                               loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
1023             col_append_str(pinfo->cinfo, COL_INFO,
1024                            tvb_format_text(pinfo->pool, tvb, loffset, linelen));
1025           }
1026           else {
1027             col_append_str(pinfo->cinfo, COL_INFO,
1028                            tvb_format_text(pinfo->pool, tvb, loffset, linelen));
1029           }
1030 
1031           if (smtp_data_desegment && !spd_frame_data->more_frags) {
1032             /* terminate the desegmentation */
1033             frag_msg = fragment_end_seq_next(&smtp_data_reassembly_table,
1034                                              pinfo, spd_frame_data->conversation_id, NULL);
1035           }
1036         }
1037         /*
1038          * Step past this line.
1039          */
1040         loffset = next_offset;
1041       }
1042     }
1043 
1044     if (smtp_data_desegment) {
1045       next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled SMTP",
1046                                           frag_msg, &smtp_data_frag_items, NULL, smtp_tree);
1047       if (next_tvb) {
1048         /* XXX: this is presumptuous - we may have negotiated something else */
1049         if (imf_handle) {
1050           call_dissector(imf_handle, next_tvb, pinfo, tree);
1051         } else {
1052           /*
1053            * Message body.
1054            * Put its lines into the protocol tree, a line at a time.
1055            */
1056           dissect_smtp_data(tvb, offset, smtp_tree);
1057         }
1058 
1059         pinfo->fragmented = FALSE;
1060       } else {
1061         pinfo->fragmented = TRUE;
1062       }
1063     }
1064   } else {
1065     /*
1066      * Process the response, a line at a time, until we hit a line
1067      * that doesn't have a continuation indication on it.
1068      */
1069     hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb, 0, 0, TRUE);
1070     proto_item_set_hidden(hidden_item);
1071 
1072     loffset = offset;
1073 
1074     //Multiline information
1075     smtp_multiline_state_t multiline_state = SMTP_MULTILINE_NONE;
1076     guint32 multiline_code = 0;
1077     proto_item* code_item = NULL;
1078 
1079     while (tvb_offset_exists(tvb, offset)) {
1080       /*
1081        * Find the end of the line.
1082        */
1083       linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1084 
1085       if (loffset == offset)
1086           col_append_str(pinfo->cinfo, COL_INFO, "S: ");
1087       else
1088           col_append_str(pinfo->cinfo, COL_INFO, " | ");
1089 
1090       if (linelen >= 3) {
1091           line_code[0] = tvb_get_guint8(tvb, offset);
1092           line_code[1] = tvb_get_guint8(tvb, offset+1);
1093           line_code[2] = tvb_get_guint8(tvb, offset+2);
1094           if (g_ascii_isdigit(line_code[0]) && g_ascii_isdigit(line_code[1])
1095               && g_ascii_isdigit(line_code[2])) {
1096             /*
1097              * We have a 3-digit response code.
1098              */
1099             code = (line_code[0] - '0')*100 + (line_code[1] - '0')*10 + (line_code[2] - '0');
1100             if ((linelen > 3) && (tvb_get_guint8(tvb, offset + 3) == '-')) {
1101               if (multiline_state == SMTP_MULTILINE_NONE) {
1102                 multiline_state = SMTP_MULTILINE_START;
1103                 multiline_code = code;
1104               } else {
1105                 multiline_state = SMTP_MULTILINE_CONTINUE;
1106               }
1107             } else if ((multiline_state == SMTP_MULTILINE_START) || (multiline_state == SMTP_MULTILINE_CONTINUE)) {
1108               multiline_state = SMTP_MULTILINE_END;
1109             }
1110 
1111             /*
1112              * If we're awaiting the response to a STARTTLS code, this
1113              * is it - if it's 220, all subsequent traffic will
1114              * be TLS, otherwise we're back to boring old SMTP.
1115              */
1116             if (session_state->smtp_state == SMTP_STATE_AWAITING_STARTTLS_RESPONSE) {
1117               if (code == 220) {
1118                 /* This is the last non-TLS frame. */
1119                 ssl_starttls_ack(tls_handle, pinfo, smtp_handle);
1120               }
1121               session_state->smtp_state =  SMTP_STATE_READING_CMDS;
1122             }
1123 
1124             if (code == 334) {
1125                 switch(session_state->auth_state)
1126                 {
1127                 case SMTP_AUTH_STATE_START:
1128                     session_state->auth_state = SMTP_AUTH_STATE_USERNAME_REQ;
1129                     break;
1130                 case SMTP_AUTH_STATE_USERNAME_RSP:
1131                     session_state->auth_state = SMTP_AUTH_STATE_PASSWORD_REQ;
1132                     break;
1133                 case SMTP_AUTH_STATE_PLAIN_REQ:
1134                     session_state->auth_state = SMTP_AUTH_STATE_PLAIN_RSP;
1135                     break;
1136                 case SMTP_AUTH_STATE_PLAIN_START_REQ:
1137                     session_state->auth_state = SMTP_AUTH_STATE_PLAIN_REQ;
1138                     break;
1139                 case SMTP_AUTH_STATE_NTLM_REQ:
1140                     session_state->auth_state = SMTP_AUTH_STATE_NTLM_CHALLANGE;
1141                     break;
1142                 case SMTP_AUTH_STATE_NONE:
1143                 case SMTP_AUTH_STATE_USERNAME_REQ:
1144                 case SMTP_AUTH_STATE_PASSWORD_REQ:
1145                 case SMTP_AUTH_STATE_PASSWORD_RSP:
1146                 case SMTP_AUTH_STATE_PLAIN_RSP:
1147                 case SMTP_AUTH_STATE_PLAIN_CRED_REQ:
1148                 case SMTP_AUTH_STATE_NTLM_RSP:
1149                 case SMTP_AUTH_STATE_NTLM_CHALLANGE:
1150                 case SMTP_AUTH_STATE_SUCCESS:
1151                 case SMTP_AUTH_STATE_FAILED:
1152                     /* ignore */
1153                     break;
1154                 }
1155             } else if ((session_state->auth_state == SMTP_AUTH_STATE_PASSWORD_RSP) ||
1156                        ( session_state->auth_state == SMTP_AUTH_STATE_PLAIN_RSP) ||
1157                        ( session_state->auth_state == SMTP_AUTH_STATE_NTLM_RSP) ||
1158                        ( session_state->auth_state == SMTP_AUTH_STATE_PLAIN_CRED_REQ) ) {
1159                 if (code == 235) {
1160                   session_state->auth_state = SMTP_AUTH_STATE_SUCCESS;
1161                 } else {
1162                   session_state->auth_state = SMTP_AUTH_STATE_FAILED;
1163                 }
1164                 session_state->last_auth_frame = pinfo->num;
1165             }
1166 
1167             /*
1168              * Put the response code and parameters into the protocol tree.
1169              * Only create a new response tree when not in the middle of multiline response.
1170              */
1171             if ((multiline_state != SMTP_MULTILINE_CONTINUE) &&
1172                 (multiline_state != SMTP_MULTILINE_END))
1173             {
1174               ti = proto_tree_add_item(smtp_tree, hf_smtp_response, tvb,
1175                 offset, next_offset - offset, ENC_ASCII | ENC_NA);
1176               cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
1177 
1178               code_item = proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3, code);
1179             } else if (multiline_code != code) {
1180               expert_add_info_format(pinfo, code_item, &ei_smtp_rsp_code, "Unexpected response code %u in multiline response. Expected %u", code, multiline_code);
1181             }
1182 
1183             decrypt = NULL;
1184             if (linelen >= 4) {
1185                 if ((smtp_auth_parameter_decoding_enabled) && (code == 334)) {
1186                     decrypt = tvb_get_string_enc(pinfo->pool, tvb, offset + 4, linelen - 4, ENC_ASCII);
1187                     if (strlen(decrypt) > 1 && (g_base64_decode_inplace(decrypt, &decrypt_len)) && decrypt_len > 0) {
1188                       decrypt[decrypt_len] = 0;
1189                       if (g_ascii_strncasecmp(decrypt, "NTLMSSP", 7) == 0) {
1190                         base64_string = tvb_get_string_enc(pinfo->pool, tvb, loffset + 4, linelen - 4, ENC_ASCII);
1191                         col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", code);
1192                         proto_tree_add_string(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
1193                                           offset + 4, linelen - 4, (const char*)base64_string);
1194                         dissect_ntlm_auth(tvb, pinfo, cmdresp_tree, base64_string);
1195                       }
1196                       else {
1197                         proto_tree_add_string(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
1198                                           offset + 4, linelen - 4, (const char*)decrypt);
1199 
1200                         col_append_fstr(pinfo->cinfo, COL_INFO, "%d %s", code, format_text(pinfo->pool, decrypt, decrypt_len));
1201                       }
1202                     } else {
1203                       decrypt = NULL;
1204                     }
1205                 }
1206 
1207                 if (decrypt == NULL) {
1208                     proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
1209                                       offset + 4, linelen - 4, ENC_ASCII|ENC_NA);
1210 
1211                     if ((multiline_state != SMTP_MULTILINE_CONTINUE) &&
1212                         (multiline_state != SMTP_MULTILINE_END)) {
1213                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1214                                     tvb_format_text(pinfo->pool, tvb, offset, linelen));
1215                     } else {
1216                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1217                         tvb_format_text(pinfo->pool, tvb, offset+4, linelen-4));
1218                     }
1219                 }
1220             } else {
1221                col_append_str(pinfo->cinfo, COL_INFO,
1222                               tvb_format_text(pinfo->pool, tvb, offset, linelen));
1223             }
1224           }
1225 
1226           //Clear multiline state if this is the last line
1227           if (multiline_state == SMTP_MULTILINE_END)
1228             multiline_state = SMTP_MULTILINE_NONE;
1229       }
1230       /*
1231        * Step past this line.
1232        */
1233       offset = next_offset;
1234 
1235     }
1236   }
1237 
1238   return tvb_captured_length(tvb);
1239 }
1240 
1241 
1242 /* Register all the bits needed by the filtering engine */
1243 
1244 void
proto_register_smtp(void)1245 proto_register_smtp(void)
1246 {
1247   static hf_register_info hf[] = {
1248     { &hf_smtp_req,
1249       { "Request", "smtp.req",
1250         FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1251 
1252     { &hf_smtp_rsp,
1253       { "Response", "smtp.rsp",
1254         FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1255 
1256     { &hf_smtp_message,
1257       { "Message", "smtp.message",
1258         FT_STRING,  BASE_NONE, NULL, 0x0, NULL, HFILL }},
1259 
1260     { &hf_smtp_command_line,
1261       { "Command Line", "smtp.command_line",
1262         FT_STRING,  BASE_NONE, NULL, 0x0, NULL, HFILL }},
1263 
1264     { &hf_smtp_req_command,
1265       { "Command", "smtp.req.command",
1266         FT_STRING,  BASE_NONE, NULL, 0x0, NULL, HFILL }},
1267 
1268     { &hf_smtp_req_parameter,
1269       { "Request parameter", "smtp.req.parameter",
1270         FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1271 
1272     { &hf_smtp_response,
1273       { "Response", "smtp.response",
1274         FT_STRING,  BASE_NONE, NULL, 0x0, NULL, HFILL }},
1275 
1276     { &hf_smtp_rsp_code,
1277       { "Response code", "smtp.response.code",
1278         FT_UINT32, BASE_DEC|BASE_EXT_STRING, &response_codes_vs_ext, 0x0, NULL, HFILL }},
1279 
1280     { &hf_smtp_rsp_parameter,
1281       { "Response parameter", "smtp.rsp.parameter",
1282         FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1283 
1284     { &hf_smtp_username,
1285       { "Username", "smtp.auth.username",
1286         FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1287 
1288     { &hf_smtp_password,
1289       { "Password", "smtp.auth.password",
1290         FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1291 
1292     { &hf_smtp_username_password,
1293       { "Username/Password", "smtp.auth.username_password",
1294         FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1295 
1296     { &hf_smtp_eom,
1297       { "EOM", "smtp.eom",
1298         FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1299 
1300     /* Fragment entries */
1301     { &hf_smtp_data_fragments,
1302       { "DATA fragments", "smtp.data.fragments",
1303         FT_NONE, BASE_NONE, NULL, 0x00, "Message fragments", HFILL } },
1304 
1305     { &hf_smtp_data_fragment,
1306       { "DATA fragment", "smtp.data.fragment",
1307         FT_FRAMENUM, BASE_NONE, NULL, 0x00, "Message fragment", HFILL } },
1308 
1309     { &hf_smtp_data_fragment_overlap,
1310       { "DATA fragment overlap", "smtp.data.fragment.overlap", FT_BOOLEAN,
1311         BASE_NONE, NULL, 0x0, "Message fragment overlap", HFILL } },
1312 
1313     { &hf_smtp_data_fragment_overlap_conflicts,
1314       { "DATA fragment overlapping with conflicting data",
1315         "smtp.data.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL,
1316         0x0, "Message fragment overlapping with conflicting data", HFILL } },
1317 
1318     { &hf_smtp_data_fragment_multiple_tails,
1319       { "DATA has multiple tail fragments", "smtp.data.fragment.multiple_tails",
1320         FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Message has multiple tail fragments", HFILL } },
1321 
1322     { &hf_smtp_data_fragment_too_long_fragment,
1323       { "DATA fragment too long", "smtp.data.fragment.too_long_fragment",
1324         FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Message fragment too long", HFILL } },
1325 
1326     { &hf_smtp_data_fragment_error,
1327       { "DATA defragmentation error", "smtp.data.fragment.error",
1328         FT_FRAMENUM, BASE_NONE, NULL, 0x00, "Message defragmentation error", HFILL } },
1329 
1330     { &hf_smtp_data_fragment_count,
1331       { "DATA fragment count", "smtp.data.fragment.count",
1332         FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
1333 
1334     { &hf_smtp_data_reassembled_in,
1335       { "Reassembled DATA in frame", "smtp.data.reassembled.in",
1336         FT_FRAMENUM, BASE_NONE, NULL, 0x00, "This DATA fragment is reassembled in this frame", HFILL } },
1337 
1338     { &hf_smtp_data_reassembled_length,
1339       { "Reassembled DATA length", "smtp.data.reassembled.length",
1340         FT_UINT32, BASE_DEC, NULL, 0x00, "The total length of the reassembled payload", HFILL } },
1341   };
1342   static gint *ett[] = {
1343     &ett_smtp,
1344     &ett_smtp_cmdresp,
1345     &ett_smtp_data_fragment,
1346     &ett_smtp_data_fragments,
1347 
1348   };
1349 
1350   static ei_register_info ei[] = {
1351     { &ei_smtp_base64_decode, { "smtp.base64_decode", PI_PROTOCOL, PI_WARN, "base64 decode failed or is not enabled (check SMTP preferences)", EXPFILL }},
1352     { &ei_smtp_rsp_code,{ "smtp.response.code.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected response code in multiline response", EXPFILL } },
1353   };
1354 
1355   module_t *smtp_module;
1356   expert_module_t* expert_smtp;
1357 
1358   proto_smtp = proto_register_protocol("Simple Mail Transfer Protocol",
1359                                        "SMTP", "smtp");
1360 
1361   proto_register_field_array(proto_smtp, hf, array_length(hf));
1362   proto_register_subtree_array(ett, array_length(ett));
1363   expert_smtp = expert_register_protocol(proto_smtp);
1364   expert_register_field_array(expert_smtp, ei, array_length(ei));
1365   reassembly_table_register(&smtp_data_reassembly_table,
1366                         &addresses_ports_reassembly_table_functions);
1367 
1368   /* Allow dissector to find be found by name. */
1369   smtp_handle = register_dissector("smtp", dissect_smtp, proto_smtp);
1370 
1371   /* Preferences */
1372   smtp_module = prefs_register_protocol(proto_smtp, NULL);
1373   prefs_register_bool_preference(smtp_module, "desegment_lines",
1374                                  "Reassemble SMTP command and response lines spanning multiple TCP segments",
1375                                  "Whether the SMTP dissector should reassemble command and response lines"
1376                                  " spanning multiple TCP segments. To use this option, you must also enable "
1377                                  "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1378                                  &smtp_desegment);
1379 
1380   prefs_register_bool_preference(smtp_module, "desegment_data",
1381                                  "Reassemble SMTP DATA commands spanning multiple TCP segments",
1382                                  "Whether the SMTP dissector should reassemble DATA command and lines"
1383                                  " spanning multiple TCP segments. To use this option, you must also enable "
1384                                  "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1385                                  &smtp_data_desegment);
1386 
1387   prefs_register_bool_preference(smtp_module, "decryption",
1388                                  "Decode Base64 encoded AUTH parameters",
1389                                  "Whether the SMTP dissector should decode Base64 encoded AUTH parameters",
1390                                  &smtp_auth_parameter_decoding_enabled);
1391 
1392   credentials_tap = register_tap("credentials"); /* credentials tap */
1393 }
1394 
1395 /* The registration hand-off routine */
1396 void
proto_reg_handoff_smtp(void)1397 proto_reg_handoff_smtp(void)
1398 {
1399   dissector_add_uint_range_with_preference("tcp.port", TCP_PORT_SMTP, smtp_handle);
1400   ssl_dissector_add(TCP_PORT_SSL_SMTP, smtp_handle);
1401   /* No "auto" preference since handle is shared with SMTP */
1402   dissector_add_uint("tcp.port", TCP_PORT_SUBMISSION, smtp_handle);
1403 
1404   /* find the IMF dissector */
1405   imf_handle = find_dissector_add_dependency("imf", proto_smtp);
1406 
1407   /* find the TLS dissector */
1408   tls_handle = find_dissector_add_dependency("tls", proto_smtp);
1409 
1410   /* find the NTLM dissector */
1411   ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_smtp);
1412 
1413   /* find the data-text-lines dissector */
1414   data_text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_smtp);
1415 }
1416 
1417 /*
1418  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1419  *
1420  * Local variables:
1421  * c-basic-offset: 2
1422  * tab-width: 8
1423  * indent-tabs-mode: nil
1424  * End:
1425  *
1426  * vi: set shiftwidth=2 tabstop=8 expandtab:
1427  * :indentSize=2:tabSize=8:noTabs=true
1428  */
1429