suricata
detect-smtp.c
Go to the documentation of this file.
1 /* Copyright (C) 2025 Open Information Security Foundation
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  *
21  * \author Philippe Antoine <pantoine@oisf.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "detect-smtp.h"
27 #include "detect-engine.h"
29 #include "detect-engine-helper.h"
30 #include "detect-parse.h"
31 #include "app-layer-smtp.h"
32 #include "rust.h"
33 
34 static int g_smtp_helo_buffer_id = 0;
35 static int g_smtp_mail_from_buffer_id = 0;
36 static int g_smtp_rcpt_to_buffer_id = 0;
37 
38 static int DetectSmtpHeloSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
39 {
40  if (DetectBufferSetActiveList(de_ctx, s, g_smtp_helo_buffer_id) < 0)
41  return -1;
42 
44  return -1;
45 
46  return 0;
47 }
48 
49 static InspectionBuffer *GetSmtpHeloData(DetectEngineThreadCtx *det_ctx,
50  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
51  const int list_id)
52 {
53  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
54  if (buffer->inspect == NULL) {
55  SMTPState *smtp_state = (SMTPState *)FlowGetAppState(f);
56  if (smtp_state) {
57  if (smtp_state->helo == NULL || smtp_state->helo_len == 0)
58  return NULL;
59  InspectionBufferSetup(det_ctx, list_id, buffer, smtp_state->helo, smtp_state->helo_len);
60  InspectionBufferApplyTransforms(buffer, transforms);
61  }
62  }
63  return buffer;
64 }
65 
66 static int DetectSmtpMailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
67 {
68  if (DetectBufferSetActiveList(de_ctx, s, g_smtp_mail_from_buffer_id) < 0)
69  return -1;
70 
72  return -1;
73 
74  return 0;
75 }
76 
77 static InspectionBuffer *GetSmtpMailFromData(DetectEngineThreadCtx *det_ctx,
78  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
79  const int list_id)
80 {
81  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
82  if (buffer->inspect == NULL) {
83  SMTPTransaction *tx = (SMTPTransaction *)txv;
84  if (tx->mail_from == NULL || tx->mail_from_len == 0)
85  return NULL;
86  InspectionBufferSetup(det_ctx, list_id, buffer, tx->mail_from, tx->mail_from_len);
87  InspectionBufferApplyTransforms(buffer, transforms);
88  }
89  return buffer;
90 }
91 
92 static int DetectSmtpRcptToSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
93 {
94  if (DetectBufferSetActiveList(de_ctx, s, g_smtp_rcpt_to_buffer_id) < 0)
95  return -1;
96 
98  return -1;
99 
100  return 0;
101 }
102 
103 static InspectionBuffer *GetSmtpRcptToData(DetectEngineThreadCtx *det_ctx,
104  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
105  const int list_id, uint32_t idx)
106 {
107  InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, idx);
108  if (buffer == NULL || buffer->initialized)
109  return buffer;
110 
111  SMTPTransaction *tx = (SMTPTransaction *)txv;
112  if (TAILQ_EMPTY(&tx->rcpt_to_list)) {
114  return NULL;
115  }
116 
117  SMTPString *s;
118  if (idx == 0) {
119  s = TAILQ_FIRST(&tx->rcpt_to_list);
120  } else {
121  // TODO optimize ?
122  s = TAILQ_FIRST(&tx->rcpt_to_list);
123  for (uint32_t i = 0; i < idx; i++) {
124  s = TAILQ_NEXT(s, next);
125  }
126  }
127  if (s == NULL) {
129  return NULL;
130  }
131 
132  InspectionBufferSetupMulti(buffer, transforms, s->str, s->len);
133  buffer->flags = DETECT_CI_FLAGS_SINGLE;
134  return buffer;
135 }
136 
138 {
139  SCSigTableElmt kw = { 0 };
140  kw.name = "smtp.helo";
141  kw.desc = "SMTP helo buffer";
142  kw.url = "/rules/smtp-keywords.html#smtp-helo";
143  kw.Setup = (int (*)(void *, void *, const char *))DetectSmtpHeloSetup;
146  g_smtp_helo_buffer_id =
147  DetectHelperBufferMpmRegister("smtp.helo", "SMTP helo", ALPROTO_SMTP, false,
148  true, // to server
149  GetSmtpHeloData);
150 
151  kw.name = "smtp.mail_from";
152  kw.desc = "SMTP mail from buffer";
153  kw.url = "/rules/smtp-keywords.html#smtp-mail-from";
154  kw.Setup = (int (*)(void *, void *, const char *))DetectSmtpMailFromSetup;
157  g_smtp_mail_from_buffer_id =
158  DetectHelperBufferMpmRegister("smtp.mail_from", "SMTP MAIL FROM", ALPROTO_SMTP, false,
159  true, // to server
160  GetSmtpMailFromData);
161 
162  kw.name = "smtp.rcpt_to";
163  kw.desc = "SMTP rcpt to buffer";
164  kw.url = "/rules/smtp-keywords.html#smtp-rcpt-to";
165  kw.Setup = (int (*)(void *, void *, const char *))DetectSmtpRcptToSetup;
168  g_smtp_rcpt_to_buffer_id =
169  DetectHelperMultiBufferMpmRegister("smtp.rcpt_to", "SMTP RCPT TO", ALPROTO_SMTP, false,
170  true, // to server
171  GetSmtpRcptToData);
172 }
SMTPState_
Definition: app-layer-smtp.h:116
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1770
detect-engine.h
SIGMATCH_INFO_STICKY_BUFFER
#define SIGMATCH_INFO_STICKY_BUFFER
Definition: detect.h:1527
InspectionBuffer::initialized
bool initialized
Definition: detect.h:379
DetectEngineTransforms
Definition: detect.h:410
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectBufferSetActiveList
int DetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
Definition: detect-engine.c:1359
InspectionBuffer
Definition: detect.h:375
Flow_
Flow data structure.
Definition: flow.h:354
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:854
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:248
rust.h
InspectionBuffer::flags
uint8_t flags
Definition: detect.h:380
DetectHelperBufferMpmRegister
int DetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto, bool toclient, bool toserver, InspectionBufferGetDataPtr GetData)
Definition: detect-engine-helper.c:65
InspectionBufferGet
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine.c:1503
InspectionBufferSetupMultiEmpty
void InspectionBufferSetupMultiEmpty(InspectionBuffer *buffer)
setup the buffer empty
Definition: detect-engine.c:1570
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:250
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1109
SCDetectSMTPRegister
void SCDetectSMTPRegister(void)
Definition: detect-smtp.c:137
SMTPState_::helo
uint8_t * helo
Definition: app-layer-smtp.h:151
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
SMTPTransaction_::mail_from
uint8_t * mail_from
Definition: app-layer-smtp.h:88
detect-engine-helper.h
SMTPTransaction_
Definition: app-layer-smtp.h:72
DetectHelperMultiBufferMpmRegister
int DetectHelperMultiBufferMpmRegister(const char *name, const char *desc, AppProto alproto, bool toclient, bool toserver, InspectionMultiBufferGetDataPtr GetData)
Definition: detect-engine-helper.c:84
SMTPTransaction_::mail_from_len
uint16_t mail_from_len
Definition: app-layer-smtp.h:89
detect-smtp.h
detect-engine-content-inspection.h
SMTPString_::len
uint16_t len
Definition: app-layer-smtp.h:67
SMTPState_::helo_len
uint16_t helo_len
Definition: app-layer-smtp.h:150
DETECT_CI_FLAGS_SINGLE
#define DETECT_CI_FLAGS_SINGLE
Definition: detect-engine-content-inspection.h:49
suricata-common.h
InspectionBufferApplyTransforms
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
Definition: detect-engine.c:1714
DetectHelperKeywordRegister
int DetectHelperKeywordRegister(const SCSigTableElmt *kw)
Definition: detect-engine-helper.c:98
TAILQ_NEXT
#define TAILQ_NEXT(elm, field)
Definition: queue.h:307
SMTPString_
Definition: app-layer-smtp.h:65
InspectionBufferSetupMulti
void InspectionBufferSetupMulti(InspectionBuffer *buffer, const DetectEngineTransforms *transforms, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1583
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:376
InspectionBufferSetup
void InspectionBufferSetup(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1598
detect-parse.h
Signature_
Signature container.
Definition: detect.h:614
InspectionBufferMultipleForListGet
InspectionBuffer * InspectionBufferMultipleForListGet(DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
Definition: detect-engine.c:1523
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1503
SMTPString_::str
uint8_t * str
Definition: app-layer-smtp.h:66
app-layer-smtp.h