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