1 /* Copyright (C) 2013-2020 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 Victor Julien <victor@inliniac.net>
22 *
23 * Logs vars in JSON format.
24 *
25 */
26
27 #include "suricata-common.h"
28 #include "debug.h"
29 #include "detect.h"
30 #include "flow.h"
31 #include "conf.h"
32
33 #include "threads.h"
34 #include "tm-threads.h"
35 #include "threadvars.h"
36 #include "util-debug.h"
37
38 #include "util-misc.h"
39 #include "util-unittest.h"
40 #include "util-unittest-helper.h"
41
42 #include "detect-parse.h"
43 #include "detect-engine.h"
44 #include "detect-engine-mpm.h"
45 #include "detect-reference.h"
46 #include "app-layer-parser.h"
47 #include "app-layer-dnp3.h"
48 #include "app-layer-htp.h"
49 #include "app-layer-htp-xff.h"
50 #include "util-classification-config.h"
51 #include "util-syslog.h"
52 #include "util-logopenfile.h"
53
54 #include "output.h"
55 #include "output-json.h"
56 #include "output-json-metadata.h"
57
58 #include "util-byte.h"
59 #include "util-privs.h"
60 #include "util-print.h"
61 #include "util-proto-name.h"
62 #include "util-optimize.h"
63 #include "util-buffer.h"
64 #include "util-crypt.h"
65
66 #define MODULE_NAME "JsonMetadataLog"
67
68 typedef struct MetadataJsonOutputCtx_ {
69 LogFileCtx* file_ctx;
70 OutputJsonCommonSettings cfg;
71 } MetadataJsonOutputCtx;
72
73 typedef struct JsonMetadataLogThread_ {
74 /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
75 LogFileCtx* file_ctx;
76 MemBuffer *json_buffer;
77 MetadataJsonOutputCtx* json_output_ctx;
78 } JsonMetadataLogThread;
79
MetadataJson(ThreadVars * tv,JsonMetadataLogThread * aft,const Packet * p)80 static int MetadataJson(ThreadVars *tv, JsonMetadataLogThread *aft, const Packet *p)
81 {
82 JsonBuilder *js = CreateEveHeader(p, LOG_DIR_PACKET, "metadata", NULL);
83 if (unlikely(js == NULL))
84 return TM_ECODE_OK;
85
86 EveAddCommonOptions(&aft->json_output_ctx->cfg, p, p->flow, js);
87 OutputJsonBuilderBuffer(js, aft->file_ctx, &aft->json_buffer);
88
89 jb_free(js);
90 return TM_ECODE_OK;
91 }
92
JsonMetadataLogger(ThreadVars * tv,void * thread_data,const Packet * p)93 static int JsonMetadataLogger(ThreadVars *tv, void *thread_data, const Packet *p)
94 {
95 JsonMetadataLogThread *aft = thread_data;
96
97 return MetadataJson(tv, aft, p);
98 }
99
JsonMetadataLogCondition(ThreadVars * tv,const Packet * p)100 static int JsonMetadataLogCondition(ThreadVars *tv, const Packet *p)
101 {
102 if (p->pktvar) {
103 return TRUE;
104 }
105 return FALSE;
106 }
107
JsonMetadataLogThreadInit(ThreadVars * t,const void * initdata,void ** data)108 static TmEcode JsonMetadataLogThreadInit(ThreadVars *t, const void *initdata, void **data)
109 {
110 JsonMetadataLogThread *aft = SCCalloc(1, sizeof(JsonMetadataLogThread));
111 if (unlikely(aft == NULL))
112 return TM_ECODE_FAILED;
113
114 if(initdata == NULL) {
115 SCLogDebug("Error getting context for EveLogMetadata. \"initdata\" argument NULL");
116 goto error_exit;
117 }
118
119 aft->json_buffer = MemBufferCreateNew(JSON_OUTPUT_BUFFER_SIZE);
120 if (aft->json_buffer == NULL) {
121 goto error_exit;
122 }
123
124 /** Use the Output Context (file pointer and mutex) */
125 MetadataJsonOutputCtx *json_output_ctx = ((OutputCtx *)initdata)->data;
126 aft->file_ctx = LogFileEnsureExists(json_output_ctx->file_ctx, t->id);
127 if (!aft->file_ctx) {
128 goto error_exit;
129 }
130 aft->json_output_ctx = json_output_ctx;
131
132 *data = (void *)aft;
133 return TM_ECODE_OK;
134
135 error_exit:
136 if (aft->json_buffer != NULL) {
137 MemBufferFree(aft->json_buffer);
138 }
139 SCFree(aft);
140 return TM_ECODE_FAILED;
141 }
142
JsonMetadataLogThreadDeinit(ThreadVars * t,void * data)143 static TmEcode JsonMetadataLogThreadDeinit(ThreadVars *t, void *data)
144 {
145 JsonMetadataLogThread *aft = (JsonMetadataLogThread *)data;
146 if (aft == NULL) {
147 return TM_ECODE_OK;
148 }
149
150 MemBufferFree(aft->json_buffer);
151
152 /* clear memory */
153 memset(aft, 0, sizeof(JsonMetadataLogThread));
154
155 SCFree(aft);
156 return TM_ECODE_OK;
157 }
158
JsonMetadataLogDeInitCtxSub(OutputCtx * output_ctx)159 static void JsonMetadataLogDeInitCtxSub(OutputCtx *output_ctx)
160 {
161 SCLogDebug("cleaning up sub output_ctx %p", output_ctx);
162
163 MetadataJsonOutputCtx *json_output_ctx = (MetadataJsonOutputCtx *) output_ctx->data;
164
165 if (json_output_ctx != NULL) {
166 SCFree(json_output_ctx);
167 }
168 SCFree(output_ctx);
169 }
170
171 /**
172 * \brief Create a new LogFileCtx for "fast" output style.
173 * \param conf The configuration node for this output.
174 * \return A LogFileCtx pointer on success, NULL on failure.
175 */
JsonMetadataLogInitCtxSub(ConfNode * conf,OutputCtx * parent_ctx)176 static OutputInitResult JsonMetadataLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx)
177 {
178 OutputInitResult result = { NULL, false };
179 OutputJsonCtx *ajt = parent_ctx->data;
180 MetadataJsonOutputCtx *json_output_ctx = NULL;
181
182 OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
183 if (unlikely(output_ctx == NULL))
184 return result;
185
186 json_output_ctx = SCMalloc(sizeof(MetadataJsonOutputCtx));
187 if (unlikely(json_output_ctx == NULL)) {
188 goto error;
189 }
190 memset(json_output_ctx, 0, sizeof(MetadataJsonOutputCtx));
191
192 json_output_ctx->file_ctx = ajt->file_ctx;
193 json_output_ctx->cfg = ajt->cfg;
194 /* override config setting as this logger is about metadata */
195 json_output_ctx->cfg.include_metadata = true;
196
197 output_ctx->data = json_output_ctx;
198 output_ctx->DeInit = JsonMetadataLogDeInitCtxSub;
199
200 result.ctx = output_ctx;
201 result.ok = true;
202 return result;
203
204 error:
205 if (json_output_ctx != NULL) {
206 SCFree(json_output_ctx);
207 }
208 if (output_ctx != NULL) {
209 SCFree(output_ctx);
210 }
211
212 return result;
213 }
214
JsonMetadataLogRegister(void)215 void JsonMetadataLogRegister (void)
216 {
217 OutputRegisterPacketSubModule(LOGGER_JSON_METADATA, "eve-log", MODULE_NAME,
218 "eve-log.metadata", JsonMetadataLogInitCtxSub, JsonMetadataLogger,
219 JsonMetadataLogCondition, JsonMetadataLogThreadInit,
220 JsonMetadataLogThreadDeinit, NULL);
221
222 /* Kept for compatibility. */
223 OutputRegisterPacketSubModule(LOGGER_JSON_METADATA, "eve-log", MODULE_NAME,
224 "eve-log.vars", JsonMetadataLogInitCtxSub, JsonMetadataLogger,
225 JsonMetadataLogCondition, JsonMetadataLogThreadInit,
226 JsonMetadataLogThreadDeinit, NULL);
227 }
228