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