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