]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer-smtp: extract and store HELO and MAIL FROM
authorEric Leblond <eric@regit.org>
Fri, 17 Apr 2015 08:46:15 +0000 (10:46 +0200)
committerEric Leblond <eric@regit.org>
Fri, 2 Oct 2015 20:57:58 +0000 (22:57 +0200)
This patch updates the SMTP transaction and SMTP state to be able
to contain the HELO and MAIL FROM fields.

src/app-layer-smtp.c
src/app-layer-smtp.h

index 1951613d1f3a2cb740582a7fed0517e0d6b1984f..d0c6589eea8fd89908921a9dc8f6fb591263e310 100644 (file)
@@ -955,6 +955,52 @@ static int SMTPParseCommandBDAT(SMTPState *state)
     return 0;
 }
 
+static int SMTPParseCommandWithParam(SMTPState *state, uint8_t prefix_len, uint8_t **target, uint16_t *target_len)
+{
+    int i = prefix_len + 1;
+    int spc_i = 0;
+
+    while (i < state->current_line_len) {
+        if (state->current_line[i] != ' ') {
+            break;
+        }
+        i++;
+    }
+
+    /* rfc1870: with the size extension the mail from can be followed by an option.
+       We use the space separator to detect it. */
+    spc_i = i;
+    while (spc_i < state->current_line_len) {
+        if (state->current_line[spc_i] == ' ') {
+            break;
+        }
+        spc_i++;
+    }
+
+    /* FIXME check arithmetic */
+    *target = SCMalloc(spc_i - i + 1);
+    if (*target == NULL)
+        return -1;
+    memcpy(*target, state->current_line + i, spc_i - i);
+    (*target)[spc_i - i] = '\0';
+    *target_len = spc_i - i;
+
+    return 0;
+
+}
+
+static int SMTPParseCommandHELO(SMTPState *state)
+{
+    return SMTPParseCommandWithParam(state, 4, &state->helo, &state->helo_len);
+}
+
+static int SMTPParseCommandMAILFROM(SMTPState *state)
+{
+    return SMTPParseCommandWithParam(state, 9,
+                                     &state->curr_tx->mail_from,
+                                     &state->curr_tx->mail_from_len);
+}
+
 /* consider 'rset' and 'quit' to be part of the existing state */
 static int NoNewTx(SMTPState *state)
 {
@@ -1027,6 +1073,21 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f,
             }
             state->current_command = SMTP_COMMAND_BDAT;
             state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
+        } else if (state->current_line_len >= 4 &&
+                   ((SCMemcmpLowercase("helo", state->current_line, 4) == 0) ||
+                    SCMemcmpLowercase("ehlo", state->current_line, 4) == 0))  {
+            r = SMTPParseCommandHELO(state);
+            if (r == -1) {
+                SCReturnInt(-1);
+            }
+            state->current_command = SMTP_COMMAND_OTHER_CMD;
+        } else if (state->current_line_len >= 9 &&
+                   SCMemcmpLowercase("mail from", state->current_line, 9) == 0) {
+            r = SMTPParseCommandMAILFROM(state);
+            if (r == -1) {
+                SCReturnInt(-1);
+            }
+            state->current_command = SMTP_COMMAND_OTHER_CMD;
         } else {
             state->current_command = SMTP_COMMAND_OTHER_CMD;
         }
@@ -1178,6 +1239,10 @@ static void SMTPTransactionFree(SMTPTransaction *tx, SMTPState *state)
 
     if (tx->de_state != NULL)
         DetectEngineStateFree(tx->de_state);
+
+    if (tx->mail_from)
+        SCFree(tx->mail_from);
+
 #if 0
         if (tx->decoder_events->cnt <= smtp_state->events)
             smtp_state->events -= tx->decoder_events->cnt;
@@ -1205,6 +1270,10 @@ static void SMTPStateFree(void *p)
         SCFree(smtp_state->tc_db);
     }
 
+    if (smtp_state->helo) {
+        SCFree(smtp_state->helo);
+    }
+
     FileContainerFree(smtp_state->files_ts);
 
     SMTPTransaction *tx = NULL;
index 02090c61c07ed35500b2e66f7e28bf87ce243436..a63061638ea692d19d051e3a5374d32bb270b8f1 100644 (file)
@@ -65,6 +65,10 @@ typedef struct SMTPTransaction_ {
     AppLayerDecoderEvents *decoder_events;          /**< per tx events */
     DetectEngineState *de_state;
 
+    /* MAIL FROM parameters */
+    uint8_t *mail_from;
+    uint16_t mail_from_len;
+
     TAILQ_ENTRY(SMTPTransaction_) next;
 } SMTPTransaction;
 
@@ -136,6 +140,9 @@ typedef struct SMTPState_ {
     /** the list of files sent to the server */
     FileContainer *files_ts;
 
+    /* HELO of HELO message content */
+    uint8_t *helo;
+    uint16_t helo_len;
 } SMTPState;
 
 /* Create SMTP config structure */