suricata
output-json-email-common.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2015 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 Tom DeCanio <td@npulsetech.com>
22 * \author Eric Leblond <eric@regit.org>
23 *
24 * Implements json common email logging portion of the engine.
25 */
26
27#include "suricata-common.h"
28#include "detect.h"
29#include "pkt-var.h"
30#include "conf.h"
31#include "suricata.h"
32
33#include "threads.h"
34#include "threadvars.h"
35#include "tm-threads.h"
36#include "tm-threads-common.h"
37
38#include "util-print.h"
39#include "util-unittest.h"
40
41#include "util-debug.h"
42#include "app-layer-parser.h"
43#include "output.h"
44#include "app-layer-smtp.h"
45#include "app-layer.h"
46#include "util-privs.h"
47#include "util-buffer.h"
48#include "util-byte.h"
49
50#include "util-logopenfile.h"
51
52#include "output-json.h"
54
55#define LOG_EMAIL_DEFAULT 0
56#define LOG_EMAIL_EXTENDED (1<<0)
57#define LOG_EMAIL_ARRAY (1<<1) /* require array handling */
58#define LOG_EMAIL_COMMA (1<<2) /* require array handling */
59#define LOG_EMAIL_BODY_MD5 (1<<3)
60#define LOG_EMAIL_SUBJECT_MD5 (1<<4)
61
62struct {
63 const char *config_field;
64 const char *email_field;
65 uint32_t flags;
66} email_fields[] = {
67 { "reply_to", "reply-to", LOG_EMAIL_DEFAULT },
68 { "bcc", "bcc", LOG_EMAIL_COMMA|LOG_EMAIL_EXTENDED },
69 { "message_id", "message-id", LOG_EMAIL_EXTENDED },
70 { "subject", "subject", LOG_EMAIL_EXTENDED },
71 { "x_mailer", "x-mailer", LOG_EMAIL_EXTENDED },
72 { "user_agent", "user-agent", LOG_EMAIL_EXTENDED },
73 { "received", "received", LOG_EMAIL_ARRAY },
74 { "x_originating_ip", "x-originating-ip", LOG_EMAIL_DEFAULT },
75 { "in_reply_to", "in-reply-to", LOG_EMAIL_DEFAULT },
76 { "references", "references", LOG_EMAIL_DEFAULT },
77 { "importance", "importance", LOG_EMAIL_DEFAULT },
78 { "priority", "priority", LOG_EMAIL_DEFAULT },
79 { "sensitivity", "sensitivity", LOG_EMAIL_DEFAULT },
80 { "organization", "organization", LOG_EMAIL_DEFAULT },
81 { "content_md5", "content-md5", LOG_EMAIL_DEFAULT },
82 { "date", "date", LOG_EMAIL_DEFAULT },
83 { NULL, NULL, LOG_EMAIL_DEFAULT},
84};
85
86static void EveEmailLogJSONMd5(
87 OutputJsonEmailCtx *email_ctx, SCJsonBuilder *js, SMTPTransaction *tx)
88{
89 if (email_ctx->flags & LOG_EMAIL_SUBJECT_MD5) {
90 MimeStateSMTP *entity = tx->mime_state;
91 if (entity == NULL) {
92 return;
93 }
94 SCMimeSmtpLogSubjectMd5(js, entity);
95 }
96
97 if (email_ctx->flags & LOG_EMAIL_BODY_MD5) {
98 MimeStateSMTP *entity = tx->mime_state;
99 if (entity == NULL) {
100 return;
101 }
102 SCMimeSmtpLogBodyMd5(js, entity);
103 }
104}
105
106static void EveEmailLogJSONCustom(
107 OutputJsonEmailCtx *email_ctx, SCJsonBuilder *js, SMTPTransaction *tx)
108{
109 int f = 0;
110 MimeStateSMTP *entity = tx->mime_state;
111 if (entity == NULL) {
112 return;
113 }
114
115 while(email_fields[f].config_field) {
116 if (((email_ctx->fields & (1ULL<<f)) != 0)
117 ||
118 ((email_ctx->flags & LOG_EMAIL_EXTENDED) && (email_fields[f].flags & LOG_EMAIL_EXTENDED))
119 ) {
121 SCMimeSmtpLogFieldArray(
123 } else if (email_fields[f].flags & LOG_EMAIL_COMMA) {
124 SCMimeSmtpLogFieldComma(
126 } else {
127 SCMimeSmtpLogFieldString(
129 }
130
131 }
132 f++;
133 }
134}
135
136/* JSON format logging */
137static bool EveEmailLogJsonData(
138 const Flow *f, void *state, void *vtx, uint64_t tx_id, SCJsonBuilder *sjs)
139{
140 SMTPState *smtp_state;
141 MimeStateSMTP *mime_state;
142
143 /* check if we have SMTP state or not */
144 AppProto proto = FlowGetAppProtocol(f);
145 switch (proto) {
146 case ALPROTO_SMTP:
147 smtp_state = (SMTPState *)state;
148 if (smtp_state == NULL) {
149 SCLogDebug("no smtp state, so no request logging");
150 SCJbFree(sjs);
151 SCReturnPtr(NULL, "SCJsonBuilder");
152 }
153 SMTPTransaction *tx = vtx;
154 mime_state = tx->mime_state;
155 SCLogDebug("lets go mime_state %p", mime_state);
156 break;
157 default:
158 /* don't know how we got here */
159 SCReturnBool(false);
160 }
161 if ((mime_state != NULL)) {
162 SCMimeSmtpLogData(sjs, mime_state);
163 SCReturnBool(true);
164 }
165
166 SCReturnBool(false);
167}
168
169/* JSON format logging */
170TmEcode EveEmailLogJson(JsonEmailLogThread *aft, SCJsonBuilder *js, const Packet *p, Flow *f,
171 void *state, void *vtx, uint64_t tx_id)
172{
173 OutputJsonEmailCtx *email_ctx = aft->emaillog_ctx;
174 SMTPTransaction *tx = (SMTPTransaction *) vtx;
175 SCJsonBuilderMark mark = { 0, 0, 0 };
176
177 SCJbGetMark(js, &mark);
178 SCJbOpenObject(js, "email");
179 if (!EveEmailLogJsonData(f, state, vtx, tx_id, js)) {
180 SCJbRestoreMark(js, &mark);
182 }
183
184 if ((email_ctx->flags & LOG_EMAIL_EXTENDED) || (email_ctx->fields != 0))
185 EveEmailLogJSONCustom(email_ctx, js, tx);
186
187 if (!g_disable_hashing) {
188 EveEmailLogJSONMd5(email_ctx, js, tx);
189 }
190
191 SCJbClose(js);
193}
194
195bool EveEmailAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
196{
197 SMTPState *smtp_state = (SMTPState *)FlowGetAppState(f);
198 if (smtp_state) {
199 SMTPTransaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_SMTP, smtp_state, tx_id);
200 if (tx) {
201 return EveEmailLogJsonData(f, smtp_state, tx, tx_id, js);
202 }
203 }
204
205 return false;
206}
207
209{
210 if (conf) {
211 const char *extended = SCConfNodeLookupChildValue(conf, "extended");
212
213 if (extended != NULL) {
214 if (SCConfValIsTrue(extended)) {
215 email_ctx->flags = LOG_EMAIL_EXTENDED;
216 }
217 }
218
219 email_ctx->fields = 0;
220 SCConfNode *custom;
221 if ((custom = SCConfNodeLookupChild(conf, "custom")) != NULL) {
222 SCConfNode *field;
223 TAILQ_FOREACH (field, &custom->head, next) {
224 int f = 0;
225 while (email_fields[f].config_field) {
226 if ((strcmp(email_fields[f].config_field, field->val) == 0) ||
227 (strcasecmp(email_fields[f].email_field, field->val) == 0)) {
228 email_ctx->fields |= (1ULL << f);
229 break;
230 }
231 f++;
232 }
233 }
234 }
235
236 email_ctx->flags = 0;
237 SCConfNode *md5_conf;
238 if ((md5_conf = SCConfNodeLookupChild(conf, "md5")) != NULL) {
239 SCConfNode *field;
240 TAILQ_FOREACH (field, &md5_conf->head, next) {
241 if (strcmp("body", field->val) == 0) {
242 SCLogInfo("Going to log the md5 sum of email body");
243 email_ctx->flags |= LOG_EMAIL_BODY_MD5;
244 }
245 if (strcmp("subject", field->val) == 0) {
246 SCLogInfo("Going to log the md5 sum of email subject");
247 email_ctx->flags |= LOG_EMAIL_SUBJECT_MD5;
248 }
249 }
250 }
251 }
252}
struct HtpBodyChunk_ * next
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
uint16_t AppProto
@ ALPROTO_SMTP
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition conf.c:796
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition conf.c:551
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition conf.c:824
uint8_t proto
#define LOG_EMAIL_ARRAY
#define LOG_EMAIL_COMMA
const char * config_field
void OutputEmailInitConf(SCConfNode *conf, OutputJsonEmailCtx *email_ctx)
#define LOG_EMAIL_BODY_MD5
const char * email_field
struct @143 email_fields[]
#define LOG_EMAIL_SUBJECT_MD5
bool EveEmailAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
uint32_t flags
#define LOG_EMAIL_DEFAULT
TmEcode EveEmailLogJson(JsonEmailLogThread *aft, SCJsonBuilder *js, const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id)
#define LOG_EMAIL_EXTENDED
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
Flow data structure.
Definition flow.h:356
OutputJsonEmailCtx * emaillog_ctx
char * val
Definition conf.h:39
MimeStateSMTP * mime_state
bool g_disable_hashing
Definition suricata.c:214
@ TM_ECODE_FAILED
@ TM_ECODE_OK
#define SCReturnBool(x)
Definition util-debug.h:295
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCReturnPtr(x, type)
Definition util-debug.h:293