/src/suricata7/src/output-json-smtp.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2021 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 | | * |
23 | | * Implements SMTP JSON logging portion of the engine. |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "detect.h" |
28 | | #include "pkt-var.h" |
29 | | #include "conf.h" |
30 | | |
31 | | #include "threads.h" |
32 | | #include "threadvars.h" |
33 | | #include "tm-threads.h" |
34 | | |
35 | | #include "util-print.h" |
36 | | #include "util-unittest.h" |
37 | | |
38 | | #include "util-debug.h" |
39 | | |
40 | | #include "output.h" |
41 | | #include "app-layer-smtp.h" |
42 | | #include "app-layer.h" |
43 | | #include "app-layer-parser.h" |
44 | | #include "util-privs.h" |
45 | | #include "util-buffer.h" |
46 | | #include "util-proto-name.h" |
47 | | #include "util-logopenfile.h" |
48 | | #include "util-time.h" |
49 | | |
50 | | #include "output-json.h" |
51 | | #include "output-json-smtp.h" |
52 | | #include "output-json-email-common.h" |
53 | | |
54 | | static void EveSmtpDataLogger(void *state, void *vtx, JsonBuilder *js) |
55 | 13.4k | { |
56 | 13.4k | SMTPTransaction *tx = vtx; |
57 | 13.4k | SMTPString *rcptto_str; |
58 | 13.4k | if (((SMTPState *)state)->helo) { |
59 | 13.1k | jb_set_string(js, "helo", (const char *)((SMTPState *)state)->helo); |
60 | 13.1k | } |
61 | 13.4k | if (tx->mail_from) { |
62 | 9.61k | jb_set_string(js, "mail_from", (const char *)tx->mail_from); |
63 | 9.61k | } |
64 | 13.4k | if (!TAILQ_EMPTY(&tx->rcpt_to_list)) { |
65 | 9.60k | jb_open_array(js, "rcpt_to"); |
66 | 13.4k | TAILQ_FOREACH(rcptto_str, &tx->rcpt_to_list, next) { |
67 | 13.4k | jb_append_string(js, (char *)rcptto_str->str); |
68 | 13.4k | } |
69 | 9.60k | jb_close(js); |
70 | 9.60k | } |
71 | 13.4k | } |
72 | | |
73 | | static int JsonSmtpLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) |
74 | 9.37k | { |
75 | 9.37k | SCEnter(); |
76 | 9.37k | JsonEmailLogThread *jhl = (JsonEmailLogThread *)thread_data; |
77 | | |
78 | 9.37k | JsonBuilder *jb = CreateEveHeaderWithTxId( |
79 | 9.37k | p, LOG_DIR_FLOW, "smtp", NULL, tx_id, jhl->emaillog_ctx->eve_ctx); |
80 | 9.37k | if (unlikely(jb == NULL)) |
81 | 0 | return TM_ECODE_OK; |
82 | | |
83 | 9.37k | jb_open_object(jb, "smtp"); |
84 | 9.37k | EveSmtpDataLogger(state, tx, jb); |
85 | 9.37k | jb_close(jb); |
86 | | |
87 | 9.37k | EveEmailLogJson(jhl, jb, p, f, state, tx, tx_id); |
88 | 9.37k | OutputJsonBuilderBuffer(jb, jhl->ctx); |
89 | | |
90 | 9.37k | jb_free(jb); |
91 | | |
92 | 9.37k | SCReturnInt(TM_ECODE_OK); |
93 | | |
94 | 9.37k | } |
95 | | |
96 | | bool EveSMTPAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) |
97 | 4.28k | { |
98 | 4.28k | SMTPState *smtp_state = (SMTPState *)FlowGetAppState(f); |
99 | 4.28k | if (smtp_state) { |
100 | 4.28k | SMTPTransaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_SMTP, smtp_state, tx_id); |
101 | 4.28k | if (tx) { |
102 | 4.09k | EveSmtpDataLogger(smtp_state, tx, js); |
103 | 4.09k | return true; |
104 | 4.09k | } |
105 | 4.28k | } |
106 | | |
107 | 189 | return false; |
108 | 4.28k | } |
109 | | |
110 | | static void OutputSmtpLogDeInitCtxSub(OutputCtx *output_ctx) |
111 | 0 | { |
112 | 0 | SCLogDebug("cleaning up sub output_ctx %p", output_ctx); |
113 | 0 | OutputJsonEmailCtx *email_ctx = output_ctx->data; |
114 | 0 | if (email_ctx != NULL) { |
115 | 0 | SCFree(email_ctx); |
116 | 0 | } |
117 | 0 | SCFree(output_ctx); |
118 | 0 | } |
119 | | |
120 | | static OutputInitResult OutputSmtpLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) |
121 | 4 | { |
122 | 4 | OutputInitResult result = { NULL, false }; |
123 | 4 | OutputJsonCtx *ojc = parent_ctx->data; |
124 | | |
125 | 4 | OutputJsonEmailCtx *email_ctx = SCCalloc(1, sizeof(OutputJsonEmailCtx)); |
126 | 4 | if (unlikely(email_ctx == NULL)) |
127 | 0 | return result; |
128 | | |
129 | 4 | OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); |
130 | 4 | if (unlikely(output_ctx == NULL)) { |
131 | 0 | SCFree(email_ctx); |
132 | 0 | return result; |
133 | 0 | } |
134 | | |
135 | 4 | email_ctx->eve_ctx = ojc; |
136 | | |
137 | 4 | OutputEmailInitConf(conf, email_ctx); |
138 | | |
139 | 4 | output_ctx->data = email_ctx; |
140 | 4 | output_ctx->DeInit = OutputSmtpLogDeInitCtxSub; |
141 | | |
142 | | /* enable the logger for the app layer */ |
143 | 4 | AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_SMTP); |
144 | | |
145 | 4 | result.ctx = output_ctx; |
146 | 4 | result.ok = true; |
147 | 4 | return result; |
148 | 4 | } |
149 | | |
150 | | static TmEcode JsonSmtpLogThreadInit(ThreadVars *t, const void *initdata, void **data) |
151 | 4 | { |
152 | 4 | JsonEmailLogThread *aft = SCCalloc(1, sizeof(JsonEmailLogThread)); |
153 | 4 | if (unlikely(aft == NULL)) |
154 | 0 | return TM_ECODE_FAILED; |
155 | | |
156 | 4 | if(initdata == NULL) { |
157 | 0 | SCLogDebug("Error getting context for EveLogSMTP. \"initdata\" argument NULL"); |
158 | 0 | goto error_exit; |
159 | 0 | } |
160 | | |
161 | | /* Use the Output Context (file pointer and mutex) */ |
162 | 4 | aft->emaillog_ctx = ((OutputCtx *)initdata)->data; |
163 | | |
164 | 4 | aft->ctx = CreateEveThreadCtx(t, aft->emaillog_ctx->eve_ctx); |
165 | 4 | if (aft->ctx == NULL) { |
166 | 0 | goto error_exit; |
167 | 0 | } |
168 | | |
169 | 4 | *data = (void *)aft; |
170 | 4 | return TM_ECODE_OK; |
171 | | |
172 | 0 | error_exit: |
173 | 0 | SCFree(aft); |
174 | 0 | return TM_ECODE_FAILED; |
175 | 4 | } |
176 | | |
177 | | static TmEcode JsonSmtpLogThreadDeinit(ThreadVars *t, void *data) |
178 | 0 | { |
179 | 0 | JsonEmailLogThread *aft = (JsonEmailLogThread *)data; |
180 | 0 | if (aft == NULL) { |
181 | 0 | return TM_ECODE_OK; |
182 | 0 | } |
183 | 0 | FreeEveThreadCtx(aft->ctx); |
184 | | |
185 | | /* clear memory */ |
186 | 0 | memset(aft, 0, sizeof(JsonEmailLogThread)); |
187 | |
|
188 | 0 | SCFree(aft); |
189 | 0 | return TM_ECODE_OK; |
190 | 0 | } |
191 | | |
192 | 71 | void JsonSmtpLogRegister (void) { |
193 | | /* register as child of eve-log */ |
194 | 71 | OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonSmtpLog", "eve-log.smtp", |
195 | 71 | OutputSmtpLogInitSub, ALPROTO_SMTP, JsonSmtpLogger, JsonSmtpLogThreadInit, |
196 | | JsonSmtpLogThreadDeinit, NULL); |
197 | 71 | } |