suricata
detect-email.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 #include "detect-engine.h"
19 #include "detect-engine-helper.h"
20 #include "detect-parse.h"
21 #include "app-layer-smtp.h"
22 #include "detect-email.h"
23 #include "rust.h"
24 
25 static int g_mime_email_from_buffer_id = 0;
26 static int g_mime_email_subject_buffer_id = 0;
27 static int g_mime_email_to_buffer_id = 0;
28 static int g_mime_email_cc_buffer_id = 0;
29 
30 static int DetectMimeEmailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
31 {
32  if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_from_buffer_id) < 0)
33  return -1;
34 
36  return -1;
37 
38  return 0;
39 }
40 
41 static InspectionBuffer *GetMimeEmailFromData(DetectEngineThreadCtx *det_ctx,
42  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
43  const int list_id)
44 {
45  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
46  if (buffer->inspect == NULL) {
47  SMTPTransaction *tx = (SMTPTransaction *)txv;
48 
49  const uint8_t *b_email_from = NULL;
50  uint32_t b_email_from_len = 0;
51 
52  if (tx->mime_state == NULL)
53  return NULL;
54 
55  if (SCDetectMimeEmailGetData(tx->mime_state, &b_email_from, &b_email_from_len, "from") != 1)
56  return NULL;
57 
58  InspectionBufferSetup(det_ctx, list_id, buffer, b_email_from, b_email_from_len);
59  InspectionBufferApplyTransforms(buffer, transforms);
60  }
61  return buffer;
62 }
63 
64 static int DetectMimeEmailSubjectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
65 {
66  if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_subject_buffer_id) < 0)
67  return -1;
68 
70  return -1;
71 
72  return 0;
73 }
74 
75 static InspectionBuffer *GetMimeEmailSubjectData(DetectEngineThreadCtx *det_ctx,
76  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
77  const int list_id)
78 {
79  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
80  if (buffer->inspect == NULL) {
81  SMTPTransaction *tx = (SMTPTransaction *)txv;
82 
83  const uint8_t *b_email_sub = NULL;
84  uint32_t b_email_sub_len = 0;
85 
86  if (tx->mime_state == NULL)
87  return NULL;
88 
89  if (SCDetectMimeEmailGetData(tx->mime_state, &b_email_sub, &b_email_sub_len, "subject") !=
90  1)
91  return NULL;
92 
93  InspectionBufferSetup(det_ctx, list_id, buffer, b_email_sub, b_email_sub_len);
94  InspectionBufferApplyTransforms(buffer, transforms);
95  }
96  return buffer;
97 }
98 
99 static int DetectMimeEmailToSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
100 {
101  if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_to_buffer_id) < 0)
102  return -1;
103 
105  return -1;
106 
107  return 0;
108 }
109 
110 static InspectionBuffer *GetMimeEmailToData(DetectEngineThreadCtx *det_ctx,
111  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
112  const int list_id)
113 {
114  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
115  if (buffer->inspect == NULL) {
116  SMTPTransaction *tx = (SMTPTransaction *)txv;
117 
118  const uint8_t *b_email_to = NULL;
119  uint32_t b_email_to_len = 0;
120 
121  if ((tx->mime_state != NULL)) {
122  if (SCDetectMimeEmailGetData(tx->mime_state, &b_email_to, &b_email_to_len, "to") != 1)
123  return NULL;
124  }
125 
126  if (b_email_to == NULL || b_email_to_len == 0)
127  return NULL;
128 
129  InspectionBufferSetup(det_ctx, list_id, buffer, b_email_to, b_email_to_len);
130  InspectionBufferApplyTransforms(buffer, transforms);
131  }
132  return buffer;
133 }
134 
135 static int DetectMimeEmailCcSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
136 {
137  if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_cc_buffer_id) < 0)
138  return -1;
139 
141  return -1;
142 
143  return 0;
144 }
145 
146 static InspectionBuffer *GetMimeEmailCcData(DetectEngineThreadCtx *det_ctx,
147  const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
148  const int list_id)
149 {
150  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
151  if (buffer->inspect == NULL) {
152  SMTPTransaction *tx = (SMTPTransaction *)txv;
153 
154  const uint8_t *b_email_cc = NULL;
155  uint32_t b_email_cc_len = 0;
156 
157  if (tx->mime_state == NULL)
158  return NULL;
159 
160  if (SCDetectMimeEmailGetData(tx->mime_state, &b_email_cc, &b_email_cc_len, "cc") != 1)
161  return NULL;
162 
163  InspectionBufferSetup(det_ctx, list_id, buffer, b_email_cc, b_email_cc_len);
164  InspectionBufferApplyTransforms(buffer, transforms);
165  }
166  return buffer;
167 }
168 
170 {
171  SCSigTableElmt kw = { 0 };
172 
173  kw.name = "email.from";
174  kw.desc = "'From' field from an email";
175  kw.url = "/rules/email-keywords.html#email.from";
176  kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailFromSetup;
179  g_mime_email_from_buffer_id =
180  DetectHelperBufferMpmRegister("email.from", "MIME EMAIL FROM", ALPROTO_SMTP, false,
181  true, // to server
182  GetMimeEmailFromData);
183 
184  kw.name = "email.subject";
185  kw.desc = "'Subject' field from an email";
186  kw.url = "/rules/email-keywords.html#email.subject";
187  kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailSubjectSetup;
190  g_mime_email_subject_buffer_id = DetectHelperBufferMpmRegister("email.subject",
191  "MIME EMAIL SUBJECT", ALPROTO_SMTP, false,
192  true, // to server
193  GetMimeEmailSubjectData);
194 
195  kw.name = "email.to";
196  kw.desc = "'To' field from an email";
197  kw.url = "/rules/email-keywords.html#email.to";
198  kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailToSetup;
201  g_mime_email_to_buffer_id =
202  DetectHelperBufferMpmRegister("email.to", "MIME EMAIL TO", ALPROTO_SMTP, false,
203  true, // to server
204  GetMimeEmailToData);
205 
206  kw.name = "email.cc";
207  kw.desc = "'Cc' field from an email";
208  kw.url = "/rules/email-keywords.html#email.cc";
209  kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailCcSetup;
212  g_mime_email_cc_buffer_id =
213  DetectHelperBufferMpmRegister("email.cc", "MIME EMAIL CC", ALPROTO_SMTP, false,
214  true, // to server
215  GetMimeEmailCcData);
216 }
DetectEmailRegister
void DetectEmailRegister(void)
Definition: detect-email.c:169
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1870
detect-engine.h
SIGMATCH_INFO_STICKY_BUFFER
#define SIGMATCH_INFO_STICKY_BUFFER
Definition: detect.h:1534
detect-email.h
DetectEngineTransforms
Definition: detect.h:409
DetectBufferSetActiveList
int DetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
Definition: detect-engine.c:1377
InspectionBuffer
Definition: detect.h:374
Flow_
Flow data structure.
Definition: flow.h:354
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:860
rust.h
DetectHelperBufferMpmRegister
int DetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto, bool toclient, bool toserver, InspectionBufferGetDataPtr GetData)
Definition: detect-engine-helper.c:64
InspectionBufferGet
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine.c:1521
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1116
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
detect-engine-helper.h
SMTPTransaction_
Definition: app-layer-smtp.h:72
InspectionBufferApplyTransforms
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
Definition: detect-engine.c:1593
DetectHelperKeywordRegister
int DetectHelperKeywordRegister(const SCSigTableElmt *kw)
Definition: detect-engine-helper.c:114
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:375
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:1655
detect-parse.h
Signature_
Signature container.
Definition: detect.h:618
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1510
app-layer-smtp.h
SMTPTransaction_::mime_state
MimeStateSMTP * mime_state
Definition: app-layer-smtp.h:85