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