smtp reply code mpm phase support added

remotes/origin/master-1.2.x
Anoop Saldanha 14 years ago committed by Victor Julien
parent 4a6908d3e9
commit 4d38a571cc

@ -91,6 +91,74 @@
#define SMTP_EHLO_EXTENSION_STARTTLS
#define SMTP_EHLO_EXTENSION_8BITMIME
#define SMTP_MPM MPM_AC
static MpmCtx *smtp_mpm_ctx = NULL;
MpmThreadCtx *smtp_mpm_thread_ctx;
/* smtp reply codes. If an entry is made here, please make a simultaneous
* entry in smtp_reply_map */
enum {
SMTP_REPLY_211,
SMTP_REPLY_214,
SMTP_REPLY_220,
SMTP_REPLY_221,
SMTP_REPLY_250,
SMTP_REPLY_251,
SMTP_REPLY_252,
SMTP_REPLY_354,
SMTP_REPLY_421,
SMTP_REPLY_450,
SMTP_REPLY_451,
SMTP_REPLY_452,
SMTP_REPLY_455,
SMTP_REPLY_500,
SMTP_REPLY_501,
SMTP_REPLY_502,
SMTP_REPLY_503,
SMTP_REPLY_504,
SMTP_REPLY_550,
SMTP_REPLY_551,
SMTP_REPLY_552,
SMTP_REPLY_553,
SMTP_REPLY_554,
SMTP_REPLY_555,
};
SCEnumCharMap smtp_reply_map[ ] = {
{ "211", SMTP_REPLY_211 },
{ "214", SMTP_REPLY_214 },
{ "220", SMTP_REPLY_220 },
{ "221", SMTP_REPLY_221 },
{ "250", SMTP_REPLY_250 },
{ "251", SMTP_REPLY_251 },
{ "252", SMTP_REPLY_252 },
{ "354", SMTP_REPLY_354 },
{ "421", SMTP_REPLY_421 },
{ "450", SMTP_REPLY_450 },
{ "451", SMTP_REPLY_451 },
{ "452", SMTP_REPLY_452 },
{ "455", SMTP_REPLY_455 },
{ "500", SMTP_REPLY_500 },
{ "501", SMTP_REPLY_501 },
{ "502", SMTP_REPLY_502 },
{ "503", SMTP_REPLY_503 },
{ "504", SMTP_REPLY_504 },
{ "550", SMTP_REPLY_550 },
{ "551", SMTP_REPLY_551 },
{ "552", SMTP_REPLY_552 },
{ "553", SMTP_REPLY_553 },
{ "554", SMTP_REPLY_554 },
{ "555", SMTP_REPLY_555 },
{ NULL, -1 },
};
//static void SMTPParserReset(void)
//{
// return;
@ -131,7 +199,7 @@ static int SMTPGetLine(SMTPState *state)
uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
if (lf_idx == NULL) {
/* set decoder event */
/* Fragmented line - set decoder event */
if (state->ts_current_line_db == 0) {
state->ts_db = SCMalloc(state->input_len);
if (state->ts_db == NULL) {
@ -190,6 +258,7 @@ static int SMTPGetLine(SMTPState *state)
state->current_line_len--;
state->current_line_delimiter_len = 2;
} else {
/* set decoder event for just LF delimiter */
state->current_line_delimiter_len = 1;
}
}
@ -219,7 +288,7 @@ static int SMTPGetLine(SMTPState *state)
uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
if (lf_idx == NULL) {
/* set decoder event */
/* Fragmented line - set decoder event */
if (state->tc_current_line_db == 0) {
state->tc_db = SCMalloc(state->input_len);
if (state->tc_db == NULL) {
@ -278,6 +347,7 @@ static int SMTPGetLine(SMTPState *state)
state->current_line_len--;
state->current_line_delimiter_len = 2;
} else {
/* set decoder event for just LF delimiter */
state->current_line_delimiter_len = 1;
}
}
@ -373,11 +443,6 @@ static int SMTPProcessReply(SMTPState *state, Flow *f,
{
uint64_t reply_code = 0;
if (state->cmds_idx == state->cmds_cnt) {
/* decoder event - unable to match reply with request */
return -1;
}
/* the reply code has to contain at least 3 bytes, to hold the 3 digit
* reply code */
if (state->current_line_len < 3) {
@ -401,9 +466,20 @@ static int SMTPProcessReply(SMTPState *state, Flow *f,
}
}
if (ByteExtractString(&reply_code, 10, 3,
(const char *)state->current_line) < 3) {
/* decoder event */
/* I don't like this pmq reset here. We'll devise a method later, that
* should make the use of the mpm very efficient */
PmqReset(state->pmq);
int mpm_cnt = mpm_table[SMTP_MPM].Search(smtp_mpm_ctx, smtp_mpm_thread_ctx,
state->pmq, state->current_line,
3);
if (mpm_cnt == 0) {
/* set decoder event - reply code invalid */
return -1;
}
reply_code = smtp_reply_map[state->pmq->pattern_id_array[0]].enum_value;
if (state->cmds_idx == state->cmds_cnt) {
/* decoder event - unable to match reply with request */
return -1;
}
@ -416,13 +492,15 @@ static int SMTPProcessReply(SMTPState *state, Flow *f,
* leave without matching it against any buffered command */
if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN;
if (reply_code == 220) {
if (reply_code == SMTP_REPLY_220) {
return 0;
} else {
/* set decoder event - first reply from server not a welcome message */
}
}
if (state->cmds[state->cmds_idx] == SMTP_COMMAND_STARTTLS) {
if (reply_code == 220) {
if (reply_code == SMTP_REPLY_220) {
/* we are entering STARRTTLS data mode */
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
pstate->flags |= APP_LAYER_PARSER_DONE;
@ -432,17 +510,19 @@ static int SMTPProcessReply(SMTPState *state, Flow *f,
/* decoder event */
}
} else if (state->cmds[state->cmds_idx] == SMTP_COMMAND_DATA) {
if (reply_code == 354) {
if (reply_code == SMTP_REPLY_354) {
/* Next comes the mail for the DATA command in toserver direction */
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
} else {
/* decoder event */
}
} else {
/* we don't care for any other command */
/* we don't care for any other command for now */
/* check if reply falls in the valid list of replies for SMTP. If not
* decoder event */
}
/* if it is a multiline reply, we need to move the index only once for all
/* if it is a multi-line reply, we need to move the index only once for all
* the line of the reply. We unset the multiline flag on the last
* line of the multiline reply, following which we increment the index */
if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
@ -601,6 +681,14 @@ static void *SMTPStateAlloc(void)
}
smtp_state->cmds_buffer_len = SMTP_COMMAND_BUFFER_STEPS;
smtp_state->pmq = SCMalloc(sizeof(PatternMatcherQueue));
if (smtp_state->pmq == NULL) {
/* we need to exit here, since it is load time */
exit(EXIT_FAILURE);
}
PmqSetup(smtp_state->pmq, 0,
sizeof(smtp_reply_map)/sizeof(SCEnumCharMap) - 2);
return smtp_state;
}
@ -612,6 +700,10 @@ static void SMTPStateFree(void *p)
{
SMTPState *smtp_state = (SMTPState *)p;
if (smtp_state->pmq != NULL) {
PmqFree(smtp_state->pmq);
SCFree(smtp_state->pmq);
}
if (smtp_state->cmds != NULL) {
SCFree(smtp_state->cmds);
}
@ -627,6 +719,41 @@ static void SMTPStateFree(void *p)
return;
}
static void SMTPSetMpmState(void)
{
smtp_mpm_ctx = SCMalloc(sizeof(MpmCtx));
if (smtp_mpm_ctx == NULL) {
/* we need to exit here, since it is load time */
exit(EXIT_FAILURE);
}
memset(smtp_mpm_ctx, 0, sizeof(MpmCtx));
smtp_mpm_thread_ctx = SCMalloc(sizeof(MpmThreadCtx));
if (smtp_mpm_thread_ctx == NULL) {
/* we need to exit here, since it is load time */
exit(EXIT_FAILURE);
}
memset(smtp_mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
mpm_table[SMTP_MPM].InitCtx(smtp_mpm_ctx, -1);
mpm_table[SMTP_MPM].InitThreadCtx(smtp_mpm_ctx, smtp_mpm_thread_ctx, 0);
uint32_t i = 0;
for (i = 0; i < sizeof(smtp_reply_map)/sizeof(SCEnumCharMap) - 1; i++) {
SCEnumCharMap *map = &smtp_reply_map[i];
mpm_table[SMTP_MPM].AddPatternNocase(smtp_mpm_ctx,
(uint8_t *)map->enum_name,
3 /* reply codes always 3 bytes */,
0 /* now defunct option */,
0 /* now defunct option */,
i /* pattern id */,
0 /* no sid */,
0 /* no flags */);
}
mpm_table[SMTP_MPM].Prepare(smtp_mpm_ctx);
}
/**
* \brief Register the SMPT Protocol parser.
*/
@ -644,6 +771,8 @@ void RegisterSMTPParsers(void)
AppLayerRegisterProto("smtp", ALPROTO_SMTP, STREAM_TOCLIENT,
SMTPParseServerRecord);
SMTPSetMpmState();
return;
}

@ -73,6 +73,9 @@ typedef struct SMTPState_ {
/** index of the command in the buffer, currently in inspection by reply
* handler */
uint16_t cmds_idx;
/* needed by the mpm */
PatternMatcherQueue *pmq;
} SMTPState;
void RegisterSMTPParsers(void);

@ -425,12 +425,16 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data) {
if (det_ctx->de_state_sig_array == NULL) {
return TM_ECODE_FAILED;
}
memset(det_ctx->de_state_sig_array, 0,
det_ctx->de_state_sig_array_len * sizeof(uint8_t));
det_ctx->match_array_len = de_ctx->sig_array_len;
det_ctx->match_array = SCMalloc(det_ctx->match_array_len * sizeof(Signature *));
if (det_ctx->match_array == NULL) {
return TM_ECODE_FAILED;
}
memset(det_ctx->match_array, 0,
det_ctx->match_array_len * sizeof(Signature *));
}
/** alert counter setup */

Loading…
Cancel
Save