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