]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-smtp.c
detect file: cleanups
[people/ms/suricata.git] / src / app-layer-smtp.c
CommitLineData
7fa22e84 1/* Copyright (C) 2007-2012 Open Information Security Foundation
576ec7da
AS
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
420befb1 21 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
576ec7da
AS
22 */
23
24#include "suricata.h"
25#include "suricata-common.h"
26#include "debug.h"
27#include "decode.h"
28#include "threads.h"
29
30#include "stream-tcp-private.h"
31#include "stream-tcp-reassemble.h"
32#include "stream-tcp.h"
33#include "stream.h"
34
429c6388
AS
35#include "app-layer.h"
36#include "app-layer-detect-proto.h"
576ec7da
AS
37#include "app-layer-protos.h"
38#include "app-layer-parser.h"
39#include "app-layer-smtp.h"
40
a49cbf8a 41#include "util-mpm.h"
576ec7da
AS
42#include "util-debug.h"
43#include "util-byte.h"
44#include "util-unittest.h"
576ec7da
AS
45#include "util-unittest-helper.h"
46#include "util-memcmp.h"
47#include "flow-util.h"
48
49#include "detect-engine.h"
50#include "detect-engine-state.h"
51#include "detect-parse.h"
52
5311cd48 53#include "decode-events.h"
5e2d9dbd 54#include "conf.h"
576ec7da 55
56b74c8b 56#include "util-mem.h"
26ba647d
GL
57#include "util-misc.h"
58
59/* content-limit default value */
4526aed2 60#define FILEDATA_CONTENT_LIMIT 100000
26ba647d 61/* content-inspect-min-size default value */
4526aed2 62#define FILEDATA_CONTENT_INSPECT_MIN_SIZE 32768
26ba647d 63/* content-inspect-window default value */
4526aed2 64#define FILEDATA_CONTENT_INSPECT_WINDOW 4096
56b74c8b 65
576ec7da
AS
66#define SMTP_MAX_REQUEST_AND_REPLY_LINE_LENGTH 510
67
68#define SMTP_COMMAND_BUFFER_STEPS 5
69
70/* we are in process of parsing a fresh command. Just a placeholder. If we
71 * are not in STATE_COMMAND_DATA_MODE, we have to be in this mode */
72#define SMTP_PARSER_STATE_COMMAND_MODE 0x00
73/* we are in mode of parsing a command's data. Used when we are parsing tls
74 * or accepting the rfc 2822 mail after DATA command */
75#define SMTP_PARSER_STATE_COMMAND_DATA_MODE 0x01
76/* Used when we are still in the process of parsing a server command. Used
77 * with multi-line replies and the stream is fragmented before all the lines
78 * for a response is seen */
79#define SMTP_PARSER_STATE_PARSING_SERVER_RESPONSE 0x02
80/* Used to indicate that the parser has seen the first reply */
81#define SMTP_PARSER_STATE_FIRST_REPLY_SEEN 0x04
82/* Used to indicate that the parser is parsing a multiline reply */
83#define SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY 0x08
84
85/* Various SMTP commands
86 * We currently have var-ified just STARTTLS and DATA, since we need to them
87 * for state transitions. The rest are just indicate as OTHER_CMD. Other
88 * commands would be introduced as and when needed */
89#define SMTP_COMMAND_STARTTLS 1
90#define SMTP_COMMAND_DATA 2
d3ca65de 91#define SMTP_COMMAND_BDAT 3
576ec7da
AS
92/* not an actual command per se, but the mode where we accept the mail after
93 * DATA has it's own reply code for completion, from the server. We give this
94 * stage a pseudo command of it's own, so that we can add this to the command
95 * buffer to match with the reply */
d3ca65de 96#define SMTP_COMMAND_DATA_MODE 4
576ec7da 97/* All other commands are represented by this var */
d3ca65de 98#define SMTP_COMMAND_OTHER_CMD 5
576ec7da
AS
99
100/* Different EHLO extensions. Not used now. */
101#define SMTP_EHLO_EXTENSION_PIPELINING
102#define SMTP_EHLO_EXTENSION_SIZE
103#define SMTP_EHLO_EXTENSION_DSN
104#define SMTP_EHLO_EXTENSION_STARTTLS
105#define SMTP_EHLO_EXTENSION_8BITMIME
106
5311cd48
AS
107SCEnumCharMap smtp_decoder_event_table[ ] = {
108 { "INVALID_REPLY", SMTP_DECODER_EVENT_INVALID_REPLY },
109 { "UNABLE_TO_MATCH_REPLY_WITH_REQUEST",
110 SMTP_DECODER_EVENT_UNABLE_TO_MATCH_REPLY_WITH_REQUEST },
111 { "MAX_COMMAND_LINE_LEN_EXCEEDED",
112 SMTP_DECODER_EVENT_MAX_COMMAND_LINE_LEN_EXCEEDED },
113 { "MAX_REPLY_LINE_LEN_EXCEEDED",
114 SMTP_DECODER_EVENT_MAX_REPLY_LINE_LEN_EXCEEDED },
115 { "INVALID_PIPELINED_SEQUENCE",
116 SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE },
117 { "BDAT_CHUNK_LEN_EXCEEDED",
118 SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED },
119 { "NO_SERVER_WELCOME_MESSAGE",
120 SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE },
121 { "TLS_REJECTED",
122 SMTP_DECODER_EVENT_TLS_REJECTED },
123 { "DATA_COMMAND_REJECTED",
124 SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED },
c2dc6867
DA
125
126 /* MIME Events */
127 { "MIME_PARSE_FAILED",
128 SMTP_DECODER_EVENT_MIME_PARSE_FAILED },
129 { "MIME_MALFORMED_MSG",
130 SMTP_DECODER_EVENT_MIME_MALFORMED_MSG },
131 { "MIME_INVALID_BASE64",
132 SMTP_DECODER_EVENT_MIME_INVALID_BASE64 },
133 { "MIME_INVALID_QP",
134 SMTP_DECODER_EVENT_MIME_INVALID_QP },
135 { "MIME_LONG_LINE",
136 SMTP_DECODER_EVENT_MIME_LONG_LINE },
137 { "MIME_LONG_ENC_LINE",
138 SMTP_DECODER_EVENT_MIME_LONG_ENC_LINE },
139 { "MIME_LONG_HEADER_NAME",
140 SMTP_DECODER_EVENT_MIME_LONG_HEADER_NAME },
141 { "MIME_LONG_HEADER_VALUE",
142 SMTP_DECODER_EVENT_MIME_LONG_HEADER_VALUE },
6d170cad
VJ
143 { "MIME_LONG_BOUNDARY",
144 SMTP_DECODER_EVENT_MIME_BOUNDARY_TOO_LONG },
c2dc6867 145
10e2e2a8
EL
146 /* Invalid behavior or content */
147 { "DUPLICATE_FIELDS",
148 SMTP_DECODER_EVENT_DUPLICATE_FIELDS },
5dbedbfa
EL
149 { "UNPARSABLE_CONTENT",
150 SMTP_DECODER_EVENT_UNPARSABLE_CONTENT },
10e2e2a8 151
5311cd48
AS
152 { NULL, -1 },
153};
4d38a571 154
e05034f5 155#define SMTP_MPM DEFAULT_MPM
4d38a571
AS
156
157static MpmCtx *smtp_mpm_ctx = NULL;
158MpmThreadCtx *smtp_mpm_thread_ctx;
159
160/* smtp reply codes. If an entry is made here, please make a simultaneous
161 * entry in smtp_reply_map */
162enum {
163 SMTP_REPLY_211,
164 SMTP_REPLY_214,
165 SMTP_REPLY_220,
166 SMTP_REPLY_221,
7850d896 167 SMTP_REPLY_235,
4d38a571
AS
168 SMTP_REPLY_250,
169 SMTP_REPLY_251,
170 SMTP_REPLY_252,
171
7850d896 172 SMTP_REPLY_334,
4d38a571
AS
173 SMTP_REPLY_354,
174
175 SMTP_REPLY_421,
176 SMTP_REPLY_450,
177 SMTP_REPLY_451,
178 SMTP_REPLY_452,
179 SMTP_REPLY_455,
180
181 SMTP_REPLY_500,
182 SMTP_REPLY_501,
183 SMTP_REPLY_502,
184 SMTP_REPLY_503,
185 SMTP_REPLY_504,
186 SMTP_REPLY_550,
187 SMTP_REPLY_551,
188 SMTP_REPLY_552,
189 SMTP_REPLY_553,
190 SMTP_REPLY_554,
191 SMTP_REPLY_555,
192};
193
194SCEnumCharMap smtp_reply_map[ ] = {
195 { "211", SMTP_REPLY_211 },
196 { "214", SMTP_REPLY_214 },
197 { "220", SMTP_REPLY_220 },
198 { "221", SMTP_REPLY_221 },
7850d896 199 { "235", SMTP_REPLY_235 },
4d38a571
AS
200 { "250", SMTP_REPLY_250 },
201 { "251", SMTP_REPLY_251 },
202 { "252", SMTP_REPLY_252 },
203
7850d896 204 { "334", SMTP_REPLY_334 },
4d38a571
AS
205 { "354", SMTP_REPLY_354 },
206
207 { "421", SMTP_REPLY_421 },
208 { "450", SMTP_REPLY_450 },
209 { "451", SMTP_REPLY_451 },
210 { "452", SMTP_REPLY_452 },
211 { "455", SMTP_REPLY_455 },
212
213 { "500", SMTP_REPLY_500 },
214 { "501", SMTP_REPLY_501 },
215 { "502", SMTP_REPLY_502 },
216 { "503", SMTP_REPLY_503 },
217 { "504", SMTP_REPLY_504 },
218 { "550", SMTP_REPLY_550 },
219 { "551", SMTP_REPLY_551 },
220 { "552", SMTP_REPLY_552 },
221 { "553", SMTP_REPLY_553 },
222 { "554", SMTP_REPLY_554 },
223 { "555", SMTP_REPLY_555 },
224 { NULL, -1 },
225};
c2dc6867 226
c2dc6867 227/* Create SMTP config structure */
99005584 228SMTPConfig smtp_config = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 0};
c2dc6867 229
752fdba9
EL
230static SMTPString *SMTPStringAlloc(void);
231
c2dc6867 232/**
e5c36952 233 * \brief Configure SMTP Mime Decoder by parsing out mime section of YAML
c2dc6867
DA
234 * config file
235 *
236 * \return none
237 */
238static void SMTPConfigure(void) {
239
240 SCEnter();
241 int ret = 0, val;
242 intmax_t imval;
26ba647d
GL
243 uint32_t content_limit = 0;
244 uint32_t content_inspect_min_size = 0;
245 uint32_t content_inspect_window = 0;
c2dc6867 246
e5c36952 247 ConfNode *config = ConfGetNode("app-layer.protocols.smtp.mime");
c2dc6867
DA
248 if (config != NULL) {
249
250 ret = ConfGetChildValueBool(config, "decode-mime", &val);
251 if (ret) {
252 smtp_config.decode_mime = val;
253 }
254
255 ret = ConfGetChildValueBool(config, "decode-base64", &val);
256 if (ret) {
257 smtp_config.mime_config.decode_base64 = val;
258 }
259
260 ret = ConfGetChildValueBool(config, "decode-quoted-printable", &val);
261 if (ret) {
262 smtp_config.mime_config.decode_quoted_printable = val;
263 }
264
265 ret = ConfGetChildValueInt(config, "header-value-depth", &imval);
266 if (ret) {
267 smtp_config.mime_config.header_value_depth = (uint32_t) imval;
268 }
269
270 ret = ConfGetChildValueBool(config, "extract-urls", &val);
271 if (ret) {
272 smtp_config.mime_config.extract_urls = val;
273 }
99005584
EL
274
275 ret = ConfGetChildValueBool(config, "body-md5", &val);
276 if (ret) {
277 smtp_config.mime_config.body_md5 = val;
278 }
c2dc6867
DA
279 }
280
281 /* Pass mime config data to MimeDec API */
282 MimeDecSetConfig(&smtp_config.mime_config);
283
4526aed2
VJ
284 smtp_config.content_limit = FILEDATA_CONTENT_LIMIT;
285 smtp_config.content_inspect_window = FILEDATA_CONTENT_INSPECT_WINDOW;
286 smtp_config.content_inspect_min_size = FILEDATA_CONTENT_INSPECT_MIN_SIZE;
287
26ba647d
GL
288 ConfNode *t = ConfGetNode("app-layer.protocols.smtp.inspected-tracker");
289 ConfNode *p = NULL;
290
4526aed2
VJ
291 if (t != NULL) {
292 TAILQ_FOREACH(p, &t->head, next) {
293 if (strcasecmp("content-limit", p->name) == 0) {
294 if (ParseSizeStringU32(p->val, &content_limit) < 0) {
295 SCLogWarning(SC_ERR_SIZE_PARSE,
296 "parsing content-limit %s failed", p->val);
297 content_limit = FILEDATA_CONTENT_LIMIT;
298 }
299 smtp_config.content_limit = content_limit;
26ba647d 300 }
26ba647d 301
4526aed2
VJ
302 if (strcasecmp("content-inspect-min-size", p->name) == 0) {
303 if (ParseSizeStringU32(p->val, &content_inspect_min_size) < 0) {
304 SCLogWarning(SC_ERR_SIZE_PARSE,
305 "parsing content-inspect-min-size %s failed", p->val);
306 content_inspect_min_size = FILEDATA_CONTENT_INSPECT_MIN_SIZE;
307 }
308 smtp_config.content_inspect_min_size = content_inspect_min_size;
26ba647d 309 }
26ba647d 310
4526aed2
VJ
311 if (strcasecmp("content-inspect-window", p->name) == 0) {
312 if (ParseSizeStringU32(p->val, &content_inspect_window) < 0) {
313 SCLogWarning(SC_ERR_SIZE_PARSE,
314 "parsing content-inspect-window %s failed", p->val);
315 content_inspect_window = FILEDATA_CONTENT_INSPECT_WINDOW;
316 }
317 smtp_config.content_inspect_window = content_inspect_window;
26ba647d
GL
318 }
319 }
320 }
321
c2dc6867
DA
322 SCReturn;
323}
324
d209699a
VJ
325void SMTPSetEvent(SMTPState *s, uint8_t e)
326{
327 SCLogDebug("setting event %u", e);
328
329 if (s->curr_tx != NULL) {
330 AppLayerDecoderEventsSetEventRaw(&s->curr_tx->decoder_events, e);
331// s->events++;
332 return;
333 }
334 SCLogDebug("couldn't set event %u", e);
335}
336
56b74c8b
VJ
337static SMTPTransaction *SMTPTransactionCreate(void)
338{
339 SMTPTransaction *tx = SCCalloc(1, sizeof(*tx));
340 if (tx == NULL) {
341 return NULL;
342 }
343
752fdba9 344 TAILQ_INIT(&tx->rcpt_to_list);
56b74c8b
VJ
345 tx->mime_state = NULL;
346 return tx;
347}
348
9afaf14b
VJ
349/** \internal
350 * \brief update inspected tracker if it gets to far behind
351 *
352 * As smtp uses the FILE_USE_DETECT flag in the file API, we are responsible
353 * for making sure that File::content_inspected is not getting too far
354 * behind.
355 */
356static void SMTPPruneFiles(FileContainer *files)
357{
358 SCLogDebug("cfg: win %"PRIu32" min_size %"PRIu32,
359 smtp_config.content_inspect_window, smtp_config.content_inspect_min_size);
360
361 File *file = files->head;
362 while (file) {
363 if (file->chunks_head) {
364 uint32_t window = smtp_config.content_inspect_window;
365 if (file->chunks_head->stream_offset == 0)
366 window = MAX(window, smtp_config.content_inspect_min_size);
367
368 uint64_t file_size = file->content_len_so_far;
369 uint64_t data_size = file_size - file->chunks_head->stream_offset;
370
371 SCLogDebug("window %"PRIu32", file_size %"PRIu64", data_size %"PRIu64,
372 window, file_size, data_size);
373
374 if (data_size > (window * 3)) {
375 uint64_t left_edge = file_size - window;
376 SCLogDebug("file->content_inspected now %"PRIu64, left_edge);
377 file->content_inspected = left_edge;
378 }
379 }
c2dc6867 380
9afaf14b
VJ
381 file = file->next;
382 }
383}
384
aa4ad9d2
VJ
385static void FlagDetectStateNewFile(SMTPTransaction *tx)
386{
387 if (tx && tx->de_state) {
388 SCLogDebug("DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW set");
389 tx->de_state->dir_state[0].flags |= DETECT_ENGINE_STATE_FLAG_FILE_TS_NEW;
390 }
391}
392
9afaf14b
VJ
393int SMTPProcessDataChunk(const uint8_t *chunk, uint32_t len,
394 MimeDecParseState *state)
395{
396 SCEnter();
c2dc6867
DA
397 int ret = MIME_DEC_OK;
398 Flow *flow = (Flow *) state->data;
399 SMTPState *smtp_state = (SMTPState *) flow->alstate;
400 MimeDecEntity *entity = (MimeDecEntity *) state->stack->top->data;
401 FileContainer *files = NULL;
402 uint16_t flags = 0;
403
404 /* Set flags */
405 if (flow->flags & FLOW_FILE_NO_STORE_TS) {
406 flags |= FILE_NOSTORE;
407 }
408
409 if (flow->flags & FLOW_FILE_NO_MAGIC_TS) {
410 flags |= FILE_NOMAGIC;
411 }
412
413 if (flow->flags & FLOW_FILE_NO_MD5_TS) {
414 flags |= FILE_NOMD5;
415 }
416
c2dc6867
DA
417 /* Find file */
418 if (entity->ctnt_flags & CTNT_IS_ATTACHMENT) {
419
420 /* Make sure file container allocated */
421 if (smtp_state->files_ts == NULL) {
422 smtp_state->files_ts = FileContainerAlloc();
423 if (smtp_state->files_ts == NULL) {
424 ret = MIME_DEC_ERR_MEM;
425 SCLogError(SC_ERR_MEM_ALLOC, "Could not create file container");
e43eb76a 426 SCReturnInt(ret);
c2dc6867
DA
427 }
428 }
429 files = smtp_state->files_ts;
430
431 /* Open file if necessary */
432 if (state->body_begin) {
433
434 if (SCLogDebugEnabled()) {
435 SCLogDebug("Opening file...%u bytes", len);
436 printf("File - ");
437 for (uint32_t i = 0; i < entity->filename_len; i++) {
438 printf("%c", entity->filename[i]);
439 }
440 printf("\n");
441 }
442
443 /* Set storage flag if applicable since only the first file in the
444 * flow seems to be processed by the 'filestore' detector */
445 if (files->head != NULL && (files->head->flags & FILE_STORE)) {
446 flags |= FILE_STORE;
447 }
448
449 if (FileOpenFile(files, (uint8_t *) entity->filename, entity->filename_len,
9afaf14b 450 (uint8_t *) chunk, len, flags|FILE_USE_DETECT) == NULL) {
c2dc6867
DA
451 ret = MIME_DEC_ERR_DATA;
452 SCLogDebug("FileOpenFile() failed");
453 }
aa4ad9d2 454 FlagDetectStateNewFile(smtp_state->curr_tx);
c2dc6867
DA
455
456 /* If close in the same chunk, then pass in empty bytes */
457 if (state->body_end) {
458
459 SCLogDebug("Closing file...%u bytes", len);
460
461 if (files->tail->state == FILE_STATE_OPENED) {
462 ret = FileCloseFile(files, (uint8_t *) NULL, 0, flags);
463 if (ret != 0) {
464 SCLogDebug("FileCloseFile() failed: %d", ret);
9d33131d 465 ret = MIME_DEC_ERR_DATA;
c2dc6867
DA
466 }
467 } else {
468 SCLogDebug("File already closed");
469 }
470 }
471 } else if (state->body_end) {
472 /* Close file */
473 SCLogDebug("Closing file...%u bytes", len);
474
56b74c8b 475 if (files && files->tail && files->tail->state == FILE_STATE_OPENED) {
c2dc6867
DA
476 ret = FileCloseFile(files, (uint8_t *) chunk, len, flags);
477 if (ret != 0) {
478 SCLogDebug("FileCloseFile() failed: %d", ret);
9d33131d 479 ret = MIME_DEC_ERR_DATA;
c2dc6867
DA
480 }
481 } else {
482 SCLogDebug("File already closed");
483 }
484 } else {
485 /* Append data chunk to file */
486 SCLogDebug("Appending file...%u bytes", len);
487
488 /* 0 is ok, -2 is not stored, -1 is error */
489 ret = FileAppendData(files, (uint8_t *) chunk, len);
490 if (ret == -2) {
491 ret = 0;
492 SCLogDebug("FileAppendData() - file no longer being extracted");
493 } else if (ret < 0) {
494 SCLogDebug("FileAppendData() failed: %d", ret);
9d33131d 495 ret = MIME_DEC_ERR_DATA;
c2dc6867
DA
496 }
497 }
498
9d33131d 499 if (ret == 0) {
c2dc6867
DA
500 SCLogDebug("Successfully processed file data!");
501 }
502 } else {
503 SCLogDebug("Body not a Ctnt_attachment");
504 }
505
506 if (files != NULL) {
9afaf14b 507 SMTPPruneFiles(files);
c2dc6867
DA
508 FilePrune(files);
509 }
e43eb76a 510
c2dc6867
DA
511 SCReturnInt(ret);
512}
576ec7da
AS
513
514/**
515 * \internal
516 * \brief Get the next line from input. It doesn't do any length validation.
517 *
518 * \param state The smtp state.
519 *
520 * \retval 0 On suceess.
521 * \retval -1 Either when we don't have any new lines to supply anymore or
522 * on failure.
523 */
524static int SMTPGetLine(SMTPState *state)
525{
7b0f261f 526 SCEnter();
1f07d152 527 void *ptmp;
7b0f261f 528
88115902
AS
529 /* we have run out of input */
530 if (state->input_len <= 0)
576ec7da
AS
531 return -1;
532
88115902
AS
533 /* toserver */
534 if (state->direction == 0) {
535 if (state->ts_current_line_lf_seen == 1) {
536 /* we have seen the lf for the previous line. Clear the parser
537 * details to parse new line */
538 state->ts_current_line_lf_seen = 0;
539 if (state->ts_current_line_db == 1) {
540 state->ts_current_line_db = 0;
541 SCFree(state->ts_db);
542 state->ts_db = NULL;
4a6908d3 543 state->ts_db_len = 0;
88115902 544 state->current_line = NULL;
4a6908d3 545 state->current_line_len = 0;
88115902 546 }
576ec7da 547 }
576ec7da 548
88115902 549 uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
576ec7da 550
88115902 551 if (lf_idx == NULL) {
5311cd48
AS
552 /* fragmented lines. Decoder event for special cases. Not all
553 * fragmented lines should be treated as a possible evasion
554 * attempt. With multi payload smtp chunks we can have valid
555 * cases of fragmentation. But within the same segment chunk
556 * if we see fragmentation then it's definitely something you
557 * should alert about */
88115902 558 if (state->ts_current_line_db == 0) {
88115902
AS
559 state->ts_db = SCMalloc(state->input_len);
560 if (state->ts_db == NULL) {
561 return -1;
562 }
4a6908d3 563 state->ts_current_line_db = 1;
88115902
AS
564 memcpy(state->ts_db, state->input, state->input_len);
565 state->ts_db_len = state->input_len;
566 } else {
1f07d152
EL
567 ptmp = SCRealloc(state->ts_db,
568 (state->ts_db_len + state->input_len));
569 if (ptmp == NULL) {
570 SCFree(state->ts_db);
571 state->ts_db = NULL;
572 state->ts_db_len = 0;
88115902
AS
573 return -1;
574 }
1f07d152
EL
575 state->ts_db = ptmp;
576
88115902
AS
577 memcpy(state->ts_db + state->ts_db_len,
578 state->input, state->input_len);
579 state->ts_db_len += state->input_len;
580 } /* else */
581 state->input += state->input_len;
582 state->input_len = 0;
583
584 return -1;
4a6908d3 585
576ec7da 586 } else {
88115902
AS
587 state->ts_current_line_lf_seen = 1;
588
4a6908d3 589 if (state->ts_current_line_db == 1) {
1f07d152
EL
590 ptmp = SCRealloc(state->ts_db,
591 (state->ts_db_len + (lf_idx + 1 - state->input)));
592 if (ptmp == NULL) {
593 SCFree(state->ts_db);
594 state->ts_db = NULL;
595 state->ts_db_len = 0;
4a6908d3
AS
596 return -1;
597 }
1f07d152
EL
598 state->ts_db = ptmp;
599
4a6908d3
AS
600 memcpy(state->ts_db + state->ts_db_len,
601 state->input, (lf_idx + 1 - state->input));
602 state->ts_db_len += (lf_idx + 1 - state->input);
603
604 if (state->ts_db_len > 1 &&
605 state->ts_db[state->ts_db_len - 2] == 0x0D) {
606 state->ts_db_len -= 2;
607 state->current_line_delimiter_len = 2;
88115902 608 } else {
4a6908d3
AS
609 state->ts_db_len -= 1;
610 state->current_line_delimiter_len = 1;
88115902 611 }
576ec7da 612
4a6908d3
AS
613 state->current_line = state->ts_db;
614 state->current_line_len = state->ts_db_len;
615
88115902 616 } else {
4a6908d3
AS
617 state->current_line = state->input;
618 state->current_line_len = lf_idx - state->input;
619
620 if (state->input != lf_idx &&
621 *(lf_idx - 1) == 0x0D) {
622 state->current_line_len--;
623 state->current_line_delimiter_len = 2;
88115902 624 } else {
4a6908d3 625 state->current_line_delimiter_len = 1;
88115902 626 }
4a6908d3 627 }
88115902
AS
628
629 state->input_len -= (lf_idx - state->input) + 1;
4a6908d3 630 state->input = (lf_idx + 1);
88115902
AS
631
632 return 0;
4a6908d3 633 }
88115902
AS
634
635 /* toclient */
576ec7da 636 } else {
88115902
AS
637 if (state->tc_current_line_lf_seen == 1) {
638 /* we have seen the lf for the previous line. Clear the parser
639 * details to parse new line */
640 state->tc_current_line_lf_seen = 0;
641 if (state->tc_current_line_db == 1) {
642 state->tc_current_line_db = 0;
643 SCFree(state->tc_db);
644 state->tc_db = NULL;
4a6908d3 645 state->tc_db_len = 0;
88115902 646 state->current_line = NULL;
4a6908d3 647 state->current_line_len = 0;
88115902
AS
648 }
649 }
650
651 uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
652
653 if (lf_idx == NULL) {
5311cd48
AS
654 /* fragmented lines. Decoder event for special cases. Not all
655 * fragmented lines should be treated as a possible evasion
656 * attempt. With multi payload smtp chunks we can have valid
657 * cases of fragmentation. But within the same segment chunk
658 * if we see fragmentation then it's definitely something you
659 * should alert about */
88115902 660 if (state->tc_current_line_db == 0) {
88115902
AS
661 state->tc_db = SCMalloc(state->input_len);
662 if (state->tc_db == NULL) {
576ec7da
AS
663 return -1;
664 }
4a6908d3 665 state->tc_current_line_db = 1;
88115902
AS
666 memcpy(state->tc_db, state->input, state->input_len);
667 state->tc_db_len = state->input_len;
576ec7da 668 } else {
1f07d152
EL
669 ptmp = SCRealloc(state->tc_db,
670 (state->tc_db_len + state->input_len));
671 if (ptmp == NULL) {
672 SCFree(state->tc_db);
673 state->tc_db = NULL;
674 state->tc_db_len = 0;
88115902
AS
675 return -1;
676 }
1f07d152
EL
677 state->tc_db = ptmp;
678
88115902
AS
679 memcpy(state->tc_db + state->tc_db_len,
680 state->input, state->input_len);
681 state->tc_db_len += state->input_len;
682 } /* else */
683 state->input += state->input_len;
684 state->input_len = 0;
576ec7da 685
88115902 686 return -1;
4a6908d3 687
576ec7da 688 } else {
88115902
AS
689 state->tc_current_line_lf_seen = 1;
690
4a6908d3 691 if (state->tc_current_line_db == 1) {
1f07d152
EL
692 ptmp = SCRealloc(state->tc_db,
693 (state->tc_db_len + (lf_idx + 1 - state->input)));
694 if (ptmp == NULL) {
695 SCFree(state->tc_db);
696 state->tc_db = NULL;
697 state->tc_db_len = 0;
4a6908d3
AS
698 return -1;
699 }
1f07d152
EL
700 state->tc_db = ptmp;
701
4a6908d3
AS
702 memcpy(state->tc_db + state->tc_db_len,
703 state->input, (lf_idx + 1 - state->input));
704 state->tc_db_len += (lf_idx + 1 - state->input);
705
706 if (state->tc_db_len > 1 &&
707 state->tc_db[state->tc_db_len - 2] == 0x0D) {
708 state->tc_db_len -= 2;
709 state->current_line_delimiter_len = 2;
88115902 710 } else {
4a6908d3
AS
711 state->tc_db_len -= 1;
712 state->current_line_delimiter_len = 1;
576ec7da 713 }
88115902 714
4a6908d3
AS
715 state->current_line = state->tc_db;
716 state->current_line_len = state->tc_db_len;
717
576ec7da 718 } else {
4a6908d3
AS
719 state->current_line = state->input;
720 state->current_line_len = lf_idx - state->input;
721
722 if (state->input != lf_idx &&
723 *(lf_idx - 1) == 0x0D) {
724 state->current_line_len--;
725 state->current_line_delimiter_len = 2;
88115902 726 } else {
4a6908d3 727 state->current_line_delimiter_len = 1;
88115902 728 }
4a6908d3 729 }
576ec7da 730
88115902 731 state->input_len -= (lf_idx - state->input) + 1;
4a6908d3 732 state->input = (lf_idx + 1);
88115902
AS
733
734 return 0;
735 } /* else - if (lf_idx == NULL) */
736 }
576ec7da 737
576ec7da
AS
738}
739
5311cd48 740static int SMTPInsertCommandIntoCommandBuffer(uint8_t command, SMTPState *state, Flow *f)
576ec7da 741{
7b0f261f 742 SCEnter();
1f07d152 743 void *ptmp;
7b0f261f 744
576ec7da 745 if (state->cmds_cnt >= state->cmds_buffer_len) {
bc5c9f4a
VJ
746 int increment = SMTP_COMMAND_BUFFER_STEPS;
747 if ((int)(state->cmds_buffer_len + SMTP_COMMAND_BUFFER_STEPS) > (int)USHRT_MAX) {
748 increment = USHRT_MAX - state->cmds_buffer_len;
749 }
750
1f07d152
EL
751 ptmp = SCRealloc(state->cmds,
752 sizeof(uint8_t) * (state->cmds_buffer_len + increment));
753 if (ptmp == NULL) {
754 SCFree(state->cmds);
755 state->cmds = NULL;
756 SCLogDebug("SCRealloc failure");
576ec7da
AS
757 return -1;
758 }
1f07d152
EL
759 state->cmds = ptmp;
760
bc5c9f4a 761 state->cmds_buffer_len += increment;
576ec7da
AS
762 }
763 if (state->cmds_cnt >= 1 &&
764 ((state->cmds[state->cmds_cnt - 1] == SMTP_COMMAND_STARTTLS) ||
765 (state->cmds[state->cmds_cnt - 1] == SMTP_COMMAND_DATA))) {
766 /* decoder event */
d209699a 767 SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE);
576ec7da
AS
768 /* we have to have EHLO, DATA, VRFY, EXPN, TURN, QUIT, NOOP,
769 * STARTTLS as the last command in pipelined mode */
770 }
bc5c9f4a
VJ
771
772 /** \todo decoder event */
7b0f261f
VJ
773 if ((int)(state->cmds_cnt + 1) > (int)USHRT_MAX) {
774 SCLogDebug("command buffer overflow");
bc5c9f4a 775 return -1;
7b0f261f 776 }
bc5c9f4a 777
576ec7da
AS
778 state->cmds[state->cmds_cnt] = command;
779 state->cmds_cnt++;
780
781 return 0;
782}
783
d3ca65de 784static int SMTPProcessCommandBDAT(SMTPState *state, Flow *f,
9634e60e 785 AppLayerParserState *pstate)
d3ca65de 786{
7b0f261f
VJ
787 SCEnter();
788
d3ca65de
AS
789 state->bdat_chunk_idx += (state->current_line_len +
790 state->current_line_delimiter_len);
791 if (state->bdat_chunk_idx > state->bdat_chunk_len) {
792 state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE;
793 /* decoder event */
d209699a 794 SMTPSetEvent(state, SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED);
7b0f261f 795 SCReturnInt(-1);
d3ca65de
AS
796 } else if (state->bdat_chunk_idx == state->bdat_chunk_len) {
797 state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE;
798 }
799
7b0f261f 800 SCReturnInt(0);
d3ca65de
AS
801}
802
576ec7da 803static int SMTPProcessCommandDATA(SMTPState *state, Flow *f,
9634e60e 804 AppLayerParserState *pstate)
576ec7da 805{
7b0f261f
VJ
806 SCEnter();
807
576ec7da
AS
808 if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
809 /* looks like are still waiting for a confirmination from the server */
810 return 0;
811 }
812
813 if (state->current_line_len == 1 && state->current_line[0] == '.') {
814 state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE;
815 /* kinda like a hack. The mail sent in DATA mode, would be
816 * acknowledged with a reply. We insert a dummy command to
817 * the command buffer to be used by the reply handler to match
818 * the reply received */
5311cd48 819 SMTPInsertCommandIntoCommandBuffer(SMTP_COMMAND_DATA_MODE, state, f);
c2dc6867 820
202b11c0 821 if (smtp_config.decode_mime && state->curr_tx->mime_state != NULL) {
c2dc6867 822 /* Complete parsing task */
56b74c8b 823 int ret = MimeDecParseComplete(state->curr_tx->mime_state);
c2dc6867
DA
824 if (ret != MIME_DEC_OK) {
825
d209699a 826 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_PARSE_FAILED);
c2dc6867
DA
827 SCLogDebug("MimeDecParseComplete() function failed");
828 }
829
830 /* Generate decoder events */
56b74c8b 831 MimeDecEntity *msg = state->curr_tx->mime_state->msg;
c2dc6867 832 if (msg->anomaly_flags & ANOM_INVALID_BASE64) {
d209699a 833 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_INVALID_BASE64);
c2dc6867
DA
834 }
835 if (msg->anomaly_flags & ANOM_INVALID_QP) {
d209699a 836 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_INVALID_QP);
c2dc6867
DA
837 }
838 if (msg->anomaly_flags & ANOM_LONG_LINE) {
d209699a 839 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_LINE);
c2dc6867
DA
840 }
841 if (msg->anomaly_flags & ANOM_LONG_ENC_LINE) {
d209699a 842 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_ENC_LINE);
c2dc6867
DA
843 }
844 if (msg->anomaly_flags & ANOM_LONG_HEADER_NAME) {
d209699a 845 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_HEADER_NAME);
c2dc6867
DA
846 }
847 if (msg->anomaly_flags & ANOM_LONG_HEADER_VALUE) {
d209699a 848 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_HEADER_VALUE);
c2dc6867
DA
849 }
850 if (msg->anomaly_flags & ANOM_MALFORMED_MSG) {
d209699a 851 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_MALFORMED_MSG);
c2dc6867 852 }
6d170cad
VJ
853 if (msg->anomaly_flags & ANOM_LONG_BOUNDARY) {
854 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_BOUNDARY_TOO_LONG);
855 }
c2dc6867 856 }
d209699a
VJ
857 state->curr_tx->done = 1;
858 SCLogDebug("marked tx as done");
c2dc6867
DA
859 }
860
861 /* If DATA, then parse out a MIME message */
862 if (state->current_command == SMTP_COMMAND_DATA &&
863 (state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
864
d209699a 865 if (smtp_config.decode_mime && state->curr_tx->mime_state) {
106bbc78 866 int ret = MimeDecParseLine((const uint8_t *) state->current_line,
2ecab3f7
EL
867 state->current_line_len, state->current_line_delimiter_len,
868 state->curr_tx->mime_state);
c2dc6867
DA
869 if (ret != MIME_DEC_OK) {
870 SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret);
871 }
872 }
576ec7da
AS
873 }
874
875 return 0;
876}
877
878static int SMTPProcessCommandSTARTTLS(SMTPState *state, Flow *f,
9634e60e 879 AppLayerParserState *pstate)
576ec7da
AS
880{
881 return 0;
882}
883
884static int SMTPProcessReply(SMTPState *state, Flow *f,
9634e60e 885 AppLayerParserState *pstate)
576ec7da 886{
7b0f261f
VJ
887 SCEnter();
888
576ec7da 889 uint64_t reply_code = 0;
997eaf42 890 PatternMatcherQueue *pmq = state->thread_local_data;
576ec7da 891
576ec7da
AS
892 /* the reply code has to contain at least 3 bytes, to hold the 3 digit
893 * reply code */
894 if (state->current_line_len < 3) {
895 /* decoder event */
d209699a 896 SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY);
576ec7da
AS
897 return -1;
898 }
899
900 if (state->current_line_len >= 4) {
901 if (state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY) {
902 if (state->current_line[3] != '-') {
903 state->parser_state &= ~SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY;
904 }
905 } else {
906 if (state->current_line[3] == '-') {
907 state->parser_state |= SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY;
908 }
909 }
910 } else {
911 if (state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY) {
912 state->parser_state &= ~SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY;
913 }
914 }
915
4d38a571
AS
916 /* I don't like this pmq reset here. We'll devise a method later, that
917 * should make the use of the mpm very efficient */
997eaf42 918 PmqReset(pmq);
4d38a571 919 int mpm_cnt = mpm_table[SMTP_MPM].Search(smtp_mpm_ctx, smtp_mpm_thread_ctx,
997eaf42 920 pmq, state->current_line,
4d38a571
AS
921 3);
922 if (mpm_cnt == 0) {
923 /* set decoder event - reply code invalid */
d209699a 924 SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY);
7b0f261f
VJ
925 SCLogDebug("invalid reply code %02x %02x %02x",
926 state->current_line[0], state->current_line[1], state->current_line[2]);
927 SCReturnInt(-1);
4d38a571 928 }
cd8283bb 929 reply_code = smtp_reply_map[pmq->rule_id_array[0]].enum_value;
4d38a571
AS
930
931 if (state->cmds_idx == state->cmds_cnt) {
0d7159b5 932 if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
1291250c
MA
933 /* the first server reply can be a multiline message. Let's
934 * flag the fact that we have seen the first reply only at the end
935 * of a multiline reply
936 */
937 if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY))
938 state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN;
0d7159b5
AS
939 if (reply_code == SMTP_REPLY_220)
940 SCReturnInt(0);
26084182 941 else {
d209699a 942 SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY);
26084182
VJ
943 SCReturnInt(0);
944 }
4d38a571 945 } else {
0d7159b5
AS
946 /* decoder event - unable to match reply with request */
947 SCLogDebug("unable to match reply with request");
26084182 948 SCReturnInt(0);
576ec7da
AS
949 }
950 }
951
95fa5ae1
VJ
952 if (state->cmds_cnt == 0) {
953 /* reply but not a command we have stored, fall through */
954 } else if (state->cmds[state->cmds_idx] == SMTP_COMMAND_STARTTLS) {
4d38a571 955 if (reply_code == SMTP_REPLY_220) {
576ec7da
AS
956 /* we are entering STARRTTLS data mode */
957 state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
8527b8e0 958 AppLayerParserStateSetFlag(pstate,
429c6388
AS
959 APP_LAYER_PARSER_NO_INSPECTION |
960 APP_LAYER_PARSER_NO_REASSEMBLY);
576ec7da
AS
961 } else {
962 /* decoder event */
d209699a 963 SMTPSetEvent(state, SMTP_DECODER_EVENT_TLS_REJECTED);
576ec7da
AS
964 }
965 } else if (state->cmds[state->cmds_idx] == SMTP_COMMAND_DATA) {
4d38a571 966 if (reply_code == SMTP_REPLY_354) {
576ec7da
AS
967 /* Next comes the mail for the DATA command in toserver direction */
968 state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
969 } else {
970 /* decoder event */
d209699a 971 SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED);
576ec7da
AS
972 }
973 } else {
4d38a571
AS
974 /* we don't care for any other command for now */
975 /* check if reply falls in the valid list of replies for SMTP. If not
976 * decoder event */
576ec7da
AS
977 }
978
4d38a571 979 /* if it is a multi-line reply, we need to move the index only once for all
576ec7da
AS
980 * the line of the reply. We unset the multiline flag on the last
981 * line of the multiline reply, following which we increment the index */
982 if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
983 state->cmds_idx++;
984 }
985
986 /* if we have matched all the buffered commands, reset the cnt and index */
987 if (state->cmds_idx == state->cmds_cnt) {
988 state->cmds_cnt = 0;
989 state->cmds_idx = 0;
990 }
991
992 return 0;
993}
994
d3ca65de
AS
995static int SMTPParseCommandBDAT(SMTPState *state)
996{
7b0f261f
VJ
997 SCEnter();
998
d3ca65de
AS
999 int i = 4;
1000 while (i < state->current_line_len) {
1001 if (state->current_line[i] != ' ') {
1002 break;
1003 }
1004 i++;
1005 }
1006 if (i == 4) {
1007 /* decoder event */
1008 return -1;
1009 }
1010 if (i == state->current_line_len) {
1011 /* decoder event */
1012 return -1;
1013 }
25638832 1014 char *endptr = NULL;
d3ca65de
AS
1015 state->bdat_chunk_len = strtoul((const char *)state->current_line + i,
1016 (char **)&endptr, 10);
25638832 1017 if ((uint8_t *)endptr == state->current_line + i) {
d3ca65de
AS
1018 /* decoder event */
1019 return -1;
1020 }
1021
1022 return 0;
1023}
1024
7bca8268
EL
1025static int SMTPParseCommandWithParam(SMTPState *state, uint8_t prefix_len, uint8_t **target, uint16_t *target_len)
1026{
1027 int i = prefix_len + 1;
1028 int spc_i = 0;
1029
1030 while (i < state->current_line_len) {
1031 if (state->current_line[i] != ' ') {
1032 break;
1033 }
1034 i++;
1035 }
1036
1037 /* rfc1870: with the size extension the mail from can be followed by an option.
1038 We use the space separator to detect it. */
1039 spc_i = i;
1040 while (spc_i < state->current_line_len) {
1041 if (state->current_line[spc_i] == ' ') {
1042 break;
1043 }
1044 spc_i++;
1045 }
1046
7bca8268
EL
1047 *target = SCMalloc(spc_i - i + 1);
1048 if (*target == NULL)
1049 return -1;
1050 memcpy(*target, state->current_line + i, spc_i - i);
1051 (*target)[spc_i - i] = '\0';
1052 *target_len = spc_i - i;
1053
1054 return 0;
7bca8268
EL
1055}
1056
1057static int SMTPParseCommandHELO(SMTPState *state)
1058{
10e2e2a8
EL
1059 if (state->helo) {
1060 SMTPSetEvent(state, SMTP_DECODER_EVENT_DUPLICATE_FIELDS);
1061 return 0;
1062 }
7bca8268
EL
1063 return SMTPParseCommandWithParam(state, 4, &state->helo, &state->helo_len);
1064}
1065
1066static int SMTPParseCommandMAILFROM(SMTPState *state)
1067{
10e2e2a8
EL
1068 if (state->curr_tx->mail_from) {
1069 SMTPSetEvent(state, SMTP_DECODER_EVENT_DUPLICATE_FIELDS);
1070 return 0;
1071 }
7bca8268
EL
1072 return SMTPParseCommandWithParam(state, 9,
1073 &state->curr_tx->mail_from,
1074 &state->curr_tx->mail_from_len);
1075}
1076
752fdba9
EL
1077static int SMTPParseCommandRCPTTO(SMTPState *state)
1078{
1079 uint8_t *rcptto;
1080 uint16_t rcptto_len;
1081
1082 if (SMTPParseCommandWithParam(state, 7, &rcptto, &rcptto_len) == 0) {
1083 SMTPString *rcptto_str = SMTPStringAlloc();
1084 if (rcptto_str) {
1085 rcptto_str->str = rcptto;
1086 rcptto_str->len = rcptto_len;
1087 TAILQ_INSERT_TAIL(&state->curr_tx->rcpt_to_list, rcptto_str, next);
1088 } else {
1089 SCFree(rcptto);
1090 return -1;
1091 }
1092 } else {
1093 return -1;
1094 }
1095 return 0;
1096}
1097
7c3b22da
VJ
1098/* consider 'rset' and 'quit' to be part of the existing state */
1099static int NoNewTx(SMTPState *state)
1100{
1101 if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
1102 if (state->current_line_len >= 4 &&
1103 SCMemcmpLowercase("rset", state->current_line, 4) == 0) {
1104 return 1;
1105 } else if (state->current_line_len >= 4 &&
1106 SCMemcmpLowercase("quit", state->current_line, 4) == 0) {
1107 return 1;
1108 }
1109 }
1110 return 0;
1111}
1112
576ec7da 1113static int SMTPProcessRequest(SMTPState *state, Flow *f,
9634e60e 1114 AppLayerParserState *pstate)
576ec7da 1115{
7b0f261f 1116 SCEnter();
d209699a
VJ
1117 SMTPTransaction *tx = state->curr_tx;
1118
7c3b22da 1119 if (state->curr_tx == NULL || (state->curr_tx->done && !NoNewTx(state))) {
d209699a
VJ
1120 tx = SMTPTransactionCreate();
1121 if (tx == NULL)
1122 return -1;
1123 state->curr_tx = tx;
1124 TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
1125 tx->tx_id = state->tx_cnt++;
1126 }
7b0f261f 1127
0d7159b5 1128 if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
d209699a 1129 SMTPSetEvent(state, SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE);
0d7159b5
AS
1130 }
1131
576ec7da
AS
1132 /* there are 2 commands that can push it into this COMMAND_DATA mode -
1133 * STARTTLS and DATA */
1134 if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
d3ca65de
AS
1135 int r = 0;
1136
576ec7da
AS
1137 if (state->current_line_len >= 8 &&
1138 SCMemcmpLowercase("starttls", state->current_line, 8) == 0) {
1139 state->current_command = SMTP_COMMAND_STARTTLS;
1140 } else if (state->current_line_len >= 4 &&
1141 SCMemcmpLowercase("data", state->current_line, 4) == 0) {
1142 state->current_command = SMTP_COMMAND_DATA;
c2dc6867 1143 if (smtp_config.decode_mime) {
5dbedbfa
EL
1144 if (tx->mime_state) {
1145 /* We have 2 chained mails and did not detect the end
1146 * of first one. So we start a new transaction. */
1147 tx->mime_state->state_flag = PARSE_ERROR;
1148 SMTPSetEvent(state, SMTP_DECODER_EVENT_UNPARSABLE_CONTENT);
1149 tx = SMTPTransactionCreate();
1150 if (tx == NULL)
1151 return -1;
1152 state->curr_tx = tx;
1153 TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
1154 tx->tx_id = state->tx_cnt++;
1155 }
d2657bec 1156 tx->mime_state = MimeDecInitParser(f, SMTPProcessDataChunk);
56b74c8b 1157 if (tx->mime_state == NULL) {
c2dc6867
DA
1158 SCLogError(SC_ERR_MEM_ALLOC, "MimeDecInitParser() failed to "
1159 "allocate data");
1160 return MIME_DEC_ERR_MEM;
1161 }
1162
1163 /* Add new MIME message to end of list */
56b74c8b
VJ
1164 if (tx->msg_head == NULL) {
1165 tx->msg_head = tx->mime_state->msg;
1166 tx->msg_tail = tx->mime_state->msg;
c2dc6867
DA
1167 }
1168 else {
56b74c8b
VJ
1169 tx->msg_tail->next = tx->mime_state->msg;
1170 tx->msg_tail = tx->mime_state->msg;
c2dc6867
DA
1171 }
1172 }
1173
d3ca65de
AS
1174 } else if (state->current_line_len >= 4 &&
1175 SCMemcmpLowercase("bdat", state->current_line, 4) == 0) {
1176 r = SMTPParseCommandBDAT(state);
7b0f261f
VJ
1177 if (r == -1) {
1178 SCReturnInt(-1);
1179 }
d3ca65de
AS
1180 state->current_command = SMTP_COMMAND_BDAT;
1181 state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
7bca8268
EL
1182 } else if (state->current_line_len >= 4 &&
1183 ((SCMemcmpLowercase("helo", state->current_line, 4) == 0) ||
1184 SCMemcmpLowercase("ehlo", state->current_line, 4) == 0)) {
1185 r = SMTPParseCommandHELO(state);
1186 if (r == -1) {
1187 SCReturnInt(-1);
1188 }
1189 state->current_command = SMTP_COMMAND_OTHER_CMD;
1190 } else if (state->current_line_len >= 9 &&
1191 SCMemcmpLowercase("mail from", state->current_line, 9) == 0) {
1192 r = SMTPParseCommandMAILFROM(state);
1193 if (r == -1) {
1194 SCReturnInt(-1);
1195 }
1196 state->current_command = SMTP_COMMAND_OTHER_CMD;
752fdba9
EL
1197 } else if (state->current_line_len >= 7 &&
1198 SCMemcmpLowercase("rcpt to", state->current_line, 7) == 0) {
1199 r = SMTPParseCommandRCPTTO(state);
1200 if (r == -1) {
1201 SCReturnInt(-1);
1202 }
1203 state->current_command = SMTP_COMMAND_OTHER_CMD;
576ec7da
AS
1204 } else {
1205 state->current_command = SMTP_COMMAND_OTHER_CMD;
1206 }
1207
1208 /* Every command is inserted into a command buffer, to be matched
1209 * against reply(ies) sent by the server */
1210 if (SMTPInsertCommandIntoCommandBuffer(state->current_command,
5311cd48 1211 state, f) == -1) {
7b0f261f 1212 SCReturnInt(-1);
576ec7da 1213 }
d3ca65de 1214
7b0f261f 1215 SCReturnInt(r);
576ec7da
AS
1216 }
1217
1218 switch (state->current_command) {
1219 case SMTP_COMMAND_STARTTLS:
1220 return SMTPProcessCommandSTARTTLS(state, f, pstate);
1221
1222 case SMTP_COMMAND_DATA:
1223 return SMTPProcessCommandDATA(state, f, pstate);
1224
d3ca65de
AS
1225 case SMTP_COMMAND_BDAT:
1226 return SMTPProcessCommandBDAT(state, f, pstate);
1227
576ec7da
AS
1228 default:
1229 /* we have nothing to do with any other command at this instant.
1230 * Just let it go through */
7b0f261f 1231 SCReturnInt(0);
576ec7da
AS
1232 }
1233}
1234
88115902 1235static int SMTPParse(int direction, Flow *f, SMTPState *state,
9634e60e 1236 AppLayerParserState *pstate, uint8_t *input,
997eaf42 1237 uint32_t input_len,
429c6388 1238 PatternMatcherQueue *local_data)
576ec7da 1239{
7b0f261f
VJ
1240 SCEnter();
1241
4e7cb7b8
VJ
1242 if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1243 SCReturnInt(1);
f4f53924
VJ
1244 } else if (input == NULL || input_len == 0) {
1245 SCReturnInt(-1);
4e7cb7b8
VJ
1246 }
1247
576ec7da
AS
1248 state->input = input;
1249 state->input_len = input_len;
88115902 1250 state->direction = direction;
997eaf42 1251 state->thread_local_data = local_data;
576ec7da 1252
87599bc7
AS
1253 /* toserver */
1254 if (direction == 0) {
1255 while (SMTPGetLine(state) >= 0) {
d3ca65de 1256 if (SMTPProcessRequest(state, f, pstate) == -1)
7b0f261f 1257 SCReturnInt(-1);
87599bc7 1258 }
88115902 1259
87599bc7
AS
1260 /* toclient */
1261 } else {
1262 while (SMTPGetLine(state) >= 0) {
d3ca65de 1263 if (SMTPProcessReply(state, f, pstate) == -1)
7b0f261f 1264 SCReturnInt(-1);
88115902 1265 }
576ec7da
AS
1266 }
1267
7b0f261f 1268 SCReturnInt(0);
576ec7da
AS
1269}
1270
88115902 1271static int SMTPParseClientRecord(Flow *f, void *alstate,
9634e60e 1272 AppLayerParserState *pstate,
576ec7da 1273 uint8_t *input, uint32_t input_len,
429c6388 1274 void *local_data)
576ec7da 1275{
7b0f261f
VJ
1276 SCEnter();
1277
88115902 1278 /* first arg 0 is toserver */
429c6388 1279 return SMTPParse(0, f, alstate, pstate, input, input_len, local_data);
88115902 1280}
576ec7da 1281
88115902 1282static int SMTPParseServerRecord(Flow *f, void *alstate,
9634e60e 1283 AppLayerParserState *pstate,
88115902 1284 uint8_t *input, uint32_t input_len,
429c6388 1285 void *local_data)
88115902 1286{
7b0f261f
VJ
1287 SCEnter();
1288
88115902 1289 /* first arg 1 is toclient */
429c6388 1290 return SMTPParse(1, f, alstate, pstate, input, input_len, local_data);
576ec7da
AS
1291
1292 return 0;
1293}
1294
1295/**
1296 * \internal
1297 * \brief Function to allocate SMTP state memory.
1298 */
d2657bec 1299void *SMTPStateAlloc(void)
576ec7da
AS
1300{
1301 SMTPState *smtp_state = SCMalloc(sizeof(SMTPState));
e176be6f 1302 if (unlikely(smtp_state == NULL))
576ec7da
AS
1303 return NULL;
1304 memset(smtp_state, 0, sizeof(SMTPState));
1305
1306 smtp_state->cmds = SCMalloc(sizeof(uint8_t) *
1307 SMTP_COMMAND_BUFFER_STEPS);
1308 if (smtp_state->cmds == NULL) {
1309 SCFree(smtp_state);
1310 return NULL;
1311 }
1312 smtp_state->cmds_buffer_len = SMTP_COMMAND_BUFFER_STEPS;
1313
56b74c8b
VJ
1314 TAILQ_INIT(&smtp_state->tx_list);
1315
997eaf42
AS
1316 return smtp_state;
1317}
1318
752fdba9
EL
1319static SMTPString *SMTPStringAlloc(void)
1320{
1321 SMTPString *smtp_string = SCMalloc(sizeof(SMTPString));
1322 if (unlikely(smtp_string == NULL))
1323 return NULL;
1324 memset(smtp_string, 0, sizeof(SMTPString));
1325
1326 return smtp_string;
1327}
1328
1329
1330static void SMTPStringFree(SMTPString *str)
1331{
1332 if (str->str) {
1333 SCFree(str->str);
1334 }
1335 SCFree(str);
1336}
1337
997eaf42
AS
1338static void *SMTPLocalStorageAlloc(void)
1339{
1340 /* needed by the mpm */
1341 PatternMatcherQueue *pmq = SCMalloc(sizeof(PatternMatcherQueue));
e176be6f 1342 if (unlikely(pmq == NULL)) {
4d38a571
AS
1343 exit(EXIT_FAILURE);
1344 }
fa885e1d 1345 PmqSetup(pmq);
4d38a571 1346
997eaf42
AS
1347 return pmq;
1348}
1349
1350static void SMTPLocalStorageFree(void *pmq)
1351{
1352 if (pmq != NULL) {
1353 PmqFree(pmq);
1354 SCFree(pmq);
1355 }
1356
1357 return;
576ec7da
AS
1358}
1359
56b74c8b
VJ
1360static void SMTPTransactionFree(SMTPTransaction *tx, SMTPState *state)
1361{
1362 if (tx->mime_state != NULL) {
1363 MimeDecDeInitParser(tx->mime_state);
1364 }
d209699a
VJ
1365 /* Free list of MIME message recursively */
1366 MimeDecFreeEntity(tx->msg_head);
1367
7b818494 1368 if (tx->decoder_events != NULL)
d209699a 1369 AppLayerDecoderEventsFreeEvents(&tx->decoder_events);
7b818494 1370
e984a572
VJ
1371 if (tx->de_state != NULL)
1372 DetectEngineStateFree(tx->de_state);
7bca8268
EL
1373
1374 if (tx->mail_from)
1375 SCFree(tx->mail_from);
1376
752fdba9
EL
1377 SMTPString *str = NULL;
1378 while ((str = TAILQ_FIRST(&tx->rcpt_to_list))) {
1379 TAILQ_REMOVE(&tx->rcpt_to_list, str, next);
1380 SMTPStringFree(str);
1381 }
d209699a
VJ
1382#if 0
1383 if (tx->decoder_events->cnt <= smtp_state->events)
1384 smtp_state->events -= tx->decoder_events->cnt;
1385 else
1386 smtp_state->events = 0;
1387#endif
56b74c8b
VJ
1388 SCFree(tx);
1389}
1390
576ec7da
AS
1391/**
1392 * \internal
1393 * \brief Function to free SMTP state memory.
1394 */
1395static void SMTPStateFree(void *p)
1396{
1397 SMTPState *smtp_state = (SMTPState *)p;
1398
1399 if (smtp_state->cmds != NULL) {
1400 SCFree(smtp_state->cmds);
1401 }
88115902
AS
1402 if (smtp_state->ts_current_line_db) {
1403 SCFree(smtp_state->ts_db);
1404 }
1405 if (smtp_state->tc_current_line_db) {
1406 SCFree(smtp_state->tc_db);
1407 }
576ec7da 1408
7bca8268
EL
1409 if (smtp_state->helo) {
1410 SCFree(smtp_state->helo);
1411 }
1412
c2dc6867 1413 FileContainerFree(smtp_state->files_ts);
56b74c8b
VJ
1414
1415 SMTPTransaction *tx = NULL;
1416 while ((tx = TAILQ_FIRST(&smtp_state->tx_list))) {
56b74c8b
VJ
1417 TAILQ_REMOVE(&smtp_state->tx_list, tx, next);
1418 SMTPTransactionFree(tx, smtp_state);
1419 }
c2dc6867 1420
576ec7da
AS
1421 SCFree(smtp_state);
1422
1423 return;
1424}
1425
4d38a571
AS
1426static void SMTPSetMpmState(void)
1427{
1428 smtp_mpm_ctx = SCMalloc(sizeof(MpmCtx));
e176be6f 1429 if (unlikely(smtp_mpm_ctx == NULL)) {
4d38a571
AS
1430 exit(EXIT_FAILURE);
1431 }
1432 memset(smtp_mpm_ctx, 0, sizeof(MpmCtx));
a49cbf8a 1433 MpmInitCtx(smtp_mpm_ctx, SMTP_MPM);
4d38a571
AS
1434
1435 smtp_mpm_thread_ctx = SCMalloc(sizeof(MpmThreadCtx));
e176be6f 1436 if (unlikely(smtp_mpm_thread_ctx == NULL)) {
4d38a571
AS
1437 exit(EXIT_FAILURE);
1438 }
1439 memset(smtp_mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
14d9ce7b 1440 MpmInitThreadCtx(smtp_mpm_thread_ctx, SMTP_MPM);
4d38a571
AS
1441
1442 uint32_t i = 0;
1443 for (i = 0; i < sizeof(smtp_reply_map)/sizeof(SCEnumCharMap) - 1; i++) {
1444 SCEnumCharMap *map = &smtp_reply_map[i];
a49cbf8a
AS
1445 /* The third argument is 3, because reply code is always 3 bytes. */
1446 MpmAddPatternCI(smtp_mpm_ctx, (uint8_t *)map->enum_name, 3,
1447 0 /* defunct */, 0 /* defunct */,
cd8283bb 1448 i /* pattern id */, i /* rule id */ , 0 /* no flags */);
4d38a571
AS
1449 }
1450
1451 mpm_table[SMTP_MPM].Prepare(smtp_mpm_ctx);
1452}
1453
5e2d9dbd
AS
1454int SMTPStateGetEventInfo(const char *event_name,
1455 int *event_id, AppLayerEventType *event_type)
1456{
1457 *event_id = SCMapEnumNameToValue(event_name, smtp_decoder_event_table);
1458 if (*event_id == -1) {
1459 SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
1460 "smtp's enum map table.", event_name);
1461 /* yes this is fatal */
1462 return -1;
1463 }
1464
d209699a 1465 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
5e2d9dbd
AS
1466
1467 return 0;
1468}
1469
429c6388
AS
1470static int SMTPRegisterPatternsForProtocolDetection(void)
1471{
1472 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
1473 "EHLO", 4, 0, STREAM_TOSERVER) < 0)
1474 {
1475 return -1;
1476 }
1477 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
1478 "HELO", 4, 0, STREAM_TOSERVER) < 0)
1479 {
1480 return -1;
1481 }
1482 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
1483 "QUIT", 4, 0, STREAM_TOSERVER) < 0)
1484 {
1485 return -1;
1486 }
1487
1488 return 0;
1489}
1490
56b74c8b
VJ
1491static void SMTPStateTransactionFree (void *state, uint64_t tx_id)
1492{
56b74c8b
VJ
1493 SMTPState *smtp_state = state;
1494 SMTPTransaction *tx = NULL;
1495 TAILQ_FOREACH(tx, &smtp_state->tx_list, next) {
1496 if (tx_id < tx->tx_id)
1497 break;
1498 else if (tx_id > tx->tx_id)
1499 continue;
1500
1501 if (tx == smtp_state->curr_tx)
1502 smtp_state->curr_tx = NULL;
56b74c8b
VJ
1503 TAILQ_REMOVE(&smtp_state->tx_list, tx, next);
1504 SMTPTransactionFree(tx, state);
1505 break;
1506 }
1507
1508
1509}
1510
f32d79df 1511/** \retval cnt highest tx id */
56b74c8b
VJ
1512static uint64_t SMTPStateGetTxCnt(void *state)
1513{
1514 uint64_t cnt = 0;
1515 SMTPState *smtp_state = state;
1516 if (smtp_state) {
f32d79df 1517 cnt = smtp_state->tx_cnt;
56b74c8b
VJ
1518 }
1519 SCLogDebug("returning %"PRIu64, cnt);
1520 return cnt;
1521}
1522
1523static void *SMTPStateGetTx(void *state, uint64_t id)
1524{
1525 SMTPState *smtp_state = state;
1526 if (smtp_state) {
1527 SMTPTransaction *tx = NULL;
1528
1529 if (smtp_state->curr_tx == NULL)
1530 return NULL;
1531 if (smtp_state->curr_tx->tx_id == id)
1532 return smtp_state->curr_tx;
1533
1534 TAILQ_FOREACH(tx, &smtp_state->tx_list, next) {
1535 if (tx->tx_id == id)
1536 return tx;
1537 }
1538 }
56b74c8b
VJ
1539 return NULL;
1540
1541}
1542
1543static int SMTPStateGetAlstateProgressCompletionStatus(uint8_t direction) {
d209699a 1544 return 1;
56b74c8b
VJ
1545}
1546
1547static int SMTPStateGetAlstateProgress(void *vtx, uint8_t direction)
1548{
1549 SMTPTransaction *tx = vtx;
d209699a 1550 return tx->done;
56b74c8b
VJ
1551}
1552
1553static FileContainer *SMTPStateGetFiles(void *state, uint8_t direction)
1554{
1555 if (state == NULL)
1556 return NULL;
1557
1558 SMTPState *smtp_state = (SMTPState *)state;
1559
1560 if (direction & STREAM_TOCLIENT) {
1561 SCReturnPtr(NULL, "FileContainer");
1562 } else {
1563 SCLogDebug("smtp_state->files_ts %p", smtp_state->files_ts);
1564 SCReturnPtr(smtp_state->files_ts, "FileContainer");
1565 }
1566}
1567
08b06bac
VJ
1568static void SMTPStateTruncate(void *state, uint8_t direction)
1569{
1570 FileContainer *fc = SMTPStateGetFiles(state, direction);
1571 if (fc != NULL) {
1572 SCLogDebug("truncating stream, closing files in %s direction (container %p)",
1573 direction & STREAM_TOCLIENT ? "STREAM_TOCLIENT" : "STREAM_TOSERVER", fc);
1574 FileTruncateAllOpenFiles(fc);
1575 }
1576}
1577
d209699a
VJ
1578static AppLayerDecoderEvents *SMTPGetEvents(void *state, uint64_t tx_id)
1579{
1580 SCLogDebug("get SMTP events for TX %"PRIu64, tx_id);
1581
1582 SMTPTransaction *tx = SMTPStateGetTx(state, tx_id);
1583 if (tx != NULL) {
1584 return tx->decoder_events;
1585 }
1586 return NULL;
1587}
1588
e984a572
VJ
1589static DetectEngineState *SMTPGetTxDetectState(void *vtx)
1590{
1591 SMTPTransaction *tx = (SMTPTransaction *)vtx;
1592 return tx->de_state;
1593}
1594
f536099a 1595static int SMTPSetTxDetectState(void *state, void *vtx, DetectEngineState *s)
e984a572
VJ
1596{
1597 SMTPTransaction *tx = (SMTPTransaction *)vtx;
1598 tx->de_state = s;
1599 return 0;
1600}
1601
576ec7da 1602/**
e5c36952 1603 * \brief Register the SMTP Protocol parser.
576ec7da
AS
1604 */
1605void RegisterSMTPParsers(void)
1606{
10966245
AS
1607 char *proto_name = "smtp";
1608
429c6388
AS
1609 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1610 AppLayerProtoDetectRegisterProtocol(ALPROTO_SMTP, proto_name);
1611 if (SMTPRegisterPatternsForProtocolDetection() < 0 )
1612 return;
ddde572f
AS
1613 } else {
1614 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1615 proto_name);
1616 return;
1617 }
576ec7da 1618
429c6388
AS
1619 if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1620 AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateAlloc, SMTPStateFree);
576ec7da 1621
429c6388
AS
1622 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOSERVER,
1623 SMTPParseClientRecord);
1624 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOCLIENT,
1625 SMTPParseServerRecord);
6cb00142 1626
429c6388 1627 AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetEventInfo);
d209699a 1628 AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetEvents);
f536099a 1629 AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, NULL,
e984a572 1630 SMTPGetTxDetectState, SMTPSetTxDetectState);
576ec7da 1631
429c6388
AS
1632 AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPLocalStorageAlloc,
1633 SMTPLocalStorageFree);
56b74c8b
VJ
1634
1635 AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateTransactionFree);
1636 AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetFiles);
1637 AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetAlstateProgress);
1638 AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTxCnt);
1639 AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTx);
1640 AppLayerParserRegisterGetStateProgressCompletionStatus(IPPROTO_TCP, ALPROTO_SMTP,
1641 SMTPStateGetAlstateProgressCompletionStatus);
08b06bac 1642 AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateTruncate);
ddde572f
AS
1643 } else {
1644 SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
1645 "still on.", proto_name);
1646 }
997eaf42 1647
4d38a571
AS
1648 SMTPSetMpmState();
1649
c2dc6867
DA
1650 SMTPConfigure();
1651
9faa4b74 1652#ifdef UNITTESTS
429c6388 1653 AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMTP, SMTPParserRegisterTests);
9faa4b74 1654#endif
576ec7da
AS
1655 return;
1656}
1657
1658/***************************************Unittests******************************/
1659
87599bc7
AS
1660#ifdef UNITTESTS
1661
576ec7da
AS
1662/*
1663 * \test Test STARTTLS.
1664 */
1665int SMTPParserTest01(void)
1666{
1667 int result = 0;
1668 Flow f;
1669 int r = 0;
1670
1671 /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */
1672 uint8_t welcome_reply[] = {
1673 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67,
1674 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
1675 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20,
1676 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36,
1677 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36,
1678 0x0d, 0x0a
1679 };
1680 uint32_t welcome_reply_len = sizeof(welcome_reply);
1681
1682 /* EHLO [192.168.0.158]<CR><LF> */
1683 uint8_t request1[] = {
1684 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x5b, 0x31, 0x39,
1685 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e,
1686 0x31, 0x35, 0x38, 0x5d, 0x0d, 0x0a
1687 };
1688 uint32_t request1_len = sizeof(request1);
1689 /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF>
1690 * 250-SIZE 35882577<CR><LF>
1691 * 250-8BITMIME<CR><LF>
1692 * 250-STARTTLS<CR><LF>
1693 * 250 ENHANCEDSTATUSCODES<CR><LF>
1694 */
1695 uint8_t reply1[] = {
1696 0x32, 0x35, 0x30, 0x2d, 0x6d, 0x78, 0x2e, 0x67,
1697 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
1698 0x6d, 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75,
1699 0x72, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
1700 0x65, 0x2c, 0x20, 0x5b, 0x31, 0x31, 0x37, 0x2e,
1701 0x31, 0x39, 0x38, 0x2e, 0x31, 0x31, 0x35, 0x2e,
1702 0x35, 0x30, 0x5d, 0x0d, 0x0a, 0x32, 0x35, 0x30,
1703 0x2d, 0x53, 0x49, 0x5a, 0x45, 0x20, 0x33, 0x35,
1704 0x38, 0x38, 0x32, 0x35, 0x37, 0x37, 0x0d, 0x0a,
1705 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, 0x54,
1706 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, 0x35,
1707 0x30, 0x2d, 0x53, 0x54, 0x41, 0x52, 0x54, 0x54,
1708 0x4c, 0x53, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x20,
1709 0x45, 0x4e, 0x48, 0x41, 0x4e, 0x43, 0x45, 0x44,
1710 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x43, 0x4f,
1711 0x44, 0x45, 0x53, 0x0d, 0x0a
1712 };
1713 uint32_t reply1_len = sizeof(reply1);
1714
1715 /* STARTTLS<CR><LF> */
1716 uint8_t request2[] = {
1717 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53,
1718 0x0d, 0x0a
1719 };
1720 uint32_t request2_len = sizeof(request2);
1721 /* 220 2.0.0 Ready to start TLS<CR><LF> */
1722 uint8_t reply2[] = {
1723 0x32, 0x32, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e,
1724 0x30, 0x20, 0x52, 0x65, 0x61, 0x64, 0x79, 0x20,
1725 0x74, 0x6f, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74,
1726 0x20, 0x54, 0x4c, 0x53, 0x0d, 0x0a
1727 };
1728 uint32_t reply2_len = sizeof(reply2);
1729
1730 TcpSession ssn;
8dbf7a0d 1731 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
576ec7da
AS
1732
1733 memset(&f, 0, sizeof(f));
1734 memset(&ssn, 0, sizeof(ssn));
1735
1736 FLOW_INITIALIZE(&f);
1737 f.protoctx = (void *)&ssn;
429c6388 1738 f.proto = IPPROTO_TCP;
576ec7da
AS
1739
1740 StreamTcpInitConfig(TRUE);
576ec7da 1741
cd3e32ce 1742 SCMutexLock(&f.m);
429c6388
AS
1743 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
1744 welcome_reply, welcome_reply_len);
576ec7da
AS
1745 if (r != 0) {
1746 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 1747 SCMutexUnlock(&f.m);
576ec7da
AS
1748 goto end;
1749 }
cd3e32ce 1750 SCMutexUnlock(&f.m);
06904c90 1751 SMTPState *smtp_state = f.alstate;
576ec7da
AS
1752 if (smtp_state == NULL) {
1753 printf("no smtp state: ");
1754 goto end;
1755 }
1756 if (smtp_state->input_len != 0 ||
0d7159b5 1757 smtp_state->cmds_cnt != 0 ||
576ec7da 1758 smtp_state->cmds_idx != 0 ||
0d7159b5 1759 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
576ec7da
AS
1760 printf("smtp parser in inconsistent state\n");
1761 goto end;
1762 }
1763
cd3e32ce 1764 SCMutexLock(&f.m);
429c6388
AS
1765 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
1766 request1, request1_len);
576ec7da
AS
1767 if (r != 0) {
1768 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 1769 SCMutexUnlock(&f.m);
576ec7da
AS
1770 goto end;
1771 }
cd3e32ce 1772 SCMutexUnlock(&f.m);
576ec7da 1773 if (smtp_state->input_len != 0 ||
576ec7da
AS
1774 smtp_state->cmds_cnt != 1 ||
1775 smtp_state->cmds_idx != 0 ||
1776 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
1777 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
1778 printf("smtp parser in inconsistent state\n");
1779 goto end;
1780 }
1781
cd3e32ce 1782 SCMutexLock(&f.m);
429c6388
AS
1783 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
1784 reply1, reply1_len);
576ec7da
AS
1785 if (r != 0) {
1786 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 1787 SCMutexUnlock(&f.m);
576ec7da
AS
1788 goto end;
1789 }
cd3e32ce 1790 SCMutexUnlock(&f.m);
576ec7da 1791 if (smtp_state->input_len != 0 ||
576ec7da
AS
1792 smtp_state->cmds_cnt != 0 ||
1793 smtp_state->cmds_idx != 0 ||
1794 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
1795 printf("smtp parser in inconsistent state\n");
1796 goto end;
1797 }
1798
cd3e32ce 1799 SCMutexLock(&f.m);
429c6388
AS
1800 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
1801 request2, request2_len);
576ec7da
AS
1802 if (r != 0) {
1803 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 1804 SCMutexUnlock(&f.m);
576ec7da
AS
1805 goto end;
1806 }
cd3e32ce 1807 SCMutexUnlock(&f.m);
576ec7da 1808 if (smtp_state->input_len != 0 ||
576ec7da
AS
1809 smtp_state->cmds_cnt != 1 ||
1810 smtp_state->cmds_idx != 0 ||
1811 smtp_state->cmds[0] != SMTP_COMMAND_STARTTLS ||
1812 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
1813 printf("smtp parser in inconsistent state\n");
1814 goto end;
1815 }
1816
cd3e32ce 1817 SCMutexLock(&f.m);
429c6388
AS
1818 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
1819 reply2, reply2_len);
576ec7da
AS
1820 if (r != 0) {
1821 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 1822 SCMutexUnlock(&f.m);
576ec7da
AS
1823 goto end;
1824 }
cd3e32ce 1825 SCMutexUnlock(&f.m);
576ec7da 1826 if (smtp_state->input_len != 0 ||
576ec7da
AS
1827 smtp_state->cmds_cnt != 0 ||
1828 smtp_state->cmds_idx != 0 ||
1829 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
1830 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
1831 printf("smtp parser in inconsistent state\n");
1832 goto end;
1833 }
1834
1835 if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION) ||
c1558f5a 1836 !(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) ||
576ec7da
AS
1837 !(((TcpSession *)f.protoctx)->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) ||
1838 !(((TcpSession *)f.protoctx)->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) {
1839 goto end;
1840 }
1841
1842 result = 1;
1843end:
429c6388 1844 if (alp_tctx != NULL)
fdefb65b 1845 AppLayerParserThreadCtxFree(alp_tctx);
576ec7da
AS
1846 StreamTcpFreeConfig(TRUE);
1847 FLOW_DESTROY(&f);
1848 return result;
1849}
1850
1851/**
1852 * \test Test multiple DATA commands(full mail transactions).
1853 */
1854int SMTPParserTest02(void)
1855{
1856 int result = 0;
1857 Flow f;
1858 int r = 0;
1859
1860 /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */
1861 uint8_t welcome_reply[] = {
1862 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67,
1863 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
1864 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20,
1865 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36,
1866 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36,
1867 0x0d, 0x0a
1868 };
1869 uint32_t welcome_reply_len = sizeof(welcome_reply);
1870
1871 /* EHLO boo.com<CR><LF> */
1872 uint8_t request1[] = {
1873 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
1874 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a
1875 };
1876 uint32_t request1_len = sizeof(request1);
1877 /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF>
1878 * 250-SIZE 35882577<CR><LF>
1879 * 250-8BITMIME<CR><LF>
1880 * 250-STARTTLS<CR><LF>
1881 * 250 ENHANCEDSTATUSCODES<CR><LF>
1882 */
1883 uint8_t reply1[] = {
1884 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e,
1885 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
1886 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
1887 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d,
1888 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50,
1889 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d,
1890 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a,
1891 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30,
1892 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
1893 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35,
1894 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a,
1895 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41,
1896 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54,
1897 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d,
1898 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49,
1899 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32,
1900 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a
1901 };
1902 uint32_t reply1_len = sizeof(reply1);
1903
1904 /* MAIL FROM:asdff@asdf.com<CR><LF> */
1905 uint8_t request2[] = {
1906 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
1907 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40,
1908 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
1909 0x0d, 0x0a
1910 };
1911 uint32_t request2_len = sizeof(request2);
1912 /* 250 2.1.0 Ok<CR><LF> */
1913 uint8_t reply2[] = {
1914 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
1915 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
1916 };
1917 uint32_t reply2_len = sizeof(reply2);
1918
1919 /* RCPT TO:bimbs@gmail.com<CR><LF> */
1920 uint8_t request3[] = {
1921 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a,
1922 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d,
1923 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d,
1924 0x0a
1925 };
1926 uint32_t request3_len = sizeof(request3);
1927 /* 250 2.1.5 Ok<CR><LF> */
1928 uint8_t reply3[] = {
1929 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
1930 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
1931 };
1932 uint32_t reply3_len = sizeof(reply3);
1933
1934 /* DATA<CR><LF> */
1935 uint8_t request4[] = {
1936 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a
1937 };
1938 uint32_t request4_len = sizeof(request4);
1939 /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */
1940 uint8_t reply4[] = {
1941 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20,
1942 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74,
1943 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c,
1944 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c,
1945 0x4c, 0x46, 0x3e, 0x0d, 0x0a
1946 };
1947 uint32_t reply4_len = sizeof(reply4);
1948
1949 /* FROM:asdff@asdf.com<CR><LF> */
1950 uint8_t request5_1[] = {
1951 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64,
1952 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e,
1953 0x63, 0x6f, 0x6d, 0x0d, 0x0a
1954 };
1955 uint32_t request5_1_len = sizeof(request5_1);
1956 /* TO:bimbs@gmail.com<CR><LF> */
1957 uint8_t request5_2[] = {
1958 0x54, 0x4f, 0x3a, 0x62, 0x69, 0x6d, 0x62, 0x73,
1959 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63,
1960 0x6f, 0x6d, 0x0d, 0x0a
1961 };
1962 uint32_t request5_2_len = sizeof(request5_2);
1963 /* <CR><LF> */
1964 uint8_t request5_3[] = {
1965 0x0d, 0x0a
1966 };
1967 uint32_t request5_3_len = sizeof(request5_3);
1968 /* this is test mail1<CR><LF> */
1969 uint8_t request5_4[] = {
1970 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
1971 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x69,
1972 0x6c, 0x31, 0x0d, 0x0a
1973 };
1974 uint32_t request5_4_len = sizeof(request5_4);
1975 /* .<CR><LF> */
1976 uint8_t request5_5[] = {
1977 0x2e, 0x0d, 0x0a
1978 };
1979 uint32_t request5_5_len = sizeof(request5_5);
1980 /* 250 2.0.0 Ok: queued as 6A1AF20BF2<CR><LF> */
1981 uint8_t reply5[] = {
1982 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e,
1983 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75,
1984 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
1985 0x36, 0x41, 0x31, 0x41, 0x46, 0x32, 0x30, 0x42,
1986 0x46, 0x32, 0x0d, 0x0a
1987 };
1988 uint32_t reply5_len = sizeof(reply5);
1989
1990 /* MAIL FROM:asdfg@asdf.com<CR><LF> */
1991 uint8_t request6[] = {
1992 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
1993 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x67, 0x40,
1994 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
1995 0x0d, 0x0a
1996 };
1997 uint32_t request6_len = sizeof(request6);
1998 /* 250 2.1.0 Ok<CR><LF> */
1999 uint8_t reply6[] = {
2000 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
2001 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
2002 };
2003 uint32_t reply6_len = sizeof(reply6);
2004
2005 /* RCPT TO:bimbs@gmail.com<CR><LF> */
2006 uint8_t request7[] = {
2007 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a,
2008 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d,
2009 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d,
2010 0x0a
2011 };
2012 uint32_t request7_len = sizeof(request7);
2013 /* 250 2.1.5 Ok<CR><LF> */
2014 uint8_t reply7[] = {
2015 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
2016 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
2017 };
2018 uint32_t reply7_len = sizeof(reply7);
2019
2020 /* DATA<CR><LF> */
2021 uint8_t request8[] = {
2022 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a
2023 };
2024 uint32_t request8_len = sizeof(request8);
2025 /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */
2026 uint8_t reply8[] = {
2027 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20,
2028 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74,
2029 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c,
2030 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c,
2031 0x4c, 0x46, 0x3e, 0x0d, 0x0a
2032 };
2033 uint32_t reply8_len = sizeof(reply8);
2034
2035 /* FROM:asdfg@gmail.com<CR><LF> */
2036 uint8_t request9_1[] = {
2037 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64,
2038 0x66, 0x67, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c,
2039 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a
2040 };
2041 uint32_t request9_1_len = sizeof(request9_1);
2042 /* TO:bimbs@gmail.com<CR><LF> */
2043 uint8_t request9_2[] = {
2044 0x54, 0x4f, 0x3a, 0x62, 0x69, 0x6d, 0x62, 0x73,
2045 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63,
2046 0x6f, 0x6d, 0x0d, 0x0a
2047 };
2048 uint32_t request9_2_len = sizeof(request9_2);
2049 /* <CR><LF> */
2050 uint8_t request9_3[] = {
2051 0x0d, 0x0a
2052 };
2053 uint32_t request9_3_len = sizeof(request9_3);
2054 /* this is test mail2<CR><LF> */
2055 uint8_t request9_4[] = {
2056 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
2057 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x69,
2058 0x6c, 0x32, 0x0d, 0x0a
2059 };
2060 uint32_t request9_4_len = sizeof(request9_4);
2061 /* .<CR><LF> */
2062 uint8_t request9_5[] = {
2063 0x2e, 0x0d, 0x0a
2064 };
2065 uint32_t request9_5_len = sizeof(request9_5);
2066 /* 250 2.0.0 Ok: queued as 28CFF20BF2<CR><LF> */
2067 uint8_t reply9[] = {
2068 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e,
2069 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75,
2070 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
2071 0x32, 0x38, 0x43, 0x46, 0x46, 0x32, 0x30, 0x42,
2072 0x46, 0x32, 0x0d, 0x0a
2073 };
2074 uint32_t reply9_len = sizeof(reply9);
2075
2076 /* QUIT<CR><LF> */
2077 uint8_t request10[] = {
2078 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a
2079 };
2080 uint32_t request10_len = sizeof(request10);
2081 /* 221 2.0.0 Bye<CR><LF> */
2082 uint8_t reply10[] = {
2083 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e,
2084 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a
2085 };
2086 uint32_t reply10_len = sizeof(reply10);
2087
2088 TcpSession ssn;
8dbf7a0d 2089 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
576ec7da
AS
2090
2091 memset(&f, 0, sizeof(f));
2092 memset(&ssn, 0, sizeof(ssn));
2093
2094 FLOW_INITIALIZE(&f);
2095 f.protoctx = (void *)&ssn;
429c6388 2096 f.proto = IPPROTO_TCP;
576ec7da
AS
2097
2098 StreamTcpInitConfig(TRUE);
576ec7da 2099
cd3e32ce 2100 SCMutexLock(&f.m);
429c6388
AS
2101 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2102 welcome_reply, welcome_reply_len);
576ec7da
AS
2103 if (r != 0) {
2104 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2105 SCMutexUnlock(&f.m);
576ec7da
AS
2106 goto end;
2107 }
cd3e32ce 2108 SCMutexUnlock(&f.m);
06904c90 2109 SMTPState *smtp_state = f.alstate;
576ec7da
AS
2110 if (smtp_state == NULL) {
2111 printf("no smtp state: ");
2112 goto end;
2113 }
2114 if (smtp_state->input_len != 0 ||
0d7159b5 2115 smtp_state->cmds_cnt != 0 ||
576ec7da 2116 smtp_state->cmds_idx != 0 ||
0d7159b5 2117 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
576ec7da
AS
2118 printf("smtp parser in inconsistent state\n");
2119 goto end;
2120 }
2121
cd3e32ce 2122 SCMutexLock(&f.m);
429c6388
AS
2123 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2124 request1, request1_len);
576ec7da
AS
2125 if (r != 0) {
2126 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2127 SCMutexUnlock(&f.m);
576ec7da
AS
2128 goto end;
2129 }
cd3e32ce 2130 SCMutexUnlock(&f.m);
576ec7da 2131 if (smtp_state->input_len != 0 ||
576ec7da
AS
2132 smtp_state->cmds_cnt != 1 ||
2133 smtp_state->cmds_idx != 0 ||
2134 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2135 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2136 printf("smtp parser in inconsistent state\n");
2137 goto end;
2138 }
2139
cd3e32ce 2140 SCMutexLock(&f.m);
429c6388
AS
2141 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2142 reply1, reply1_len);
576ec7da
AS
2143 if (r != 0) {
2144 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2145 SCMutexUnlock(&f.m);
576ec7da
AS
2146 goto end;
2147 }
cd3e32ce 2148 SCMutexUnlock(&f.m);
576ec7da 2149 if (smtp_state->input_len != 0 ||
576ec7da
AS
2150 smtp_state->cmds_cnt != 0 ||
2151 smtp_state->cmds_idx != 0 ||
2152 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2153 printf("smtp parser in inconsistent state\n");
2154 goto end;
2155 }
2156
cd3e32ce 2157 SCMutexLock(&f.m);
429c6388
AS
2158 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2159 request2, request2_len);
576ec7da
AS
2160 if (r != 0) {
2161 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2162 SCMutexUnlock(&f.m);
576ec7da
AS
2163 goto end;
2164 }
cd3e32ce 2165 SCMutexUnlock(&f.m);
576ec7da 2166 if (smtp_state->input_len != 0 ||
576ec7da
AS
2167 smtp_state->cmds_cnt != 1 ||
2168 smtp_state->cmds_idx != 0 ||
2169 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2170 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2171 printf("smtp parser in inconsistent state\n");
2172 goto end;
2173 }
2174
cd3e32ce 2175 SCMutexLock(&f.m);
429c6388
AS
2176 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2177 reply2, reply2_len);
576ec7da
AS
2178 if (r != 0) {
2179 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2180 SCMutexUnlock(&f.m);
576ec7da
AS
2181 goto end;
2182 }
cd3e32ce 2183 SCMutexUnlock(&f.m);
576ec7da 2184 if (smtp_state->input_len != 0 ||
576ec7da
AS
2185 smtp_state->cmds_cnt != 0 ||
2186 smtp_state->cmds_idx != 0 ||
2187 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2188 printf("smtp parser in inconsistent state\n");
2189 goto end;
2190 }
2191
cd3e32ce 2192 SCMutexLock(&f.m);
429c6388
AS
2193 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2194 request3, request3_len);
576ec7da
AS
2195 if (r != 0) {
2196 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2197 SCMutexUnlock(&f.m);
576ec7da
AS
2198 goto end;
2199 }
cd3e32ce 2200 SCMutexUnlock(&f.m);
576ec7da 2201 if (smtp_state->input_len != 0 ||
576ec7da
AS
2202 smtp_state->cmds_cnt != 1 ||
2203 smtp_state->cmds_idx != 0 ||
2204 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2205 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2206 printf("smtp parser in inconsistent state\n");
2207 goto end;
2208 }
2209
cd3e32ce 2210 SCMutexLock(&f.m);
429c6388
AS
2211 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2212 reply3, reply3_len);
576ec7da
AS
2213 if (r != 0) {
2214 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2215 SCMutexUnlock(&f.m);
576ec7da
AS
2216 goto end;
2217 }
cd3e32ce 2218 SCMutexUnlock(&f.m);
576ec7da 2219 if (smtp_state->input_len != 0 ||
576ec7da
AS
2220 smtp_state->cmds_cnt != 0 ||
2221 smtp_state->cmds_idx != 0 ||
2222 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2223 printf("smtp parser in inconsistent state\n");
2224 goto end;
2225 }
2226
cd3e32ce 2227 SCMutexLock(&f.m);
429c6388
AS
2228 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2229 request4, request4_len);
576ec7da
AS
2230 if (r != 0) {
2231 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2232 SCMutexUnlock(&f.m);
576ec7da
AS
2233 goto end;
2234 }
cd3e32ce 2235 SCMutexUnlock(&f.m);
576ec7da 2236 if (smtp_state->input_len != 0 ||
576ec7da
AS
2237 smtp_state->cmds_cnt != 1 ||
2238 smtp_state->cmds_idx != 0 ||
2239 smtp_state->cmds[0] != SMTP_COMMAND_DATA ||
2240 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2241 printf("smtp parser in inconsistent state\n");
2242 goto end;
2243 }
2244
cd3e32ce 2245 SCMutexLock(&f.m);
429c6388
AS
2246 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2247 reply4, reply4_len);
576ec7da
AS
2248 if (r != 0) {
2249 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2250 SCMutexUnlock(&f.m);
576ec7da
AS
2251 goto end;
2252 }
cd3e32ce 2253 SCMutexUnlock(&f.m);
576ec7da 2254 if (smtp_state->input_len != 0 ||
576ec7da
AS
2255 smtp_state->cmds_cnt != 0 ||
2256 smtp_state->cmds_idx != 0 ||
2257 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2258 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2259 printf("smtp parser in inconsistent state\n");
2260 goto end;
2261 }
2262
cd3e32ce 2263 SCMutexLock(&f.m);
429c6388
AS
2264 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2265 request5_1, request5_1_len);
576ec7da
AS
2266 if (r != 0) {
2267 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2268 SCMutexUnlock(&f.m);
576ec7da
AS
2269 goto end;
2270 }
cd3e32ce 2271 SCMutexUnlock(&f.m);
576ec7da 2272 if (smtp_state->input_len != 0 ||
576ec7da
AS
2273 smtp_state->cmds_cnt != 0 ||
2274 smtp_state->cmds_idx != 0 ||
2275 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2276 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2277
2278 printf("smtp parser in inconsistent state\n");
2279 goto end;
2280 }
2281
cd3e32ce 2282 SCMutexLock(&f.m);
429c6388
AS
2283 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2284 request5_2, request5_2_len);
576ec7da
AS
2285 if (r != 0) {
2286 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2287 SCMutexUnlock(&f.m);
576ec7da
AS
2288 goto end;
2289 }
cd3e32ce 2290 SCMutexUnlock(&f.m);
576ec7da 2291 if (smtp_state->input_len != 0 ||
576ec7da
AS
2292 smtp_state->cmds_cnt != 0 ||
2293 smtp_state->cmds_idx != 0 ||
2294 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2295 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2296
2297 printf("smtp parser in inconsistent state\n");
2298 goto end;
2299 }
2300
cd3e32ce 2301 SCMutexLock(&f.m);
429c6388
AS
2302 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2303 request5_3, request5_3_len);
576ec7da
AS
2304 if (r != 0) {
2305 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2306 SCMutexUnlock(&f.m);
576ec7da
AS
2307 goto end;
2308 }
cd3e32ce 2309 SCMutexUnlock(&f.m);
576ec7da 2310 if (smtp_state->input_len != 0 ||
576ec7da
AS
2311 smtp_state->cmds_cnt != 0 ||
2312 smtp_state->cmds_idx != 0 ||
2313 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2314 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2315
2316 printf("smtp parser in inconsistent state\n");
2317 goto end;
2318 }
2319
cd3e32ce 2320 SCMutexLock(&f.m);
429c6388
AS
2321 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2322 request5_4, request5_4_len);
576ec7da
AS
2323 if (r != 0) {
2324 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2325 SCMutexUnlock(&f.m);
576ec7da
AS
2326 goto end;
2327 }
cd3e32ce 2328 SCMutexUnlock(&f.m);
576ec7da 2329 if (smtp_state->input_len != 0 ||
576ec7da
AS
2330 smtp_state->cmds_cnt != 0 ||
2331 smtp_state->cmds_idx != 0 ||
2332 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2333 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2334
2335 printf("smtp parser in inconsistent state\n");
2336 goto end;
2337 }
2338
cd3e32ce 2339 SCMutexLock(&f.m);
429c6388
AS
2340 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2341 request5_5, request5_5_len);
576ec7da
AS
2342 if (r != 0) {
2343 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2344 SCMutexUnlock(&f.m);
576ec7da
AS
2345 goto end;
2346 }
cd3e32ce 2347 SCMutexUnlock(&f.m);
576ec7da 2348 if (smtp_state->input_len != 0 ||
576ec7da
AS
2349 smtp_state->cmds_cnt != 1 ||
2350 smtp_state->cmds_idx != 0 ||
2351 smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE ||
2352 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2353 printf("smtp parser in inconsistent state\n");
2354 goto end;
2355 }
2356
cd3e32ce 2357 SCMutexLock(&f.m);
429c6388
AS
2358 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2359 reply5, reply5_len);
576ec7da
AS
2360 if (r != 0) {
2361 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2362 SCMutexUnlock(&f.m);
576ec7da
AS
2363 goto end;
2364 }
cd3e32ce 2365 SCMutexUnlock(&f.m);
576ec7da 2366 if (smtp_state->input_len != 0 ||
576ec7da
AS
2367 smtp_state->cmds_cnt != 0 ||
2368 smtp_state->cmds_idx != 0 ||
2369 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2370 printf("smtp parser in inconsistent state\n");
2371 goto end;
2372 }
2373
cd3e32ce 2374 SCMutexLock(&f.m);
429c6388
AS
2375 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2376 request6, request6_len);
576ec7da
AS
2377 if (r != 0) {
2378 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2379 SCMutexUnlock(&f.m);
576ec7da
AS
2380 goto end;
2381 }
cd3e32ce 2382 SCMutexUnlock(&f.m);
576ec7da 2383 if (smtp_state->input_len != 0 ||
576ec7da
AS
2384 smtp_state->cmds_cnt != 1 ||
2385 smtp_state->cmds_idx != 0 ||
2386 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2387 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2388 printf("smtp parser in inconsistent state\n");
2389 goto end;
2390 }
2391
cd3e32ce 2392 SCMutexLock(&f.m);
429c6388
AS
2393 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2394 reply6, reply6_len);
576ec7da
AS
2395 if (r != 0) {
2396 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2397 SCMutexUnlock(&f.m);
576ec7da
AS
2398 goto end;
2399 }
cd3e32ce 2400 SCMutexUnlock(&f.m);
576ec7da 2401 if (smtp_state->input_len != 0 ||
576ec7da
AS
2402 smtp_state->cmds_cnt != 0 ||
2403 smtp_state->cmds_idx != 0 ||
2404 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2405 printf("smtp parser in inconsistent state\n");
2406 goto end;
2407 }
2408
cd3e32ce 2409 SCMutexLock(&f.m);
429c6388
AS
2410 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2411 request7, request7_len);
576ec7da
AS
2412 if (r != 0) {
2413 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2414 SCMutexUnlock(&f.m);
576ec7da
AS
2415 goto end;
2416 }
cd3e32ce 2417 SCMutexUnlock(&f.m);
576ec7da 2418 if (smtp_state->input_len != 0 ||
576ec7da
AS
2419 smtp_state->cmds_cnt != 1 ||
2420 smtp_state->cmds_idx != 0 ||
2421 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2422 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2423 printf("smtp parser in inconsistent state\n");
2424 goto end;
2425 }
2426
cd3e32ce 2427 SCMutexLock(&f.m);
429c6388
AS
2428 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2429 reply7, reply7_len);
576ec7da
AS
2430 if (r != 0) {
2431 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2432 SCMutexUnlock(&f.m);
576ec7da
AS
2433 goto end;
2434 }
cd3e32ce 2435 SCMutexUnlock(&f.m);
576ec7da 2436 if (smtp_state->input_len != 0 ||
576ec7da
AS
2437 smtp_state->cmds_cnt != 0 ||
2438 smtp_state->cmds_idx != 0 ||
2439 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2440 printf("smtp parser in inconsistent state\n");
2441 goto end;
2442 }
2443
cd3e32ce 2444 SCMutexLock(&f.m);
429c6388
AS
2445 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2446 request8, request8_len);
576ec7da
AS
2447 if (r != 0) {
2448 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2449 SCMutexUnlock(&f.m);
576ec7da
AS
2450 goto end;
2451 }
cd3e32ce 2452 SCMutexUnlock(&f.m);
576ec7da 2453 if (smtp_state->input_len != 0 ||
576ec7da
AS
2454 smtp_state->cmds_cnt != 1 ||
2455 smtp_state->cmds_idx != 0 ||
2456 smtp_state->cmds[0] != SMTP_COMMAND_DATA ||
2457 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2458 printf("smtp parser in inconsistent state\n");
2459 goto end;
2460 }
2461
cd3e32ce 2462 SCMutexLock(&f.m);
429c6388
AS
2463 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2464 reply8, reply8_len);
576ec7da
AS
2465 if (r != 0) {
2466 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2467 SCMutexUnlock(&f.m);
576ec7da
AS
2468 goto end;
2469 }
cd3e32ce 2470 SCMutexUnlock(&f.m);
576ec7da 2471 if (smtp_state->input_len != 0 ||
576ec7da
AS
2472 smtp_state->cmds_cnt != 0 ||
2473 smtp_state->cmds_idx != 0 ||
2474 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2475 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2476 printf("smtp parser in inconsistent state\n");
2477 goto end;
2478 }
2479
cd3e32ce 2480 SCMutexLock(&f.m);
429c6388
AS
2481 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2482 request9_1, request9_1_len);
576ec7da
AS
2483 if (r != 0) {
2484 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2485 SCMutexUnlock(&f.m);
576ec7da
AS
2486 goto end;
2487 }
cd3e32ce 2488 SCMutexUnlock(&f.m);
576ec7da 2489 if (smtp_state->input_len != 0 ||
576ec7da
AS
2490 smtp_state->cmds_cnt != 0 ||
2491 smtp_state->cmds_idx != 0 ||
2492 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2493 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2494
2495 printf("smtp parser in inconsistent state\n");
2496 goto end;
2497 }
2498
cd3e32ce 2499 SCMutexLock(&f.m);
429c6388
AS
2500 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2501 request9_2, request9_2_len);
576ec7da
AS
2502 if (r != 0) {
2503 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2504 SCMutexUnlock(&f.m);
576ec7da
AS
2505 goto end;
2506 }
cd3e32ce 2507 SCMutexUnlock(&f.m);
576ec7da 2508 if (smtp_state->input_len != 0 ||
576ec7da
AS
2509 smtp_state->cmds_cnt != 0 ||
2510 smtp_state->cmds_idx != 0 ||
2511 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2512 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2513
2514 printf("smtp parser in inconsistent state\n");
2515 goto end;
2516 }
2517
cd3e32ce 2518 SCMutexLock(&f.m);
429c6388
AS
2519 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2520 request9_3, request9_3_len);
576ec7da
AS
2521 if (r != 0) {
2522 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2523 SCMutexUnlock(&f.m);
576ec7da
AS
2524 goto end;
2525 }
cd3e32ce 2526 SCMutexUnlock(&f.m);
576ec7da 2527 if (smtp_state->input_len != 0 ||
576ec7da
AS
2528 smtp_state->cmds_cnt != 0 ||
2529 smtp_state->cmds_idx != 0 ||
2530 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2531 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2532
2533 printf("smtp parser in inconsistent state\n");
2534 goto end;
2535 }
2536
cd3e32ce 2537 SCMutexLock(&f.m);
429c6388
AS
2538 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2539 request9_4, request9_4_len);
576ec7da
AS
2540 if (r != 0) {
2541 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2542 SCMutexUnlock(&f.m);
576ec7da
AS
2543 goto end;
2544 }
cd3e32ce 2545 SCMutexUnlock(&f.m);
576ec7da 2546 if (smtp_state->input_len != 0 ||
576ec7da
AS
2547 smtp_state->cmds_cnt != 0 ||
2548 smtp_state->cmds_idx != 0 ||
2549 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2550 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2551
2552 printf("smtp parser in inconsistent state\n");
2553 goto end;
2554 }
2555
cd3e32ce 2556 SCMutexLock(&f.m);
429c6388
AS
2557 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2558 request9_5, request9_5_len);
576ec7da
AS
2559 if (r != 0) {
2560 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2561 SCMutexUnlock(&f.m);
576ec7da
AS
2562 goto end;
2563 }
cd3e32ce 2564 SCMutexUnlock(&f.m);
576ec7da 2565 if (smtp_state->input_len != 0 ||
576ec7da
AS
2566 smtp_state->cmds_cnt != 1 ||
2567 smtp_state->cmds_idx != 0 ||
2568 smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE ||
2569 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2570 printf("smtp parser in inconsistent state\n");
2571 goto end;
2572 }
2573
cd3e32ce 2574 SCMutexLock(&f.m);
429c6388
AS
2575 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2576 reply9, reply9_len);
576ec7da
AS
2577 if (r != 0) {
2578 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2579 SCMutexUnlock(&f.m);
576ec7da
AS
2580 goto end;
2581 }
cd3e32ce 2582 SCMutexUnlock(&f.m);
576ec7da 2583 if (smtp_state->input_len != 0 ||
576ec7da
AS
2584 smtp_state->cmds_cnt != 0 ||
2585 smtp_state->cmds_idx != 0 ||
2586 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2587 printf("smtp parser in inconsistent state\n");
2588 goto end;
2589 }
2590
cd3e32ce 2591 SCMutexLock(&f.m);
429c6388
AS
2592 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2593 request10, request10_len);
576ec7da
AS
2594 if (r != 0) {
2595 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2596 SCMutexUnlock(&f.m);
576ec7da
AS
2597 goto end;
2598 }
cd3e32ce 2599 SCMutexUnlock(&f.m);
576ec7da 2600 if (smtp_state->input_len != 0 ||
576ec7da
AS
2601 smtp_state->cmds_cnt != 1 ||
2602 smtp_state->cmds_idx != 0 ||
2603 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2604 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2605 printf("smtp parser in inconsistent state\n");
2606 goto end;
2607 }
2608
cd3e32ce 2609 SCMutexLock(&f.m);
429c6388
AS
2610 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2611 reply10, reply10_len);
576ec7da
AS
2612 if (r != 0) {
2613 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2614 SCMutexUnlock(&f.m);
576ec7da
AS
2615 goto end;
2616 }
cd3e32ce 2617 SCMutexUnlock(&f.m);
576ec7da 2618 if (smtp_state->input_len != 0 ||
576ec7da
AS
2619 smtp_state->cmds_cnt != 0 ||
2620 smtp_state->cmds_idx != 0 ||
2621 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2622 printf("smtp parser in inconsistent state\n");
2623 goto end;
2624 }
2625
2626 result = 1;
2627end:
429c6388 2628 if (alp_tctx != NULL)
fdefb65b 2629 AppLayerParserThreadCtxFree(alp_tctx);
576ec7da
AS
2630 StreamTcpFreeConfig(TRUE);
2631 FLOW_DESTROY(&f);
2632 return result;
2633}
2634
2635/**
2636 * \test Testing parsing pipelined commands.
2637 */
2638int SMTPParserTest03(void)
2639{
2640 int result = 0;
2641 Flow f;
2642 int r = 0;
2643
2644 /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */
2645 uint8_t welcome_reply[] = {
2646 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e,
2647 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2648 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2649 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20,
2650 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f,
2651 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a
2652 };
2653 uint32_t welcome_reply_len = sizeof(welcome_reply);
2654
2655 /* EHLO boo.com<CR><LF> */
2656 uint8_t request1[] = {
2657 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
2658 0x2e, 0x63, 0x6f, 0x6d, 0x0a
2659 };
2660 uint32_t request1_len = sizeof(request1);
2661 /* 250-poona_slack_vm1.localdomain<CR><LF>
2662 * 250-PIPELINING<CR><LF>
2663 * 250-SIZE 10240000<CR><LF>
2664 * 250-VRFY<CR><LF>
2665 * 250-ETRN<CR><LF>
2666 * 250-ENHANCEDSTATUSCODES<CR><LF>
2667 * 250-8BITMIME<CR><LF>
2668 * 250 DSN<CR><LF>
2669 */
2670 uint8_t reply1[] = {
2671 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e,
2672 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2673 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2674 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d,
2675 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50,
2676 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d,
2677 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a,
2678 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30,
2679 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
2680 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35,
2681 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a,
2682 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41,
2683 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54,
2684 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d,
2685 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49,
2686 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32,
2687 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a
2688 };
2689 uint32_t reply1_len = sizeof(reply1);
2690
2691 /* MAIL FROM:pbsf@asdfs.com<CR><LF>
2692 * RCPT TO:pbsf@asdfs.com<CR><LF>
2693 * DATA<CR><LF>
2694 */
2695 uint8_t request2[] = {
2696 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
2697 0x4d, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61,
2698 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
2699 0x0d, 0x0a, 0x52, 0x43, 0x50, 0x54, 0x20, 0x54,
2700 0x4f, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61,
2701 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
2702 0x0d, 0x0a, 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a
2703 };
2704 uint32_t request2_len = sizeof(request2);
2705 /* 250 2.1.0 Ok<CR><LF>
2706 * 250 2.1.5 Ok<CR><LF>
2707 * 354 End data with <CR><LF>.<CR><LF>|<CR><LF>|
2708 */
2709 uint8_t reply2[] = {
2710 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
2711 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a, 0x32, 0x35,
2712 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, 0x35, 0x20,
2713 0x4f, 0x6b, 0x0d, 0x0a, 0x33, 0x35, 0x34, 0x20,
2714 0x45, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61,
2715 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x3c, 0x43,
2716 0x52, 0x3e, 0x3c, 0x4c, 0x46, 0x3e, 0x2e, 0x3c,
2717 0x43, 0x52, 0x3e, 0x3c, 0x4c, 0x46, 0x3e, 0x0d,
2718 0x0a
2719 };
2720 uint32_t reply2_len = sizeof(reply2);
2721
2722 TcpSession ssn;
8dbf7a0d 2723 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
576ec7da
AS
2724
2725 memset(&f, 0, sizeof(f));
2726 memset(&ssn, 0, sizeof(ssn));
2727
2728 FLOW_INITIALIZE(&f);
2729 f.protoctx = (void *)&ssn;
429c6388 2730 f.proto = IPPROTO_TCP;
576ec7da
AS
2731
2732 StreamTcpInitConfig(TRUE);
576ec7da 2733
cd3e32ce 2734 SCMutexLock(&f.m);
429c6388
AS
2735 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2736 welcome_reply, welcome_reply_len);
576ec7da
AS
2737 if (r != 0) {
2738 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2739 SCMutexUnlock(&f.m);
576ec7da
AS
2740 goto end;
2741 }
cd3e32ce 2742 SCMutexUnlock(&f.m);
06904c90 2743 SMTPState *smtp_state = f.alstate;
576ec7da
AS
2744 if (smtp_state == NULL) {
2745 printf("no smtp state: ");
2746 goto end;
2747 }
2748 if (smtp_state->input_len != 0 ||
0d7159b5 2749 smtp_state->cmds_cnt != 0 ||
576ec7da 2750 smtp_state->cmds_idx != 0 ||
0d7159b5 2751 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
576ec7da
AS
2752 printf("smtp parser in inconsistent state\n");
2753 goto end;
2754 }
2755
cd3e32ce 2756 SCMutexLock(&f.m);
429c6388
AS
2757 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2758 request1, request1_len);
576ec7da
AS
2759 if (r != 0) {
2760 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2761 SCMutexUnlock(&f.m);
576ec7da
AS
2762 goto end;
2763 }
cd3e32ce 2764 SCMutexUnlock(&f.m);
576ec7da 2765 if (smtp_state->input_len != 0 ||
576ec7da
AS
2766 smtp_state->cmds_cnt != 1 ||
2767 smtp_state->cmds_idx != 0 ||
2768 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2769 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2770 printf("smtp parser in inconsistent state\n");
2771 goto end;
2772 }
2773
cd3e32ce 2774 SCMutexLock(&f.m);
429c6388
AS
2775 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2776 reply1, reply1_len);
576ec7da
AS
2777 if (r != 0) {
2778 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2779 SCMutexUnlock(&f.m);
576ec7da
AS
2780 goto end;
2781 }
cd3e32ce 2782 SCMutexUnlock(&f.m);
576ec7da 2783 if (smtp_state->input_len != 0 ||
576ec7da
AS
2784 smtp_state->cmds_cnt != 0 ||
2785 smtp_state->cmds_idx != 0 ||
2786 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2787 printf("smtp parser in inconsistent state\n");
2788 goto end;
2789 }
2790
cd3e32ce 2791 SCMutexLock(&f.m);
429c6388
AS
2792 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2793 request2, request2_len);
576ec7da
AS
2794 if (r != 0) {
2795 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2796 SCMutexUnlock(&f.m);
576ec7da
AS
2797 goto end;
2798 }
cd3e32ce 2799 SCMutexUnlock(&f.m);
576ec7da 2800 if (smtp_state->input_len != 0 ||
576ec7da
AS
2801 smtp_state->cmds_cnt != 3 ||
2802 smtp_state->cmds_idx != 0 ||
2803 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2804 smtp_state->cmds[1] != SMTP_COMMAND_OTHER_CMD ||
2805 smtp_state->cmds[2] != SMTP_COMMAND_DATA ||
2806 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
2807 printf("smtp parser in inconsistent state\n");
2808 goto end;
2809 }
2810
cd3e32ce 2811 SCMutexLock(&f.m);
429c6388
AS
2812 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2813 reply2, reply2_len);
576ec7da
AS
2814 if (r != 0) {
2815 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2816 SCMutexUnlock(&f.m);
576ec7da
AS
2817 goto end;
2818 }
cd3e32ce 2819 SCMutexUnlock(&f.m);
576ec7da 2820 if (smtp_state->input_len != 0 ||
576ec7da
AS
2821 smtp_state->cmds_cnt != 0 ||
2822 smtp_state->cmds_idx != 0 ||
2823 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
2824 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
2825 printf("smtp parser in inconsistent state\n");
2826 goto end;
2827 }
2828
2829 result = 1;
2830end:
429c6388 2831 if (alp_tctx != NULL)
fdefb65b 2832 AppLayerParserThreadCtxFree(alp_tctx);
576ec7da
AS
2833 StreamTcpFreeConfig(TRUE);
2834 FLOW_DESTROY(&f);
2835 return result;
2836}
2837
2838/*
2839 * \test Test smtp with just <LF> delimter instead of <CR><LF>.
2840 */
2841int SMTPParserTest04(void)
2842{
2843 int result = 0;
2844 Flow f;
2845 int r = 0;
2846
2847 /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */
2848 uint8_t welcome_reply[] = {
2849 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e,
2850 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2851 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2852 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20,
2853 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f,
2854 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a
2855 };
2856 uint32_t welcome_reply_len = sizeof(welcome_reply);
2857
2858 /* EHLO boo.com<CR><LF> */
2859 uint8_t request1[] = {
2860 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e,
2861 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2862 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2863 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20,
2864 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f,
2865 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a
2866 };
2867 uint32_t request1_len = sizeof(request1);
2868
2869 TcpSession ssn;
8dbf7a0d 2870 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
576ec7da
AS
2871
2872 memset(&f, 0, sizeof(f));
2873 memset(&ssn, 0, sizeof(ssn));
2874
2875 FLOW_INITIALIZE(&f);
2876 f.protoctx = (void *)&ssn;
429c6388 2877 f.proto = IPPROTO_TCP;
576ec7da
AS
2878
2879 StreamTcpInitConfig(TRUE);
576ec7da 2880
cd3e32ce 2881 SCMutexLock(&f.m);
429c6388
AS
2882 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
2883 welcome_reply, welcome_reply_len);
576ec7da
AS
2884 if (r != 0) {
2885 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2886 SCMutexUnlock(&f.m);
576ec7da
AS
2887 goto end;
2888 }
cd3e32ce 2889 SCMutexUnlock(&f.m);
06904c90 2890 SMTPState *smtp_state = f.alstate;
576ec7da
AS
2891 if (smtp_state == NULL) {
2892 printf("no smtp state: ");
2893 goto end;
2894 }
2895 if (smtp_state->input_len != 0 ||
0d7159b5 2896 smtp_state->cmds_cnt != 0 ||
576ec7da 2897 smtp_state->cmds_idx != 0 ||
0d7159b5 2898 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
576ec7da
AS
2899 printf("smtp parser in inconsistent state\n");
2900 goto end;
2901 }
2902
cd3e32ce 2903 SCMutexLock(&f.m);
429c6388
AS
2904 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
2905 request1, request1_len);
576ec7da
AS
2906 if (r != 0) {
2907 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 2908 SCMutexUnlock(&f.m);
576ec7da
AS
2909 goto end;
2910 }
cd3e32ce 2911 SCMutexUnlock(&f.m);
576ec7da 2912 if (smtp_state->input_len != 0 ||
576ec7da
AS
2913 smtp_state->cmds_cnt != 1 ||
2914 smtp_state->cmds_idx != 0 ||
2915 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
2916 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
2917 printf("smtp parser in inconsistent state\n");
2918 goto end;
2919 }
2920
2921 result = 1;
2922end:
429c6388 2923 if (alp_tctx != NULL)
fdefb65b 2924 AppLayerParserThreadCtxFree(alp_tctx);
576ec7da
AS
2925 StreamTcpFreeConfig(TRUE);
2926 FLOW_DESTROY(&f);
2927 return result;
2928}
2929
2930/*
2931 * \test Test STARTTLS fail.
2932 */
2933int SMTPParserTest05(void)
2934{
2935 int result = 0;
2936 Flow f;
2937 int r = 0;
2938
2939 /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */
2940 uint8_t welcome_reply[] = {
2941 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e,
2942 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2943 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2944 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20,
2945 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f,
2946 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a
2947 };
2948 uint32_t welcome_reply_len = sizeof(welcome_reply);
2949
2950 /* EHLO boo.com<CR><LF> */
2951 uint8_t request1[] = {
2952 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
2953 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a
2954 };
2955 uint32_t request1_len = sizeof(request1);
2956 /* 250-poona_slack_vm1.localdomain<CR><LF>
2957 * 250-PIPELINING<CR><LF>
2958 * 250-SIZE 10240000<CR><LF>
2959 * 250-VRFY<CR><LF>
2960 * 250-ETRN<CR><LF>
2961 * 250-ENHANCEDSTATUSCODES<CR><LF>
2962 * 250-8BITMIME<CR><LF>
2963 * 250 DSN<CR><LF>
2964 */
2965 uint8_t reply1[] = {
2966 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e,
2967 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
2968 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
2969 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d,
2970 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50,
2971 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d,
2972 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a,
2973 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30,
2974 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
2975 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35,
2976 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a,
2977 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41,
2978 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54,
2979 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d,
2980 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49,
2981 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32,
2982 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a
2983 };
2984 uint32_t reply1_len = sizeof(reply1);
2985
2986 /* STARTTLS<CR><LF> */
2987 uint8_t request2[] = {
2988 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53,
2989 0x0d, 0x0a
2990 };
2991 uint32_t request2_len = sizeof(request2);
2992 /* 502 5.5.2 Error: command not recognized<CR><LF> */
2993 uint8_t reply2[] = {
2994 0x35, 0x30, 0x32, 0x20, 0x35, 0x2e, 0x35, 0x2e,
2995 0x32, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a,
2996 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
2997 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x63,
2998 0x6f, 0x67, 0x6e, 0x69, 0x7a, 0x65, 0x64, 0x0d,
2999 0x0a
3000 };
3001 uint32_t reply2_len = sizeof(reply2);
3002
3003 /* QUIT<CR><LF> */
3004 uint8_t request3[] = {
3005 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a
3006
3007 };
3008 uint32_t request3_len = sizeof(request3);
3009 /* 221 2.0.0 Bye<CR><LF> */
3010 uint8_t reply3[] = {
3011 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e,
3012 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a
3013 };
3014 uint32_t reply3_len = sizeof(reply3);
3015
3016 TcpSession ssn;
8dbf7a0d 3017 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
576ec7da
AS
3018
3019 memset(&f, 0, sizeof(f));
3020 memset(&ssn, 0, sizeof(ssn));
3021
3022 FLOW_INITIALIZE(&f);
3023 f.protoctx = (void *)&ssn;
429c6388 3024 f.proto = IPPROTO_TCP;
576ec7da
AS
3025
3026 StreamTcpInitConfig(TRUE);
576ec7da 3027
cd3e32ce 3028 SCMutexLock(&f.m);
429c6388
AS
3029 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3030 welcome_reply, welcome_reply_len);
576ec7da
AS
3031 if (r != 0) {
3032 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3033 SCMutexUnlock(&f.m);
576ec7da
AS
3034 goto end;
3035 }
cd3e32ce 3036 SCMutexUnlock(&f.m);
06904c90 3037 SMTPState *smtp_state = f.alstate;
576ec7da
AS
3038 if (smtp_state == NULL) {
3039 printf("no smtp state: ");
3040 goto end;
3041 }
3042 if (smtp_state->input_len != 0 ||
0d7159b5 3043 smtp_state->cmds_cnt != 0 ||
576ec7da 3044 smtp_state->cmds_idx != 0 ||
0d7159b5 3045 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
576ec7da
AS
3046 printf("smtp parser in inconsistent state\n");
3047 goto end;
3048 }
3049
cd3e32ce 3050 SCMutexLock(&f.m);
429c6388
AS
3051 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3052 request1, request1_len);
576ec7da
AS
3053 if (r != 0) {
3054 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3055 SCMutexUnlock(&f.m);
576ec7da
AS
3056 goto end;
3057 }
cd3e32ce 3058 SCMutexUnlock(&f.m);
576ec7da 3059 if (smtp_state->input_len != 0 ||
576ec7da
AS
3060 smtp_state->cmds_cnt != 1 ||
3061 smtp_state->cmds_idx != 0 ||
3062 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
3063 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3064 printf("smtp parser in inconsistent state\n");
3065 goto end;
3066 }
3067
cd3e32ce 3068 SCMutexLock(&f.m);
429c6388
AS
3069 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3070 reply1, reply1_len);
576ec7da
AS
3071 if (r != 0) {
3072 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3073 SCMutexUnlock(&f.m);
576ec7da
AS
3074 goto end;
3075 }
cd3e32ce 3076 SCMutexUnlock(&f.m);
576ec7da 3077 if (smtp_state->input_len != 0 ||
576ec7da
AS
3078 smtp_state->cmds_cnt != 0 ||
3079 smtp_state->cmds_idx != 0 ||
3080 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3081 printf("smtp parser in inconsistent state\n");
3082 goto end;
3083 }
3084
cd3e32ce 3085 SCMutexLock(&f.m);
429c6388
AS
3086 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3087 request2, request2_len);
576ec7da
AS
3088 if (r != 0) {
3089 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3090 SCMutexUnlock(&f.m);
576ec7da
AS
3091 goto end;
3092 }
cd3e32ce 3093 SCMutexUnlock(&f.m);
576ec7da 3094 if (smtp_state->input_len != 0 ||
576ec7da
AS
3095 smtp_state->cmds_cnt != 1 ||
3096 smtp_state->cmds_idx != 0 ||
3097 smtp_state->cmds[0] != SMTP_COMMAND_STARTTLS ||
3098 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3099 printf("smtp parser in inconsistent state\n");
3100 goto end;
3101 }
3102
cd3e32ce 3103 SCMutexLock(&f.m);
429c6388
AS
3104 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3105 reply2, reply2_len);
576ec7da
AS
3106 if (r != 0) {
3107 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3108 SCMutexUnlock(&f.m);
576ec7da
AS
3109 goto end;
3110 }
cd3e32ce 3111 SCMutexUnlock(&f.m);
576ec7da 3112 if (smtp_state->input_len != 0 ||
576ec7da
AS
3113 smtp_state->cmds_cnt != 0 ||
3114 smtp_state->cmds_idx != 0 ||
3115 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
3116 printf("smtp parser in inconsistent state\n");
3117 goto end;
3118 }
3119
3120 if ((f.flags & FLOW_NOPAYLOAD_INSPECTION) ||
c1558f5a 3121 (ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) ||
576ec7da
AS
3122 (((TcpSession *)f.protoctx)->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) ||
3123 (((TcpSession *)f.protoctx)->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) {
3124 goto end;
3125 }
3126
cd3e32ce 3127 SCMutexLock(&f.m);
429c6388
AS
3128 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3129 request3, request3_len);
576ec7da
AS
3130 if (r != 0) {
3131 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3132 SCMutexUnlock(&f.m);
576ec7da
AS
3133 goto end;
3134 }
cd3e32ce 3135 SCMutexUnlock(&f.m);
576ec7da 3136 if (smtp_state->input_len != 0 ||
576ec7da
AS
3137 smtp_state->cmds_cnt != 1 ||
3138 smtp_state->cmds_idx != 0 ||
3139 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
3140 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3141 printf("smtp parser in inconsistent state\n");
3142 goto end;
3143 }
3144
cd3e32ce 3145 SCMutexLock(&f.m);
429c6388
AS
3146 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3147 reply3, reply3_len);
576ec7da
AS
3148 if (r != 0) {
3149 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3150 SCMutexUnlock(&f.m);
576ec7da
AS
3151 goto end;
3152 }
cd3e32ce 3153 SCMutexUnlock(&f.m);
576ec7da 3154 if (smtp_state->input_len != 0 ||
576ec7da
AS
3155 smtp_state->cmds_cnt != 0 ||
3156 smtp_state->cmds_idx != 0 ||
3157 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
3158 printf("smtp parser in inconsistent state\n");
3159 goto end;
3160 }
3161
3162 result = 1;
3163end:
429c6388 3164 if (alp_tctx != NULL)
fdefb65b 3165 AppLayerParserThreadCtxFree(alp_tctx);
576ec7da
AS
3166 StreamTcpFreeConfig(TRUE);
3167 FLOW_DESTROY(&f);
3168 return result;
3169}
3170
d3ca65de
AS
3171/**
3172 * \test Test multiple DATA commands(full mail transactions).
3173 */
3174int SMTPParserTest06(void)
3175{
3176 int result = 0;
3177 Flow f;
3178 int r = 0;
3179
3180 uint8_t welcome_reply[] = {
3181 0x32, 0x32, 0x30, 0x20, 0x62, 0x61, 0x79, 0x30,
3182 0x2d, 0x6d, 0x63, 0x36, 0x2d, 0x66, 0x31, 0x30,
3183 0x2e, 0x62, 0x61, 0x79, 0x30, 0x2e, 0x68, 0x6f,
3184 0x74, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f,
3185 0x6d, 0x20, 0x53, 0x65, 0x6e, 0x64, 0x69, 0x6e,
3186 0x67, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x6c, 0x69,
3187 0x63, 0x69, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6f,
3188 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c,
3189 0x20, 0x6f, 0x72, 0x20, 0x62, 0x75, 0x6c, 0x6b,
3190 0x20, 0x65, 0x2d, 0x6d, 0x61, 0x69, 0x6c, 0x20,
3191 0x74, 0x6f, 0x20, 0x4d, 0x69, 0x63, 0x72, 0x6f,
3192 0x73, 0x6f, 0x66, 0x74, 0x27, 0x73, 0x20, 0x63,
3193 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20,
3194 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20,
3195 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x68, 0x69,
3196 0x62, 0x69, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x4f,
3197 0x74, 0x68, 0x65, 0x72, 0x20, 0x72, 0x65, 0x73,
3198 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e,
3199 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x6f,
3200 0x75, 0x6e, 0x64, 0x20, 0x61, 0x74, 0x20, 0x68,
3201 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x72,
3202 0x69, 0x76, 0x61, 0x63, 0x79, 0x2e, 0x6d, 0x73,
3203 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x6e,
3204 0x74, 0x69, 0x2d, 0x73, 0x70, 0x61, 0x6d, 0x2f,
3205 0x2e, 0x20, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74,
3206 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c,
3207 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
3208 0x20, 0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x20,
3209 0x6f, 0x66, 0x20, 0x65, 0x71, 0x75, 0x69, 0x70,
3210 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x63,
3211 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
3212 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e,
3213 0x69, 0x61, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
3214 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61,
3215 0x74, 0x65, 0x73, 0x2e, 0x20, 0x46, 0x72, 0x69,
3216 0x2c, 0x20, 0x31, 0x36, 0x20, 0x46, 0x65, 0x62,
3217 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x30, 0x35,
3218 0x3a, 0x30, 0x33, 0x3a, 0x32, 0x33, 0x20, 0x2d,
3219 0x30, 0x38, 0x30, 0x30, 0x20, 0x0d, 0x0a
3220 };
3221 uint32_t welcome_reply_len = sizeof(welcome_reply);
3222
3223 uint8_t request1[] = {
3224 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x45, 0x58, 0x43,
3225 0x48, 0x41, 0x4e, 0x47, 0x45, 0x32, 0x2e, 0x63,
3226 0x67, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x69,
3227 0x61, 0x6d, 0x69, 0x2e, 0x65, 0x64, 0x75, 0x0d,
3228 0x0a
3229 };
3230 uint32_t request1_len = sizeof(request1);
3231
3232 uint8_t reply1[] = {
3233 0x32, 0x35, 0x30, 0x2d, 0x62, 0x61, 0x79, 0x30,
3234 0x2d, 0x6d, 0x63, 0x36, 0x2d, 0x66, 0x31, 0x30,
3235 0x2e, 0x62, 0x61, 0x79, 0x30, 0x2e, 0x68, 0x6f,
3236 0x74, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f,
3237 0x6d, 0x20, 0x28, 0x33, 0x2e, 0x33, 0x2e, 0x31,
3238 0x2e, 0x34, 0x29, 0x20, 0x48, 0x65, 0x6c, 0x6c,
3239 0x6f, 0x20, 0x5b, 0x31, 0x32, 0x39, 0x2e, 0x31,
3240 0x37, 0x31, 0x2e, 0x33, 0x32, 0x2e, 0x35, 0x39,
3241 0x5d, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53,
3242 0x49, 0x5a, 0x45, 0x20, 0x32, 0x39, 0x36, 0x39,
3243 0x36, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35,
3244 0x30, 0x2d, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49,
3245 0x4e, 0x49, 0x4e, 0x47, 0x0d, 0x0a, 0x32, 0x35,
3246 0x30, 0x2d, 0x38, 0x62, 0x69, 0x74, 0x6d, 0x69,
3247 0x6d, 0x65, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
3248 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x4d, 0x49,
3249 0x4d, 0x45, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
3250 0x43, 0x48, 0x55, 0x4e, 0x4b, 0x49, 0x4e, 0x47,
3251 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x41, 0x55,
3252 0x54, 0x48, 0x20, 0x4c, 0x4f, 0x47, 0x49, 0x4e,
3253 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x41, 0x55,
3254 0x54, 0x48, 0x3d, 0x4c, 0x4f, 0x47, 0x49, 0x4e,
3255 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x20, 0x4f, 0x4b,
3256 0x0d, 0x0a
3257 };
3258 uint32_t reply1_len = sizeof(reply1);
3259
3260 /* MAIL FROM:asdff@asdf.com<CR><LF> */
3261 uint8_t request2[] = {
3262 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
3263 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40,
3264 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
3265 0x0d, 0x0a
3266 };
3267 uint32_t request2_len = sizeof(request2);
3268 /* 250 2.1.0 Ok<CR><LF> */
3269 uint8_t reply2[] = {
3270 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
3271 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
3272 };
3273 uint32_t reply2_len = sizeof(reply2);
3274
3275 /* RCPT TO:bimbs@gmail.com<CR><LF> */
3276 uint8_t request3[] = {
3277 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a,
3278 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d,
3279 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d,
3280 0x0a
3281 };
3282 uint32_t request3_len = sizeof(request3);
3283 /* 250 2.1.5 Ok<CR><LF> */
3284 uint8_t reply3[] = {
3285 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
3286 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
3287 };
3288 uint32_t reply3_len = sizeof(reply3);
3289
3290 /* BDAT 51<CR><LF> */
3291 uint8_t request4[] = {
3292 0x42, 0x44, 0x41, 0x54, 0x20, 0x35, 0x31, 0x0d,
3293 0x0a,
3294 };
3295 uint32_t request4_len = sizeof(request4);
3296
3297 uint8_t request5[] = {
3298 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64,
3299 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e,
3300 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e,
3301 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x0d, 0x0a,
3302 };
3303 uint32_t request5_len = sizeof(request5);
3304
3305 uint8_t request6[] = {
3306 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64,
3307 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e,
3308 0x66, 0x0d, 0x0a,
3309 };
561630d8 3310 uint32_t request6_len = sizeof(request6);
d3ca65de
AS
3311
3312 TcpSession ssn;
8dbf7a0d 3313 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
d3ca65de
AS
3314
3315 memset(&f, 0, sizeof(f));
3316 memset(&ssn, 0, sizeof(ssn));
3317
3318 FLOW_INITIALIZE(&f);
3319 f.protoctx = (void *)&ssn;
429c6388 3320 f.proto = IPPROTO_TCP;
d3ca65de
AS
3321
3322 StreamTcpInitConfig(TRUE);
d3ca65de 3323
cd3e32ce 3324 SCMutexLock(&f.m);
429c6388
AS
3325 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3326 welcome_reply, welcome_reply_len);
d3ca65de
AS
3327 if (r != 0) {
3328 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3329 SCMutexUnlock(&f.m);
d3ca65de
AS
3330 goto end;
3331 }
cd3e32ce 3332 SCMutexUnlock(&f.m);
06904c90 3333 SMTPState *smtp_state = f.alstate;
d3ca65de
AS
3334 if (smtp_state == NULL) {
3335 printf("no smtp state: ");
3336 goto end;
3337 }
3338 if (smtp_state->input_len != 0 ||
0d7159b5 3339 smtp_state->cmds_cnt != 0 ||
d3ca65de 3340 smtp_state->cmds_idx != 0 ||
0d7159b5 3341 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
d3ca65de
AS
3342 printf("smtp parser in inconsistent state\n");
3343 goto end;
3344 }
3345
cd3e32ce 3346 SCMutexLock(&f.m);
429c6388
AS
3347 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3348 request1, request1_len);
d3ca65de
AS
3349 if (r != 0) {
3350 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3351 SCMutexUnlock(&f.m);
d3ca65de
AS
3352 goto end;
3353 }
cd3e32ce 3354 SCMutexUnlock(&f.m);
d3ca65de
AS
3355 if (smtp_state->input_len != 0 ||
3356 smtp_state->cmds_cnt != 1 ||
3357 smtp_state->cmds_idx != 0 ||
3358 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
3359 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3360 printf("smtp parser in inconsistent state\n");
3361 goto end;
3362 }
3363
cd3e32ce 3364 SCMutexLock(&f.m);
429c6388
AS
3365 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3366 reply1, reply1_len);
d3ca65de
AS
3367 if (r != 0) {
3368 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3369 SCMutexUnlock(&f.m);
d3ca65de
AS
3370 goto end;
3371 }
cd3e32ce 3372 SCMutexUnlock(&f.m);
d3ca65de
AS
3373 if (smtp_state->input_len != 0 ||
3374 smtp_state->cmds_cnt != 0 ||
3375 smtp_state->cmds_idx != 0 ||
3376 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3377 printf("smtp parser in inconsistent state\n");
3378 goto end;
3379 }
3380
cd3e32ce 3381 SCMutexLock(&f.m);
429c6388
AS
3382 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3383 request2, request2_len);
d3ca65de
AS
3384 if (r != 0) {
3385 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3386 SCMutexUnlock(&f.m);
d3ca65de
AS
3387 goto end;
3388 }
cd3e32ce 3389 SCMutexUnlock(&f.m);
d3ca65de
AS
3390 if (smtp_state->input_len != 0 ||
3391 smtp_state->cmds_cnt != 1 ||
3392 smtp_state->cmds_idx != 0 ||
3393 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
3394 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3395 printf("smtp parser in inconsistent state\n");
3396 goto end;
3397 }
3398
cd3e32ce 3399 SCMutexLock(&f.m);
429c6388
AS
3400 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3401 reply2, reply2_len);
d3ca65de
AS
3402 if (r != 0) {
3403 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3404 SCMutexUnlock(&f.m);
d3ca65de
AS
3405 goto end;
3406 }
cd3e32ce 3407 SCMutexUnlock(&f.m);
d3ca65de
AS
3408 if (smtp_state->input_len != 0 ||
3409 smtp_state->cmds_cnt != 0 ||
3410 smtp_state->cmds_idx != 0 ||
3411 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
3412 printf("smtp parser in inconsistent state\n");
3413 goto end;
3414 }
3415
cd3e32ce 3416 SCMutexLock(&f.m);
429c6388
AS
3417 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3418 request3, request3_len);
d3ca65de
AS
3419 if (r != 0) {
3420 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3421 SCMutexUnlock(&f.m);
d3ca65de
AS
3422 goto end;
3423 }
cd3e32ce 3424 SCMutexUnlock(&f.m);
d3ca65de
AS
3425 if (smtp_state->input_len != 0 ||
3426 smtp_state->cmds_cnt != 1 ||
3427 smtp_state->cmds_idx != 0 ||
3428 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
3429 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
3430 printf("smtp parser in inconsistent state\n");
3431 goto end;
3432 }
3433
cd3e32ce 3434 SCMutexLock(&f.m);
429c6388
AS
3435 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
3436 reply3, reply3_len);
d3ca65de
AS
3437 if (r != 0) {
3438 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3439 SCMutexUnlock(&f.m);
d3ca65de
AS
3440 goto end;
3441 }
cd3e32ce 3442 SCMutexUnlock(&f.m);
d3ca65de
AS
3443 if (smtp_state->input_len != 0 ||
3444 smtp_state->cmds_cnt != 0 ||
3445 smtp_state->cmds_idx != 0 ||
3446 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
3447 printf("smtp parser in inconsistent state\n");
3448 goto end;
3449 }
3450
cd3e32ce 3451 SCMutexLock(&f.m);
429c6388
AS
3452 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3453 request4, request4_len);
d3ca65de
AS
3454 if (r != 0) {
3455 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3456 SCMutexUnlock(&f.m);
d3ca65de
AS
3457 goto end;
3458 }
cd3e32ce 3459 SCMutexUnlock(&f.m);
d3ca65de
AS
3460 if (smtp_state->input_len != 0 ||
3461 smtp_state->cmds_cnt != 1 ||
3462 smtp_state->cmds_idx != 0 ||
3463 smtp_state->cmds[0] != SMTP_COMMAND_BDAT ||
3464 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
3465 SMTP_PARSER_STATE_COMMAND_DATA_MODE) ||
3466 smtp_state->bdat_chunk_len != 51 ||
3467 smtp_state->bdat_chunk_idx != 0) {
3468 printf("smtp parser in inconsistent state\n");
3469 goto end;
3470 }
3471
cd3e32ce 3472 SCMutexLock(&f.m);
429c6388
AS
3473 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3474 request5, request5_len);
d3ca65de
AS
3475 if (r != 0) {
3476 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3477 SCMutexUnlock(&f.m);
d3ca65de
AS
3478 goto end;
3479 }
cd3e32ce 3480 SCMutexUnlock(&f.m);
d3ca65de
AS
3481 if (smtp_state->input_len != 0 ||
3482 smtp_state->cmds_cnt != 1 ||
3483 smtp_state->cmds_idx != 0 ||
3484 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
3485 SMTP_PARSER_STATE_COMMAND_DATA_MODE) ||
3486 smtp_state->bdat_chunk_len != 51 ||
3487 smtp_state->bdat_chunk_idx != 32) {
3488 printf("smtp parser in inconsistent state\n");
3489 goto end;
3490 }
3491
cd3e32ce 3492 SCMutexLock(&f.m);
429c6388
AS
3493 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3494 request6, request6_len);
d3ca65de
AS
3495 if (r != 0) {
3496 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3497 SCMutexUnlock(&f.m);
d3ca65de
AS
3498 goto end;
3499 }
cd3e32ce 3500 SCMutexUnlock(&f.m);
d3ca65de
AS
3501 if (smtp_state->input_len != 0 ||
3502 smtp_state->cmds_cnt != 1 ||
3503 smtp_state->cmds_idx != 0 ||
3504 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN ||
3505 smtp_state->bdat_chunk_len != 51 ||
3506 smtp_state->bdat_chunk_idx != 51) {
3507 printf("smtp parser in inconsistent state\n");
3508 goto end;
3509 }
3510
3511 result = 1;
3512end:
429c6388 3513 if (alp_tctx != NULL)
fdefb65b 3514 AppLayerParserThreadCtxFree(alp_tctx);
d3ca65de
AS
3515 StreamTcpFreeConfig(TRUE);
3516 FLOW_DESTROY(&f);
3517 return result;
3518}
3519
4a6908d3
AS
3520/*
3521 * \test Test retrieving lines when frag'ed.
3522 */
3523int SMTPParserTest07(void)
3524{
3525 int result = 0;
3526 Flow f;
3527 int r = 0;
3528
3529 const char *request1_str = "EHLO boo.com";
3530 /* EHLO boo.com<CR> */
3531 uint8_t request1_1[] = {
3532 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3533 0x2e, 0x63, 0x6f, 0x6d, 0x0d,
3534 };
3535 int32_t request1_1_len = sizeof(request1_1);
3536
3537 /* <LF> */
3538 uint8_t request1_2[] = {
3539 0x0a
3540 };
3541 int32_t request1_2_len = sizeof(request1_2);
3542
3543 /* EHLO boo.com<CR><LF> */
3544 uint8_t request2[] = {
3545 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3546 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
3547 };
3548 int32_t request2_len = sizeof(request2);
3549
3550 TcpSession ssn;
8dbf7a0d 3551 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
4a6908d3
AS
3552
3553 memset(&f, 0, sizeof(f));
3554 memset(&ssn, 0, sizeof(ssn));
3555
3556 FLOW_INITIALIZE(&f);
3557 f.protoctx = (void *)&ssn;
429c6388 3558 f.proto = IPPROTO_TCP;
4a6908d3
AS
3559
3560 StreamTcpInitConfig(TRUE);
4a6908d3 3561
cd3e32ce 3562 SCMutexLock(&f.m);
429c6388
AS
3563 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3564 request1_1, request1_1_len);
4a6908d3
AS
3565 if (r != 0) {
3566 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3567 SCMutexUnlock(&f.m);
4a6908d3
AS
3568 goto end;
3569 }
cd3e32ce 3570 SCMutexUnlock(&f.m);
bf24272c 3571 SMTPState *smtp_state = f.alstate;
4a6908d3
AS
3572 if (smtp_state == NULL) {
3573 printf("no smtp state: ");
3574 goto end;
3575 }
3576 if (smtp_state->current_line != NULL ||
3577 smtp_state->current_line_len != 0 ||
3578 smtp_state->ts_current_line_db != 1 ||
3579 smtp_state->ts_db == NULL ||
3580 smtp_state->ts_db_len != request1_1_len ||
3581 memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) {
3582 printf("smtp parser in inconsistent state\n");
3583 goto end;
3584 }
3585
cd3e32ce 3586 SCMutexLock(&f.m);
429c6388
AS
3587 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3588 request1_2, request1_2_len);
4a6908d3
AS
3589 if (r != 0) {
3590 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3591 SCMutexUnlock(&f.m);
4a6908d3
AS
3592 goto end;
3593 }
cd3e32ce 3594 SCMutexUnlock(&f.m);
4a6908d3
AS
3595 if (smtp_state->ts_current_line_db != 1 ||
3596 smtp_state->ts_db == NULL ||
3597 smtp_state->ts_db_len != (int32_t)strlen(request1_str) ||
3598 memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 ||
3599 smtp_state->current_line != smtp_state->ts_db ||
3600 smtp_state->current_line_len != smtp_state->ts_db_len) {
3601 printf("smtp parser in inconsistent state\n");
3602 goto end;
3603 }
3604
cd3e32ce 3605 SCMutexLock(&f.m);
429c6388
AS
3606 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3607 request2, request2_len);
4a6908d3
AS
3608 if (r != 0) {
3609 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3610 SCMutexUnlock(&f.m);
4a6908d3
AS
3611 goto end;
3612 }
cd3e32ce 3613 SCMutexUnlock(&f.m);
4a6908d3
AS
3614 if (smtp_state->ts_current_line_db != 0 ||
3615 smtp_state->ts_db != NULL ||
3616 smtp_state->ts_db_len != 0 ||
3617 smtp_state->current_line == NULL ||
3618 smtp_state->current_line_len != (int32_t)strlen(request1_str) ||
3619 memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) {
3620 printf("smtp parser in inconsistent state\n");
3621 goto end;
3622 }
3623
3624 result = 1;
3625end:
429c6388 3626 if (alp_tctx != NULL)
fdefb65b 3627 AppLayerParserThreadCtxFree(alp_tctx);
4a6908d3
AS
3628 StreamTcpFreeConfig(TRUE);
3629 FLOW_DESTROY(&f);
3630 return result;
3631}
3632
3633/*
3634 * \test Test retrieving lines when frag'ed.
3635 */
3636int SMTPParserTest08(void)
3637{
3638 int result = 0;
3639 Flow f;
3640 int r = 0;
3641
3642 const char *request1_str = "EHLO boo.com";
3643 /* EHLO boo.com */
3644 uint8_t request1_1[] = {
3645 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3646 0x2e, 0x63, 0x6f, 0x6d,
3647 };
3648 int32_t request1_1_len = sizeof(request1_1);
3649
3650 /* <CR><LF> */
3651 uint8_t request1_2[] = {
3652 0x0d, 0x0a
3653 };
3654 int32_t request1_2_len = sizeof(request1_2);
3655
3656 /* EHLO boo.com<CR><LF> */
3657 uint8_t request2[] = {
3658 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3659 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
3660 };
3661 int32_t request2_len = sizeof(request2);
3662
3663 TcpSession ssn;
8dbf7a0d 3664 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
4a6908d3
AS
3665
3666 memset(&f, 0, sizeof(f));
3667 memset(&ssn, 0, sizeof(ssn));
3668
3669 FLOW_INITIALIZE(&f);
3670 f.protoctx = (void *)&ssn;
429c6388 3671 f.proto = IPPROTO_TCP;
4a6908d3
AS
3672
3673 StreamTcpInitConfig(TRUE);
4a6908d3 3674
cd3e32ce 3675 SCMutexLock(&f.m);
429c6388
AS
3676 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3677 request1_1, request1_1_len);
4a6908d3
AS
3678 if (r != 0) {
3679 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3680 SCMutexUnlock(&f.m);
4a6908d3
AS
3681 goto end;
3682 }
cd3e32ce 3683 SCMutexUnlock(&f.m);
bf24272c 3684 SMTPState *smtp_state = f.alstate;
4a6908d3
AS
3685 if (smtp_state == NULL) {
3686 printf("no smtp state: ");
3687 goto end;
3688 }
3689 if (smtp_state->current_line != NULL ||
3690 smtp_state->current_line_len != 0 ||
3691 smtp_state->ts_current_line_db != 1 ||
3692 smtp_state->ts_db == NULL ||
3693 smtp_state->ts_db_len != request1_1_len ||
3694 memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) {
3695 printf("smtp parser in inconsistent state\n");
3696 goto end;
3697 }
3698
cd3e32ce 3699 SCMutexLock(&f.m);
429c6388
AS
3700 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3701 request1_2, request1_2_len);
4a6908d3
AS
3702 if (r != 0) {
3703 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3704 SCMutexUnlock(&f.m);
4a6908d3
AS
3705 goto end;
3706 }
cd3e32ce 3707 SCMutexUnlock(&f.m);
4a6908d3
AS
3708 if (smtp_state->ts_current_line_db != 1 ||
3709 smtp_state->ts_db == NULL ||
3710 smtp_state->ts_db_len != (int32_t)strlen(request1_str) ||
3711 memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 ||
3712 smtp_state->current_line != smtp_state->ts_db ||
3713 smtp_state->current_line_len != smtp_state->ts_db_len) {
3714 printf("smtp parser in inconsistent state\n");
3715 goto end;
3716 }
3717
cd3e32ce 3718 SCMutexLock(&f.m);
429c6388
AS
3719 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3720 request2, request2_len);
4a6908d3
AS
3721 if (r != 0) {
3722 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3723 SCMutexUnlock(&f.m);
4a6908d3
AS
3724 goto end;
3725 }
cd3e32ce 3726 SCMutexUnlock(&f.m);
4a6908d3
AS
3727 if (smtp_state->ts_current_line_db != 0 ||
3728 smtp_state->ts_db != NULL ||
3729 smtp_state->ts_db_len != 0 ||
3730 smtp_state->current_line == NULL ||
3731 smtp_state->current_line_len != (int32_t)strlen(request1_str) ||
3732 memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) {
3733 printf("smtp parser in inconsistent state\n");
3734 goto end;
3735 }
3736
3737 result = 1;
3738end:
429c6388 3739 if (alp_tctx != NULL)
fdefb65b 3740 AppLayerParserThreadCtxFree(alp_tctx);
4a6908d3
AS
3741 StreamTcpFreeConfig(TRUE);
3742 FLOW_DESTROY(&f);
3743 return result;
3744}
3745
3746/*
3747 * \test Test retrieving lines when frag'ed.
3748 */
3749int SMTPParserTest09(void)
3750{
3751 int result = 0;
3752 Flow f;
3753 int r = 0;
3754
3755 const char *request1_str = "EHLO boo.com";
3756 /* EHLO boo. */
3757 uint8_t request1_1[] = {
3758 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3759 0x2e,
3760 };
3761 int32_t request1_1_len = sizeof(request1_1);
3762
3763 /* com<CR><LF> */
3764 uint8_t request1_2[] = {
3765 0x63, 0x6f, 0x6d, 0x0d, 0x0a
3766 };
3767 int32_t request1_2_len = sizeof(request1_2);
3768
3769 /* EHLO boo.com<CR><LF> */
3770 uint8_t request2[] = {
3771 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3772 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
3773 };
3774 int32_t request2_len = sizeof(request2);
3775
3776 TcpSession ssn;
8dbf7a0d 3777 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
4a6908d3
AS
3778
3779 memset(&f, 0, sizeof(f));
3780 memset(&ssn, 0, sizeof(ssn));
3781
3782 FLOW_INITIALIZE(&f);
3783 f.protoctx = (void *)&ssn;
429c6388 3784 f.proto = IPPROTO_TCP;
4a6908d3
AS
3785
3786 StreamTcpInitConfig(TRUE);
4a6908d3 3787
cd3e32ce 3788 SCMutexLock(&f.m);
429c6388
AS
3789 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3790 request1_1, request1_1_len);
4a6908d3
AS
3791 if (r != 0) {
3792 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3793 SCMutexUnlock(&f.m);
4a6908d3
AS
3794 goto end;
3795 }
cd3e32ce 3796 SCMutexUnlock(&f.m);
bf24272c 3797 SMTPState *smtp_state = f.alstate;
4a6908d3
AS
3798 if (smtp_state == NULL) {
3799 printf("no smtp state: ");
3800 goto end;
3801 }
3802 if (smtp_state->current_line != NULL ||
3803 smtp_state->current_line_len != 0 ||
3804 smtp_state->ts_current_line_db != 1 ||
3805 smtp_state->ts_db == NULL ||
3806 smtp_state->ts_db_len != request1_1_len ||
3807 memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) {
3808 printf("smtp parser in inconsistent state\n");
3809 goto end;
3810 }
3811
cd3e32ce 3812 SCMutexLock(&f.m);
429c6388
AS
3813 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3814 request1_2, request1_2_len);
4a6908d3
AS
3815 if (r != 0) {
3816 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3817 SCMutexUnlock(&f.m);
4a6908d3
AS
3818 goto end;
3819 }
cd3e32ce 3820 SCMutexUnlock(&f.m);
4a6908d3
AS
3821 if (smtp_state->ts_current_line_db != 1 ||
3822 smtp_state->ts_db == NULL ||
3823 smtp_state->ts_db_len != (int32_t)strlen(request1_str) ||
3824 memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 ||
3825 smtp_state->current_line != smtp_state->ts_db ||
3826 smtp_state->current_line_len != smtp_state->ts_db_len) {
3827 printf("smtp parser in inconsistent state\n");
3828 goto end;
3829 }
3830
cd3e32ce 3831 SCMutexLock(&f.m);
429c6388
AS
3832 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3833 request2, request2_len);
4a6908d3
AS
3834 if (r != 0) {
3835 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3836 SCMutexUnlock(&f.m);
4a6908d3
AS
3837 goto end;
3838 }
cd3e32ce 3839 SCMutexUnlock(&f.m);
4a6908d3
AS
3840 if (smtp_state->ts_current_line_db != 0 ||
3841 smtp_state->ts_db != NULL ||
3842 smtp_state->ts_db_len != 0 ||
3843 smtp_state->current_line == NULL ||
3844 smtp_state->current_line_len != (int32_t)strlen(request1_str) ||
3845 memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) {
3846 printf("smtp parser in inconsistent state\n");
3847 goto end;
3848 }
3849
3850 result = 1;
3851end:
429c6388 3852 if (alp_tctx != NULL)
fdefb65b 3853 AppLayerParserThreadCtxFree(alp_tctx);
4a6908d3
AS
3854 StreamTcpFreeConfig(TRUE);
3855 FLOW_DESTROY(&f);
3856 return result;
3857}
3858
3859/*
3860 * \test Test retrieving lines when frag'ed.
3861 */
3862int SMTPParserTest10(void)
3863{
3864 int result = 0;
3865 Flow f;
3866 int r = 0;
3867
3868 const char *request1_str = "";
3869 /* EHLO boo. */
3870 uint8_t request1_1[] = {
3871 0x0d,
3872 };
3873 int32_t request1_1_len = sizeof(request1_1);
3874
3875 /* com<CR><LF> */
3876 uint8_t request1_2[] = {
3877 0x0a,
3878 };
3879 int32_t request1_2_len = sizeof(request1_2);
3880
3881 const char *request2_str = "EHLO boo.com";
3882 /* EHLO boo.com<CR><LF> */
3883 uint8_t request2[] = {
3884 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3885 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
3886 };
3887 int32_t request2_len = sizeof(request2);
3888
3889 TcpSession ssn;
8dbf7a0d 3890 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
4a6908d3
AS
3891
3892 memset(&f, 0, sizeof(f));
3893 memset(&ssn, 0, sizeof(ssn));
3894
3895 FLOW_INITIALIZE(&f);
3896 f.protoctx = (void *)&ssn;
429c6388 3897 f.proto = IPPROTO_TCP;
4a6908d3
AS
3898
3899 StreamTcpInitConfig(TRUE);
4a6908d3 3900
cd3e32ce 3901 SCMutexLock(&f.m);
429c6388
AS
3902 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3903 request1_1, request1_1_len);
4a6908d3
AS
3904 if (r != 0) {
3905 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3906 SCMutexUnlock(&f.m);
4a6908d3
AS
3907 goto end;
3908 }
cd3e32ce 3909 SCMutexUnlock(&f.m);
bf24272c 3910 SMTPState *smtp_state = f.alstate;
4a6908d3
AS
3911 if (smtp_state == NULL) {
3912 printf("no smtp state: ");
3913 goto end;
3914 }
3915 if (smtp_state->current_line != NULL ||
3916 smtp_state->current_line_len != 0 ||
3917 smtp_state->ts_current_line_db != 1 ||
3918 smtp_state->ts_db == NULL ||
3919 smtp_state->ts_db_len != request1_1_len ||
3920 memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) {
3921 printf("smtp parser in inconsistent state\n");
3922 goto end;
3923 }
3924
cd3e32ce 3925 SCMutexLock(&f.m);
429c6388
AS
3926 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3927 request1_2, request1_2_len);
4a6908d3
AS
3928 if (r != 0) {
3929 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3930 SCMutexUnlock(&f.m);
4a6908d3
AS
3931 goto end;
3932 }
cd3e32ce 3933 SCMutexUnlock(&f.m);
4a6908d3
AS
3934 if (smtp_state->ts_current_line_db != 1 ||
3935 smtp_state->ts_db == NULL ||
3936 smtp_state->ts_db_len != (int32_t)strlen(request1_str) ||
3937 memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 ||
3938 smtp_state->current_line != smtp_state->ts_db ||
3939 smtp_state->current_line_len != smtp_state->ts_db_len) {
3940 printf("smtp parser in inconsistent state\n");
3941 goto end;
3942 }
3943
cd3e32ce 3944 SCMutexLock(&f.m);
429c6388
AS
3945 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
3946 request2, request2_len);
4a6908d3
AS
3947 if (r != 0) {
3948 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 3949 SCMutexUnlock(&f.m);
4a6908d3
AS
3950 goto end;
3951 }
cd3e32ce 3952 SCMutexUnlock(&f.m);
4a6908d3
AS
3953 if (smtp_state->ts_current_line_db != 0 ||
3954 smtp_state->ts_db != NULL ||
3955 smtp_state->ts_db_len != 0 ||
3956 smtp_state->current_line == NULL ||
3957 smtp_state->current_line_len != (int32_t)strlen(request2_str) ||
3958 memcmp(smtp_state->current_line, request2_str, strlen(request2_str)) != 0) {
3959 printf("smtp parser in inconsistent state\n");
3960 goto end;
3961 }
3962
3963 result = 1;
3964end:
429c6388 3965 if (alp_tctx != NULL)
fdefb65b 3966 AppLayerParserThreadCtxFree(alp_tctx);
4a6908d3
AS
3967 StreamTcpFreeConfig(TRUE);
3968 FLOW_DESTROY(&f);
3969 return result;
3970}
3971
3972/*
3973 * \test Test retrieving lines when frag'ed.
3974 */
3975int SMTPParserTest11(void)
3976{
3977 int result = 0;
3978 Flow f;
3979 int r = 0;
3980
3981 const char *request1_str = "";
3982 /* EHLO boo. */
3983 uint8_t request1[] = {
3984 0x0a,
3985 };
3986 int32_t request1_len = sizeof(request1);
3987
3988 const char *request2_str = "EHLO boo.com";
3989 /* EHLO boo.com<CR><LF> */
3990 uint8_t request2[] = {
3991 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
3992 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
3993 };
3994 int32_t request2_len = sizeof(request2);
3995
3996 TcpSession ssn;
8dbf7a0d 3997 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
4a6908d3
AS
3998
3999 memset(&f, 0, sizeof(f));
4000 memset(&ssn, 0, sizeof(ssn));
4001
4002 FLOW_INITIALIZE(&f);
4003 f.protoctx = (void *)&ssn;
429c6388 4004 f.proto = IPPROTO_TCP;
4a6908d3
AS
4005
4006 StreamTcpInitConfig(TRUE);
4a6908d3 4007
cd3e32ce 4008 SCMutexLock(&f.m);
429c6388
AS
4009 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
4010 request1, request1_len);
4a6908d3
AS
4011 if (r != 0) {
4012 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 4013 SCMutexUnlock(&f.m);
4a6908d3
AS
4014 goto end;
4015 }
cd3e32ce 4016 SCMutexUnlock(&f.m);
bf24272c 4017 SMTPState *smtp_state = f.alstate;
4a6908d3
AS
4018 if (smtp_state == NULL) {
4019 printf("no smtp state: ");
4020 goto end;
4021 }
4022 if (smtp_state->current_line == NULL ||
4023 smtp_state->current_line_len != 0 ||
4024 smtp_state->ts_current_line_db == 1 ||
4025 smtp_state->ts_db != NULL ||
4026 smtp_state->ts_db_len != 0 ||
4027 memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) {
4028 printf("smtp parser in inconsistent state\n");
4029 goto end;
4030 }
4031
cd3e32ce 4032 SCMutexLock(&f.m);
429c6388
AS
4033 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
4034 request2, request2_len);
4a6908d3
AS
4035 if (r != 0) {
4036 printf("smtp check returned %" PRId32 ", expected 0: ", r);
cd3e32ce 4037 SCMutexUnlock(&f.m);
4a6908d3
AS
4038 goto end;
4039 }
cd3e32ce 4040 SCMutexUnlock(&f.m);
4a6908d3
AS
4041 if (smtp_state->ts_current_line_db != 0 ||
4042 smtp_state->ts_db != NULL ||
4043 smtp_state->ts_db_len != 0 ||
4044 smtp_state->current_line == NULL ||
4045 smtp_state->current_line_len != (int32_t)strlen(request2_str) ||
4046 memcmp(smtp_state->current_line, request2_str, strlen(request2_str)) != 0) {
4047 printf("smtp parser in inconsistent state\n");
4048 goto end;
4049 }
4050
4051 result = 1;
4052end:
429c6388 4053 if (alp_tctx != NULL)
fdefb65b 4054 AppLayerParserThreadCtxFree(alp_tctx);
4a6908d3
AS
4055 StreamTcpFreeConfig(TRUE);
4056 FLOW_DESTROY(&f);
4057 return result;
4058}
4059
5311cd48
AS
4060int SMTPParserTest12(void)
4061{
4062 int result = 0;
4063 Signature *s = NULL;
4064 ThreadVars th_v;
4065 Packet *p = NULL;
4066 Flow f;
4067 TcpSession ssn;
4068 DetectEngineThreadCtx *det_ctx = NULL;
4069 DetectEngineCtx *de_ctx = NULL;
4070 SMTPState *smtp_state = NULL;
4071 int r = 0;
4072
4073 /* EHLO boo.com<CR><LF> */
4074 uint8_t request1[] = {
4075 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
4076 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
4077 };
4078 int32_t request1_len = sizeof(request1);
4079
4080 /* 388<CR><LF>
4081 */
4082 uint8_t reply1[] = {
4083 0x31, 0x38, 0x38, 0x0d, 0x0a,
4084 };
4085 uint32_t reply1_len = sizeof(reply1);
4086
8dbf7a0d 4087 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
429c6388 4088
5311cd48
AS
4089 memset(&th_v, 0, sizeof(th_v));
4090 memset(&f, 0, sizeof(f));
4091 memset(&ssn, 0, sizeof(ssn));
4092
4093 p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
4094
4095 FLOW_INITIALIZE(&f);
4096 f.protoctx = (void *)&ssn;
429c6388 4097 f.proto = IPPROTO_TCP;
5311cd48
AS
4098 p->flow = &f;
4099 p->flowflags |= FLOW_PKT_TOSERVER;
4100 p->flowflags |= FLOW_PKT_ESTABLISHED;
4101 p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
4102 f.alproto = ALPROTO_SMTP;
4103
4104 StreamTcpInitConfig(TRUE);
5311cd48
AS
4105
4106 de_ctx = DetectEngineCtxInit();
4107 if (de_ctx == NULL)
4108 goto end;
4109
4110 de_ctx->flags |= DE_QUIET;
4111
4112 s = DetectEngineAppendSig(de_ctx,"alert tcp any any -> any any "
4113 "(msg:\"SMTP event handling\"; "
7fa22e84 4114 "app-layer-event: smtp.invalid_reply; "
5311cd48
AS
4115 "sid:1;)");
4116 if (s == NULL)
4117 goto end;
4118
4119 SigGroupBuild(de_ctx);
4120 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
4121
cd3e32ce 4122 SCMutexLock(&f.m);
429c6388
AS
4123 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER | STREAM_START,
4124 request1, request1_len);
5311cd48
AS
4125 if (r != 0) {
4126 printf("AppLayerParse for smtp failed. Returned %" PRId32, r);
cd3e32ce 4127 SCMutexUnlock(&f.m);
5311cd48
AS
4128 goto end;
4129 }
cd3e32ce 4130 SCMutexUnlock(&f.m);
5311cd48
AS
4131
4132 smtp_state = f.alstate;
4133 if (smtp_state == NULL) {
4134 printf("no smtp state: ");
4135 goto end;
4136 }
4137
4138 /* do detect */
4139 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4140
4141 if (PacketAlertCheck(p, 1)) {
4142 printf("sid 1 matched. It shouldn't match: ");
4143 goto end;
4144 }
4145
cd3e32ce 4146 SCMutexLock(&f.m);
429c6388
AS
4147 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT | STREAM_TOCLIENT,
4148 reply1, reply1_len);
5311cd48
AS
4149 if (r == 0) {
4150 printf("AppLayerParse for smtp failed. Returned %" PRId32, r);
cd3e32ce 4151 SCMutexUnlock(&f.m);
5311cd48
AS
4152 goto end;
4153 }
cd3e32ce 4154 SCMutexUnlock(&f.m);
5311cd48
AS
4155
4156 /* do detect */
4157 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4158
4159 if (!PacketAlertCheck(p, 1)) {
4160 printf("sid 1 didn't match. Should have matched: ");
4161 goto end;
4162 }
4163
4164 result = 1;
4165
4166end:
4167 SigGroupCleanup(de_ctx);
4168 SigCleanSignatures(de_ctx);
4169
4170 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
4171 DetectEngineCtxFree(de_ctx);
4172
429c6388 4173 if (alp_tctx != NULL)
fdefb65b 4174 AppLayerParserThreadCtxFree(alp_tctx);
5311cd48 4175 StreamTcpFreeConfig(TRUE);
5311cd48
AS
4176 FLOW_DESTROY(&f);
4177 UTHFreePackets(&p, 1);
4178 return result;
4179}
4180
4181int SMTPParserTest13(void)
4182{
4183 int result = 0;
4184 Signature *s = NULL;
4185 ThreadVars th_v;
4186 Packet *p = NULL;
4187 Flow f;
4188 TcpSession ssn;
4189 DetectEngineThreadCtx *det_ctx = NULL;
4190 DetectEngineCtx *de_ctx = NULL;
4191 SMTPState *smtp_state = NULL;
4192 int r = 0;
4193
4194 /* EHLO boo.com<CR><LF> */
4195 uint8_t request1[] = {
4196 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
4197 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a,
4198 };
4199 int32_t request1_len = sizeof(request1);
4200
4201 /* 250<CR><LF>
4202 */
4203 uint8_t reply1[] = {
4204 0x32, 0x35, 0x30, 0x0d, 0x0a,
4205 };
4206 uint32_t reply1_len = sizeof(reply1);
4207
4208 /* MAIL FROM:pbsf@asdfs.com<CR><LF>
4209 * RCPT TO:pbsf@asdfs.com<CR><LF>
4210 * DATA<CR><LF>
4211 * STARTTLS<CR><LF>
4212 */
4213 uint8_t request2[] = {
4214 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
4215 0x4d, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61,
4216 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
4217 0x0d, 0x0a, 0x52, 0x43, 0x50, 0x54, 0x20, 0x54,
4218 0x4f, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61,
4219 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
4220 0x0d, 0x0a, 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a,
4221 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53,
4222 0x0d, 0x0a
4223 };
4224 uint32_t request2_len = sizeof(request2);
4225
8dbf7a0d 4226 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
429c6388 4227
5311cd48
AS
4228 memset(&th_v, 0, sizeof(th_v));
4229 memset(&f, 0, sizeof(f));
4230 memset(&ssn, 0, sizeof(ssn));
4231
4232 p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
4233
4234 FLOW_INITIALIZE(&f);
4235 f.protoctx = (void *)&ssn;
429c6388 4236 f.proto = IPPROTO_TCP;
5311cd48
AS
4237 p->flow = &f;
4238 p->flowflags |= FLOW_PKT_TOSERVER;
4239 p->flowflags |= FLOW_PKT_ESTABLISHED;
4240 p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
4241 f.alproto = ALPROTO_SMTP;
4242
4243 StreamTcpInitConfig(TRUE);
5311cd48
AS
4244
4245 de_ctx = DetectEngineCtxInit();
4246 if (de_ctx == NULL)
4247 goto end;
4248
4249 de_ctx->flags |= DE_QUIET;
4250
4251 s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
4252 "(msg:\"SMTP event handling\"; "
7fa22e84 4253 "app-layer-event: "
5311cd48
AS
4254 "smtp.invalid_pipelined_sequence; "
4255 "sid:1;)");
4256 if (s == NULL)
4257 goto end;
4258
4259 SigGroupBuild(de_ctx);
4260 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
4261
cd3e32ce 4262 SCMutexLock(&f.m);
429c6388
AS
4263 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER | STREAM_START,
4264 request1, request1_len);
5311cd48
AS
4265 if (r != 0) {
4266 printf("AppLayerParse for smtp failed. Returned %" PRId32, r);
cd3e32ce 4267 SCMutexUnlock(&f.m);
5311cd48
AS
4268 goto end;
4269 }
cd3e32ce 4270 SCMutexUnlock(&f.m);
5311cd48
AS
4271
4272 smtp_state = f.alstate;
4273 if (smtp_state == NULL) {
4274 printf("no smtp state: ");
4275 goto end;
4276 }
4277
4278 /* do detect */
4279 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4280
4281 if (PacketAlertCheck(p, 1)) {
4282 printf("sid 1 matched. It shouldn't match: ");
4283 goto end;
4284 }
4285
cd3e32ce 4286 SCMutexLock(&f.m);
429c6388
AS
4287 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
4288 reply1, reply1_len);
5311cd48
AS
4289 if (r != 0) {
4290 printf("AppLayerParse for smtp failed. Returned %" PRId32, r);
cd3e32ce 4291 SCMutexUnlock(&f.m);
5311cd48
AS
4292 goto end;
4293 }
cd3e32ce 4294 SCMutexUnlock(&f.m);
5311cd48
AS
4295
4296 /* do detect */
4297 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4298
4299 if (PacketAlertCheck(p, 1)) {
4300 printf("sid 1 matched. It shouldn't match: ");
4301 goto end;
4302 }
4303
cd3e32ce 4304 SCMutexLock(&f.m);
429c6388
AS
4305 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
4306 request2, request2_len);
5311cd48
AS
4307 if (r != 0) {
4308 printf("AppLayerParse for smtp failed. Returned %" PRId32, r);
cd3e32ce 4309 SCMutexUnlock(&f.m);
5311cd48
AS
4310 goto end;
4311 }
cd3e32ce 4312 SCMutexUnlock(&f.m);
5311cd48
AS
4313
4314 /* do detect */
4315 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4316
4317 if (!PacketAlertCheck(p, 1)) {
4318 printf("sid 1 didn't match. Should have matched: ");
4319 goto end;
4320 }
4321
4322 result = 1;
4323
4324end:
4325 SigGroupCleanup(de_ctx);
4326 SigCleanSignatures(de_ctx);
4327
4328 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
4329 DetectEngineCtxFree(de_ctx);
4330
429c6388 4331 if (alp_tctx != NULL)
fdefb65b 4332 AppLayerParserThreadCtxFree(alp_tctx);
5311cd48 4333 StreamTcpFreeConfig(TRUE);
5311cd48
AS
4334 FLOW_DESTROY(&f);
4335 UTHFreePackets(&p, 1);
4336 return result;
4337}
4338
c2dc6867
DA
4339/**
4340 * \test Test DATA command w/MIME message.
4341 */
4342int SMTPParserTest14(void)
4343{
4344 int result = 0;
4345 Flow f;
4346 int r = 0;
4347
4348 /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */
6467a5d5 4349 static uint8_t welcome_reply[] = {
c2dc6867
DA
4350 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67,
4351 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
4352 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20,
4353 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36,
4354 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36,
4355 0x0d, 0x0a
4356 };
6467a5d5 4357 static uint32_t welcome_reply_len = sizeof(welcome_reply);
c2dc6867
DA
4358
4359 /* EHLO boo.com<CR><LF> */
6467a5d5 4360 static uint8_t request1[] = {
c2dc6867
DA
4361 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f,
4362 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a
4363 };
6467a5d5 4364 static uint32_t request1_len = sizeof(request1);
c2dc6867
DA
4365 /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF>
4366 * 250-SIZE 35882577<CR><LF>
4367 * 250-8BITMIME<CR><LF>
4368 * 250-STARTTLS<CR><LF>
4369 * 250 ENHANCEDSTATUSCODES<CR><LF>
4370 */
6467a5d5 4371 static uint8_t reply1[] = {
c2dc6867
DA
4372 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e,
4373 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f,
4374 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
4375 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d,
4376 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50,
4377 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d,
4378 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a,
4379 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30,
4380 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d,
4381 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35,
4382 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a,
4383 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41,
4384 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54,
4385 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d,
4386 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49,
4387 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32,
4388 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a
4389 };
6467a5d5 4390 static uint32_t reply1_len = sizeof(reply1);
c2dc6867
DA
4391
4392 /* MAIL FROM:asdff@asdf.com<CR><LF> */
6467a5d5 4393 static uint8_t request2[] = {
c2dc6867
DA
4394 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
4395 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40,
4396 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
4397 0x0d, 0x0a
4398 };
6467a5d5 4399 static uint32_t request2_len = sizeof(request2);
c2dc6867 4400 /* 250 2.1.0 Ok<CR><LF> */
6467a5d5 4401 static uint8_t reply2[] = {
c2dc6867
DA
4402 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
4403 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
4404 };
6467a5d5 4405 static uint32_t reply2_len = sizeof(reply2);
c2dc6867
DA
4406
4407 /* RCPT TO:bimbs@gmail.com<CR><LF> */
6467a5d5 4408 static uint8_t request3[] = {
c2dc6867
DA
4409 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a,
4410 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d,
4411 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d,
4412 0x0a
4413 };
6467a5d5 4414 static uint32_t request3_len = sizeof(request3);
c2dc6867 4415 /* 250 2.1.5 Ok<CR><LF> */
6467a5d5 4416 static uint8_t reply3[] = {
c2dc6867
DA
4417 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e,
4418 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a
4419 };
6467a5d5 4420 static uint32_t reply3_len = sizeof(reply3);
c2dc6867
DA
4421
4422 /* DATA<CR><LF> */
6467a5d5 4423 static uint8_t request4[] = {
c2dc6867
DA
4424 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a
4425 };
6467a5d5 4426 static uint32_t request4_len = sizeof(request4);
c2dc6867 4427 /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */
6467a5d5 4428 static uint8_t reply4[] = {
c2dc6867
DA
4429 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20,
4430 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74,
4431 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c,
4432 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c,
4433 0x4c, 0x46, 0x3e, 0x0d, 0x0a
4434 };
6467a5d5 4435 static uint32_t reply4_len = sizeof(reply4);
c2dc6867
DA
4436
4437 /* MIME_MSG */
6467a5d5
TD
4438 static uint64_t filesize = 133;
4439 static uint8_t request4_msg[] = {
c2dc6867
DA
4440 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72,
4441 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E,
4442 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65,
4443 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A,
4444 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61,
4445 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74,
4446 0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61,
4447 0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65,
4448 0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73,
4449 0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F,
4450 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61,
4451 0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F,
4452 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x44, 0x69,
4453 0x73, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F,
4454 0x6E, 0x3A, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63,
4455 0x68, 0x6D, 0x65, 0x6E, 0x74, 0x3B, 0x20, 0x66,
4456 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x3D,
4457 0x22, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x65, 0x78,
4458 0x65, 0x22, 0x3B, 0x0D, 0x0A, 0x0D, 0x0A, 0x54,
4459 0x56, 0x6F, 0x41, 0x41, 0x46, 0x42, 0x46, 0x41,
4460 0x41, 0x42, 0x4D, 0x41, 0x51, 0x45, 0x41, 0x61,
4461 0x69, 0x70, 0x59, 0x77, 0x77, 0x41, 0x41, 0x41,
4462 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42,
4463 0x41, 0x41, 0x44, 0x41, 0x51, 0x73, 0x42, 0x43,
4464 0x41, 0x41, 0x42, 0x41, 0x41, 0x43, 0x41, 0x41,
4465 0x41, 0x41, 0x41, 0x41, 0x48, 0x6B, 0x41, 0x41,
4466 0x41, 0x41, 0x4D, 0x41, 0x41, 0x41, 0x41, 0x65,
4467 0x51, 0x41, 0x41, 0x41, 0x41, 0x77, 0x41, 0x41,
4468 0x41, 0x41, 0x41, 0x41, 0x45, 0x41, 0x41, 0x42,
4469 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41,
4470 0x41, 0x42, 0x30, 0x41, 0x41, 0x41, 0x41, 0x49,
4471 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41,
4472 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42,
4473 0x41, 0x45, 0x41, 0x41, 0x49, 0x67, 0x41, 0x41,
4474 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4475 0x67, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4476 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4477 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4478 0x41, 0x42, 0x63, 0x58, 0x44, 0x59, 0x32, 0x4C,
4479 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C,
4480 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F,
4481 0x41, 0x3D, 0x3D, 0x0D,0x0A };
6467a5d5 4482 static uint32_t request4_msg_len = sizeof(request4_msg);
c2dc6867
DA
4483
4484 /* DATA COMPLETED */
6467a5d5 4485 static uint8_t request4_end[] = {
c2dc6867
DA
4486 0x0d, 0x0a, 0x2e, 0x0d, 0x0a
4487 };
6467a5d5 4488 static uint32_t request4_end_len = sizeof(request4_end);
c2dc6867 4489 /* 250 2.0.0 Ok: queued as 6A1AF20BF2<CR><LF> */
6467a5d5 4490 static uint8_t reply4_end[] = {
c2dc6867
DA
4491 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e,
4492 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75,
4493 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
4494 0x36, 0x41, 0x31, 0x41, 0x46, 0x32, 0x30, 0x42,
4495 0x46, 0x32, 0x0d, 0x0a
4496 };
6467a5d5 4497 static uint32_t reply4_end_len = sizeof(reply4_end);
c2dc6867
DA
4498
4499 /* QUIT<CR><LF> */
6467a5d5 4500 static uint8_t request5[] = {
c2dc6867
DA
4501 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a
4502 };
6467a5d5 4503 static uint32_t request5_len = sizeof(request5);
c2dc6867 4504 /* 221 2.0.0 Bye<CR><LF> */
6467a5d5 4505 static uint8_t reply5[] = {
c2dc6867
DA
4506 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e,
4507 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a
4508 };
6467a5d5 4509 static uint32_t reply5_len = sizeof(reply5);
c2dc6867
DA
4510
4511 TcpSession ssn;
260872cc 4512 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
c2dc6867
DA
4513
4514 memset(&f, 0, sizeof(f));
4515 memset(&ssn, 0, sizeof(ssn));
4516
4517 FLOW_INITIALIZE(&f);
4518 f.protoctx = (void *)&ssn;
260872cc 4519 f.proto = IPPROTO_TCP;
c2dc6867
DA
4520
4521 StreamTcpInitConfig(TRUE);
c2dc6867 4522
260872cc
EL
4523 SCMutexLock(&f.m);
4524 /* Welcome reply */
4525 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
4526 welcome_reply, welcome_reply_len);
c2dc6867
DA
4527 if (r != 0) {
4528 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4529 SCMutexUnlock(&f.m);
c2dc6867
DA
4530 goto end;
4531 }
260872cc 4532 SCMutexUnlock(&f.m);
c2dc6867
DA
4533 SMTPState *smtp_state = f.alstate;
4534 if (smtp_state == NULL) {
4535 printf("no smtp state: ");
4536 goto end;
4537 }
4538 if (smtp_state->input_len != 0 ||
260872cc 4539 smtp_state->cmds_cnt != 0 ||
c2dc6867 4540 smtp_state->cmds_idx != 0 ||
260872cc
EL
4541 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
4542 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4543 goto end;
4544 }
4545
260872cc
EL
4546 SCMutexLock(&f.m);
4547 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
4548 request1, request1_len);
c2dc6867
DA
4549 if (r != 0) {
4550 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4551 SCMutexUnlock(&f.m);
c2dc6867
DA
4552 goto end;
4553 }
260872cc 4554 SCMutexUnlock(&f.m);
c2dc6867
DA
4555 if (smtp_state->input_len != 0 ||
4556 smtp_state->cmds_cnt != 1 ||
4557 smtp_state->cmds_idx != 0 ||
4558 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
4559 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4560 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4561 goto end;
4562 }
4563
260872cc 4564 SCMutexLock(&f.m);
c2dc6867 4565 /* EHLO Reply */
260872cc 4566 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4567 reply1, reply1_len);
4568 if (r != 0) {
4569 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4570 SCMutexUnlock(&f.m);
c2dc6867
DA
4571 goto end;
4572 }
534360fc
EL
4573
4574 if ((smtp_state->helo_len != 7) || strncmp("boo.com", (char *)smtp_state->helo, 7)) {
4575 printf("incorrect parsing of HELO field '%s' (%d)\n", smtp_state->helo, smtp_state->helo_len);
4576 SCMutexUnlock(&f.m);
4577 goto end;
4578 }
4579
260872cc 4580 SCMutexUnlock(&f.m);
c2dc6867
DA
4581 if (smtp_state->input_len != 0 ||
4582 smtp_state->cmds_cnt != 0 ||
4583 smtp_state->cmds_idx != 0 ||
4584 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4585 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4586 goto end;
4587 }
4588
260872cc 4589 SCMutexLock(&f.m);
c2dc6867 4590 /* MAIL FROM Request */
260872cc 4591 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4592 request2, request2_len);
4593 if (r != 0) {
4594 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4595 SCMutexUnlock(&f.m);
c2dc6867
DA
4596 goto end;
4597 }
260872cc 4598 SCMutexUnlock(&f.m);
c2dc6867
DA
4599 if (smtp_state->input_len != 0 ||
4600 smtp_state->cmds_cnt != 1 ||
4601 smtp_state->cmds_idx != 0 ||
4602 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
4603 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4604 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4605 goto end;
4606 }
4607
260872cc 4608 SCMutexLock(&f.m);
c2dc6867 4609 /* MAIL FROM Reply */
260872cc 4610 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4611 reply2, reply2_len);
4612 if (r != 0) {
4613 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4614 SCMutexUnlock(&f.m);
c2dc6867
DA
4615 goto end;
4616 }
fbd6428f
EL
4617
4618 if ((smtp_state->curr_tx->mail_from_len != 14) ||
4619 strncmp("asdff@asdf.com", (char *)smtp_state->curr_tx->mail_from, 14)) {
4620 printf("incorrect parsing of MAIL FROM field '%s' (%d)\n",
4621 smtp_state->curr_tx->mail_from,
4622 smtp_state->curr_tx->mail_from_len);
4623 SCMutexUnlock(&f.m);
4624 goto end;
4625 }
4626
260872cc 4627 SCMutexUnlock(&f.m);
c2dc6867
DA
4628 if (smtp_state->input_len != 0 ||
4629 smtp_state->cmds_cnt != 0 ||
4630 smtp_state->cmds_idx != 0 ||
4631 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
260872cc 4632 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4633 goto end;
4634 }
4635
260872cc 4636 SCMutexLock(&f.m);
c2dc6867 4637 /* RCPT TO Request */
260872cc 4638 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4639 request3, request3_len);
4640 if (r != 0) {
4641 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4642 SCMutexUnlock(&f.m);
c2dc6867
DA
4643 goto end;
4644 }
260872cc 4645 SCMutexUnlock(&f.m);
c2dc6867
DA
4646 if (smtp_state->input_len != 0 ||
4647 smtp_state->cmds_cnt != 1 ||
4648 smtp_state->cmds_idx != 0 ||
4649 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
4650 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4651 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4652 goto end;
4653 }
4654
260872cc 4655 SCMutexLock(&f.m);
c2dc6867 4656 /* RCPT TO Reply */
260872cc 4657 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4658 reply3, reply3_len);
4659 if (r != 0) {
4660 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4661 SCMutexUnlock(&f.m);
c2dc6867
DA
4662 goto end;
4663 }
260872cc 4664 SCMutexUnlock(&f.m);
c2dc6867
DA
4665 if (smtp_state->input_len != 0 ||
4666 smtp_state->cmds_cnt != 0 ||
4667 smtp_state->cmds_idx != 0 ||
4668 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
260872cc 4669 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4670 goto end;
4671 }
4672
4673 /* Enable mime decoding */
4674 smtp_config.decode_mime = 1;
4675 smtp_config.mime_config.decode_base64 = 1;
4676 smtp_config.mime_config.decode_quoted_printable = 1;
4677 MimeDecSetConfig(&smtp_config.mime_config);
4678
260872cc 4679 SCMutexLock(&f.m);
c2dc6867 4680 /* DATA request */
260872cc 4681 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4682 request4, request4_len);
4683 if (r != 0) {
4684 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4685 SCMutexUnlock(&f.m);
c2dc6867
DA
4686 goto end;
4687 }
260872cc 4688 SCMutexUnlock(&f.m);
c2dc6867
DA
4689
4690 if (smtp_state->input_len != 0 ||
4691 smtp_state->cmds_cnt != 1 ||
4692 smtp_state->cmds_idx != 0 ||
4693 smtp_state->cmds[0] != SMTP_COMMAND_DATA ||
4694 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4695 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4696 goto end;
4697 }
4698
260872cc 4699 SCMutexLock(&f.m);
c2dc6867 4700 /* Data reply */
260872cc 4701 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4702 reply4, reply4_len);
4703 if (r != 0) {
4704 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4705 SCMutexUnlock(&f.m);
c2dc6867
DA
4706 goto end;
4707 }
260872cc 4708 SCMutexUnlock(&f.m);
c2dc6867
DA
4709 if (smtp_state->input_len != 0 ||
4710 smtp_state->cmds_cnt != 0 ||
4711 smtp_state->cmds_idx != 0 ||
4712 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
4713 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
260872cc 4714 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4715 goto end;
4716 }
4717
260872cc 4718 SCMutexLock(&f.m);
c2dc6867 4719 /* DATA message */
260872cc 4720 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4721 request4_msg, request4_msg_len);
4722 if (r != 0) {
4723 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4724 SCMutexUnlock(&f.m);
c2dc6867
DA
4725 goto end;
4726 }
260872cc 4727 SCMutexUnlock(&f.m);
c2dc6867
DA
4728
4729 if (smtp_state->input_len != 0 ||
4730 smtp_state->cmds_cnt != 0 ||
4731 smtp_state->cmds_idx != 0 ||
56b74c8b 4732 smtp_state->curr_tx->mime_state == NULL || smtp_state->curr_tx->msg_head == NULL || /* MIME data structures */
c2dc6867
DA
4733 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN |
4734 SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
260872cc 4735 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4736 goto end;
4737 }
4738
260872cc 4739 SCMutexLock(&f.m);
c2dc6867 4740 /* DATA . request */
260872cc 4741 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4742 request4_end, request4_end_len);
4743 if (r != 0) {
4744 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4745 SCMutexUnlock(&f.m);
c2dc6867
DA
4746 goto end;
4747 }
260872cc 4748 SCMutexUnlock(&f.m);
c2dc6867
DA
4749
4750 if (smtp_state->input_len != 0 ||
4751 smtp_state->cmds_cnt != 1 ||
4752 smtp_state->cmds_idx != 0 ||
4753 smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE ||
56b74c8b 4754 smtp_state->curr_tx->mime_state == NULL || smtp_state->curr_tx->msg_head == NULL || /* MIME data structures */
c2dc6867 4755 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
260872cc 4756 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4757 goto end;
4758 }
4759
4760 SMTPState *state = (SMTPState *) f.alstate;
4761 FileContainer *files = state->files_ts;
4762 if (files != NULL && files->head != NULL) {
4763 File *file = files->head;
4764
4765 if(strncmp((const char *)file->name, "test.exe", 8) != 0){
4766 printf("smtp-mime file name is incorrect");
4767 goto end;
4768 }
4769 if(file->size != filesize){
5461294a 4770 printf("smtp-mime file size %"PRIu64" is incorrect", file->size);
c2dc6867
DA
4771 goto end;
4772 }
6467a5d5
TD
4773 static uint8_t org_binary[] = {
4774 0x4D, 0x5A, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00,
c2dc6867
DA
4775 0x4C, 0x01, 0x01, 0x00, 0x6A, 0x2A, 0x58, 0xC3,
4776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4777 0x04, 0x00, 0x03, 0x01, 0x0B, 0x01, 0x08, 0x00,
4778 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
4779 0x79, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
4780 0x79, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
4781 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00,
4782 0x04, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
4783 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4784 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00,
4785 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4786 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4788 0x00, 0x00, 0x00, 0x00, 0x5C, 0x5C, 0x36, 0x36,
4789 0x2E, 0x39, 0x33, 0x2E, 0x36, 0x38, 0x2E, 0x36,
4790 0x5C, 0x7A, 0x00, 0x00, 0x38,};
4791 uint64_t z;
6467a5d5 4792 for (z=0; z < filesize; z++){
c2dc6867
DA
4793 if(org_binary[z] != file->chunks_head->data[z]){
4794 printf("smtp-mime file data incorrect\n");
4795 goto end;
4796 }
4797 }
4798 }
4799
260872cc 4800 SCMutexLock(&f.m);
c2dc6867 4801 /* DATA . reply */
260872cc 4802 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4803 reply4_end, reply4_end_len);
4804 if (r != 0) {
4805 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4806 SCMutexUnlock(&f.m);
c2dc6867
DA
4807 goto end;
4808 }
260872cc 4809 SCMutexUnlock(&f.m);
c2dc6867
DA
4810 if (smtp_state->input_len != 0 ||
4811 smtp_state->cmds_cnt != 0 ||
4812 smtp_state->cmds_idx != 0 ||
4813 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
260872cc 4814 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4815 goto end;
4816 }
4817
260872cc 4818 SCMutexLock(&f.m);
c2dc6867 4819 /* QUIT Request */
260872cc 4820 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER,
c2dc6867
DA
4821 request5, request5_len);
4822 if (r != 0) {
4823 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4824 SCMutexUnlock(&f.m);
c2dc6867
DA
4825 goto end;
4826 }
260872cc 4827 SCMutexUnlock(&f.m);
c2dc6867
DA
4828 if (smtp_state->input_len != 0 ||
4829 smtp_state->cmds_cnt != 1 ||
4830 smtp_state->cmds_idx != 0 ||
4831 smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
4832 smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
260872cc 4833 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4834 goto end;
4835 }
4836
260872cc 4837 SCMutexLock(&f.m);
c2dc6867 4838 /* QUIT Reply */
260872cc 4839 r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
c2dc6867
DA
4840 reply5, reply5_len);
4841 if (r != 0) {
4842 printf("smtp check returned %" PRId32 ", expected 0: ", r);
260872cc 4843 SCMutexUnlock(&f.m);
c2dc6867
DA
4844 goto end;
4845 }
260872cc 4846 SCMutexUnlock(&f.m);
c2dc6867
DA
4847 if (smtp_state->input_len != 0 ||
4848 smtp_state->cmds_cnt != 0 ||
4849 smtp_state->cmds_idx != 0 ||
4850 smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
260872cc 4851 printf("smtp parser in inconsistent state l.%d\n", __LINE__);
c2dc6867
DA
4852 goto end;
4853 }
4854
4855 result = 1;
260872cc
EL
4856end:
4857 if (alp_tctx != NULL)
4858 AppLayerParserThreadCtxFree(alp_tctx);
c2dc6867
DA
4859 StreamTcpFreeConfig(TRUE);
4860 FLOW_DESTROY(&f);
c2dc6867
DA
4861 return result;
4862}
4863
4864int SMTPProcessDataChunkTest01(void){
4865 Flow f;
4866 FLOW_INITIALIZE(&f);
4867 f.flags = FLOW_FILE_NO_STORE_TS;
4868 MimeDecParseState *state = MimeDecInitParser(&f, NULL);
4869 int ret;
d2657bec 4870 ret = SMTPProcessDataChunk(NULL, 0, state);
c2dc6867 4871
52983bf3 4872 return ret == 0;
c2dc6867
DA
4873}
4874
4875
4876int SMTPProcessDataChunkTest02(void){
4877 char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72,
4878 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E,
4879 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65,
4880 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A,
4881 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61,
4882 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74,
4883 0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61,
4884 0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65,
4885 0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73,
4886 0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F,
4887 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61,
4888 0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F,
4889 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x44, 0x69,
4890 0x73, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F,
4891 0x6E, 0x3A, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63,
4892 0x68, 0x6D, 0x65, 0x6E, 0x74, 0x3B, 0x20, 0x66,
4893 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x3D,
4894 0x22, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x65, 0x78,
4895 0x65, 0x22, 0x3B, 0x0D, 0x0A, 0x0D, 0x0A, 0x54,
4896 0x56, 0x6F, 0x41, 0x41, 0x46, 0x42, 0x46, 0x41,
4897 0x41, 0x42, 0x4D, 0x41, 0x51, 0x45, 0x41, 0x61,
4898 0x69, 0x70, 0x59, 0x77, 0x77, 0x41, 0x41, 0x41,
4899 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42,
4900 0x41, 0x41, 0x44, 0x41, 0x51, 0x73, 0x42, 0x43,
4901 0x41, 0x41, 0x42, 0x41, 0x41, 0x43, 0x41, 0x41,
4902 0x41, 0x41, 0x41, 0x41, 0x48, 0x6B, 0x41, 0x41,
4903 0x41, 0x41, 0x4D, 0x41, 0x41, 0x41, 0x41, 0x65,
4904 0x51, 0x41, 0x41, 0x41, 0x41, 0x77, 0x41, 0x41,
4905 0x41, 0x41, 0x41, 0x41, 0x45, 0x41, 0x41, 0x42,
4906 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41,
4907 0x41, 0x42, 0x30, 0x41, 0x41, 0x41, 0x41, 0x49,
4908 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41,
4909 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42,
4910 0x41, 0x45, 0x41, 0x41, 0x49, 0x67, 0x41, 0x41,
4911 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4912 0x67, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4913 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4914 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
4915 0x41, 0x42, 0x63, 0x58, 0x44, 0x59, 0x32, 0x4C,
4916 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C,
4917 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F,
4918 0x41, 0x3D, 0x3D, 0x0D, 0x0A,};
4919
4920 Flow f;
4921 FLOW_INITIALIZE(&f);
4922 f.alstate = SMTPStateAlloc();
4923 MimeDecParseState *state = MimeDecInitParser(&f, NULL);
4924 ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT;
4925 state->body_begin = 1;
4926 int ret;
d2657bec 4927 ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state);
c2dc6867 4928
52983bf3 4929 return ret == 0;
c2dc6867
DA
4930}
4931
4932
4933
4934int SMTPProcessDataChunkTest03(void){
4935 char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, };
4936 char mimemsg2[] = {0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, };
4937 char mimemsg3[] = {0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, };
4938 char mimemsg4[] = {0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, };
4939 char mimemsg5[] = {0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, };
4940 char mimemsg6[] = {0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, };
4941 char mimemsg7[] = {0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, };
4942 char mimemsg8[] = {0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, };
4943 char mimemsg9[] = {0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, };
4944 char mimemsg10[] = {0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, };
4945 char mimemsg11[] = {0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, };
4946 char mimemsg12[] = {0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F, };
4947
4948 Flow f;
4949 FLOW_INITIALIZE(&f);
4950 f.alstate = SMTPStateAlloc();
4951 MimeDecParseState *state = MimeDecInitParser(&f, NULL);
4952 ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT;
4953 int ret;
4954
4955 state->body_begin = 1;
d2657bec 4956 ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state);
c2dc6867
DA
4957 if(ret) goto end;
4958 state->body_begin = 0;
d2657bec 4959 ret = SMTPProcessDataChunk((uint8_t *)mimemsg2, sizeof(mimemsg2), state);
c2dc6867 4960 if(ret) goto end;
d2657bec 4961 ret = SMTPProcessDataChunk((uint8_t *)mimemsg3, sizeof(mimemsg3), state);
c2dc6867 4962 if(ret) goto end;
d2657bec 4963 ret = SMTPProcessDataChunk((uint8_t *)mimemsg4, sizeof(mimemsg4), state);
c2dc6867 4964 if(ret) goto end;
d2657bec 4965 ret = SMTPProcessDataChunk((uint8_t *)mimemsg5, sizeof(mimemsg5), state);
c2dc6867 4966 if(ret) goto end;
d2657bec 4967 ret = SMTPProcessDataChunk((uint8_t *)mimemsg6, sizeof(mimemsg6), state);
c2dc6867 4968 if(ret) goto end;
d2657bec 4969 ret = SMTPProcessDataChunk((uint8_t *)mimemsg7, sizeof(mimemsg7), state);
c2dc6867 4970 if(ret) goto end;
d2657bec 4971 ret = SMTPProcessDataChunk((uint8_t *)mimemsg8, sizeof(mimemsg8), state);
c2dc6867 4972 if(ret) goto end;
d2657bec 4973 ret = SMTPProcessDataChunk((uint8_t *)mimemsg9, sizeof(mimemsg9), state);
c2dc6867 4974 if(ret) goto end;
d2657bec 4975 ret = SMTPProcessDataChunk((uint8_t *)mimemsg10, sizeof(mimemsg10), state);
c2dc6867 4976 if(ret) goto end;
d2657bec 4977 ret = SMTPProcessDataChunk((uint8_t *)mimemsg11, sizeof(mimemsg11), state);
c2dc6867
DA
4978 if(ret) goto end;
4979 state->body_end = 1;
d2657bec 4980 ret = SMTPProcessDataChunk((uint8_t *)mimemsg12, sizeof(mimemsg12), state);
c2dc6867
DA
4981 if(ret) goto end;
4982
4983 end:
52983bf3 4984 return ret == 0;
c2dc6867
DA
4985}
4986
4987
4988int SMTPProcessDataChunkTest04(void){
4989 char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, };
4990 char mimemsg2[] = {0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, };
4991 char mimemsg3[] = {0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, };
4992 char mimemsg4[] = {0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, };
4993 char mimemsg5[] = {0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, };
4994 char mimemsg6[] = {0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, };
4995 char mimemsg7[] = {0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, };
4996 char mimemsg8[] = {0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, };
4997 char mimemsg9[] = {0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, };
4998 char mimemsg10[] = {0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, };
4999 char mimemsg11[] = {0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, };
5000
5001 Flow f;
5002 FLOW_INITIALIZE(&f);
5003 f.alstate = SMTPStateAlloc();
5004 MimeDecParseState *state = MimeDecInitParser(&f, NULL);
5005 ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT;
5006 int ret = MIME_DEC_OK;
5007
5008 state->body_begin = 1;
d2657bec
GL
5009 if(SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state) != 0) goto end;
5010 if(SMTPProcessDataChunk((uint8_t *)mimemsg2, sizeof(mimemsg2), state) != 0) goto end;
5011 if(SMTPProcessDataChunk((uint8_t *)mimemsg3, sizeof(mimemsg3), state) != 0) goto end;
5012 if(SMTPProcessDataChunk((uint8_t *)mimemsg4, sizeof(mimemsg4), state) != 0) goto end;
5013 if(SMTPProcessDataChunk((uint8_t *)mimemsg5, sizeof(mimemsg5), state) != 0) goto end;
5014 if(SMTPProcessDataChunk((uint8_t *)mimemsg6, sizeof(mimemsg6), state) != 0) goto end;
5015 if(SMTPProcessDataChunk((uint8_t *)mimemsg7, sizeof(mimemsg7), state) != 0) goto end;
c2dc6867
DA
5016 state->body_begin = 0;
5017 state->body_end = 1;
d2657bec 5018 if(SMTPProcessDataChunk((uint8_t *)mimemsg8, sizeof(mimemsg8), state) != 0) goto end;
c2dc6867 5019 state->body_end = 0;
d2657bec
GL
5020 if(SMTPProcessDataChunk((uint8_t *)mimemsg9, sizeof(mimemsg9), state) != 0) goto end;
5021 if(SMTPProcessDataChunk((uint8_t *)mimemsg10, sizeof(mimemsg10), state) != 0) goto end;
5022 if(SMTPProcessDataChunk((uint8_t *)mimemsg11, sizeof(mimemsg11), state) != 0) goto end;
c2dc6867
DA
5023
5024 end:
52983bf3 5025 return ret == 0;
c2dc6867
DA
5026}
5027
5028int SMTPProcessDataChunkTest05(void){
5029 char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72,
5030 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E,
5031 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65,
5032 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A,
5033 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C,
5034 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F,
5035 0x41, 0x3D, 0x3D, 0x0D, 0x0A,};
5036
5037 Flow f;
5038 FLOW_INITIALIZE(&f);
5039 f.alstate = SMTPStateAlloc();
5040 MimeDecParseState *state = MimeDecInitParser(&f, NULL);
5041 ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT;
5042 state->body_begin = 1;
5043 int ret;
5044 uint64_t file_size = 0;
d2657bec 5045 ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state);
c2dc6867
DA
5046 state->body_begin = 0;
5047 if(ret){goto end;}
5048 SMTPState *smtp_state = (SMTPState *)((Flow *)state->data)->alstate;
5049 FileContainer *files = smtp_state->files_ts;
5050 File *file = files->head;
5051 file_size = file->size;
5052
5053 FileDisableStoring(&f, STREAM_TOSERVER);
5054 FileDisableMagic(&f, STREAM_TOSERVER);
5055 FileDisableMd5(&f, STREAM_TOSERVER);
d2657bec 5056 ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state);
c2dc6867
DA
5057 if(ret){goto end;}
5058 printf("%u\t%u\n", (uint32_t) file->size, (uint32_t) file_size);
5059 if(file->size == file_size){
c2dc6867 5060 return 1;
52983bf3
JI
5061 }else{
5062 return 0;
c2dc6867
DA
5063 }
5064
5065 end:
52983bf3 5066 return ret == 0;
c2dc6867
DA
5067}
5068
87599bc7
AS
5069#endif /* UNITTESTS */
5070
576ec7da
AS
5071void SMTPParserRegisterTests(void)
5072{
87599bc7 5073#ifdef UNITTESTS
796dd522
JI
5074 UtRegisterTest("SMTPParserTest01", SMTPParserTest01);
5075 UtRegisterTest("SMTPParserTest02", SMTPParserTest02);
5076 UtRegisterTest("SMTPParserTest03", SMTPParserTest03);
5077 UtRegisterTest("SMTPParserTest04", SMTPParserTest04);
5078 UtRegisterTest("SMTPParserTest05", SMTPParserTest05);
5079 UtRegisterTest("SMTPParserTest06", SMTPParserTest06);
5080 UtRegisterTest("SMTPParserTest07", SMTPParserTest07);
5081 UtRegisterTest("SMTPParserTest08", SMTPParserTest08);
5082 UtRegisterTest("SMTPParserTest09", SMTPParserTest09);
5083 UtRegisterTest("SMTPParserTest10", SMTPParserTest10);
5084 UtRegisterTest("SMTPParserTest11", SMTPParserTest11);
5085 UtRegisterTest("SMTPParserTest12", SMTPParserTest12);
5086 UtRegisterTest("SMTPParserTest13", SMTPParserTest13);
5087 UtRegisterTest("SMTPParserTest14", SMTPParserTest14);
5088 UtRegisterTest("SMTPProcessDataChunkTest01", SMTPProcessDataChunkTest01);
5089 UtRegisterTest("SMTPProcessDataChunkTest02", SMTPProcessDataChunkTest02);
5090 UtRegisterTest("SMTPProcessDataChunkTest03", SMTPProcessDataChunkTest03);
5091 UtRegisterTest("SMTPProcessDataChunkTest04", SMTPProcessDataChunkTest04);
5092 UtRegisterTest("SMTPProcessDataChunkTest05", SMTPProcessDataChunkTest05);
87599bc7 5093#endif /* UNITTESTS */
4a6908d3 5094
576ec7da
AS
5095 return;
5096}