suricata
output-file.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2024 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 * AppLayer File Logger Output registration functions
24 */
25
26#include "suricata-common.h"
27#include "output.h"
28#include "output-file.h"
29#if 0
30#include "app-layer.h"
31#endif
32#include "app-layer-parser.h" // FileApplyTxFlags
33#include "detect-filemagic.h"
34#include "util-file.h"
35#include "util-magic.h"
36#include "util-profiling.h"
37#include "util-validate.h"
38
40
41/* logger instance, a module + a output ctx,
42 * it's perfectly valid that have multiple instances of the same
43 * log module (e.g. http.log) with different output ctx'. */
53
54static OutputFileLogger *list = NULL;
55
58{
59 OutputFileLogger *op = SCCalloc(1, sizeof(*op));
60 if (op == NULL)
61 return -1;
62
63 op->LogFunc = LogFunc;
64 op->initdata = initdata;
65 op->name = name;
66 op->logger_id = id;
69
70 if (list == NULL)
71 list = op;
72 else {
73 OutputFileLogger *t = list;
74 while (t->next)
75 t = t->next;
76 t->next = op;
77 }
78
79 SCLogDebug("OutputRegisterFileLogger happy");
80
82 return 0;
83}
84
85static void CloseFile(const Packet *p, Flow *f, AppLayerTxData *txd, File *file)
86{
88 DEBUG_VALIDATE_BUG_ON(f->alproto == ALPROTO_SMB && txd->files_logged != 0);
89 DEBUG_VALIDATE_BUG_ON(f->alproto == ALPROTO_FTPDATA && txd->files_logged != 0);
90 txd->files_logged++;
91 DEBUG_VALIDATE_BUG_ON(txd->files_logged > txd->files_opened);
92 file->flags |= FILE_LOGGED;
93 SCLogDebug("ff %p FILE_LOGGED", file);
94}
95
97 FileContainer *ffc, void *txv, const uint64_t tx_id, AppLayerTxData *txd,
98 const bool file_close, const bool file_trunc, uint8_t dir)
99{
100 if (ffc->head == NULL)
101 return;
102
103 SCLogDebug("ffc %p ffc->head %p file_close %d file_trunc %d dir %s", ffc,
104 ffc ? ffc->head : NULL, file_close, file_trunc, dir == STREAM_TOSERVER ? "ts" : "tc");
105 File *ff;
106 for (ff = ffc->head; ff != NULL; ff = ff->next) {
107 SCLogDebug("ff %p pre-FILE_LOGGED", ff);
108 if (ff->flags & FILE_LOGGED)
109 continue;
110
111 FileApplyTxFlags(txd, dir, ff);
112
113 SCLogDebug("ff %p state %u post-FILE_LOGGED", ff, ff->state);
114
115 if (file_trunc && ff->state < FILE_STATE_CLOSED) {
116 SCLogDebug("file_trunc %d ff->state %u => FILE_STATE_TRUNCATED", file_trunc, ff->state);
117 ff->state = FILE_STATE_TRUNCATED;
118 }
119
120 if (file_close && ff->state < FILE_STATE_CLOSED) {
121 SCLogDebug("file_close %d ff->state %u => FILE_STATE_TRUNCATED", file_close, ff->state);
122 ff->state = FILE_STATE_TRUNCATED;
123 }
124
125 SCLogDebug("ff %p state %u", ff, ff->state);
126
127 if (ff->state > FILE_STATE_OPENED) {
128 SCLogDebug("FILE LOGGING");
129 bool file_logged = false;
130#ifdef HAVE_MAGIC
131 if (FileForceMagic() && ff->magic == NULL) {
132 FilemagicThreadLookup(&op_thread_data->magic_ctx, ff);
133 }
134#endif
135 const OutputFileLogger *logger = list;
136 const OutputLoggerThreadStore *store = op_thread_data->store;
137 while (logger && store) {
138 DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL);
139
140 SCLogDebug("logger %p", logger);
142 logger->LogFunc(tv, store->thread_data, (const Packet *)p, (const File *)ff, txv,
143 tx_id, dir);
145 file_logged = true;
146
147 logger = logger->next;
148 store = store->next;
149
150 DEBUG_VALIDATE_BUG_ON(logger == NULL && store != NULL);
151 DEBUG_VALIDATE_BUG_ON(logger != NULL && store == NULL);
152 }
153
154 if (file_logged) {
155 CloseFile(p, p->flow, txd, ff);
156 }
157 }
158 }
159}
160
161/** \brief thread init for the file logger
162 * This will run the thread init functions for the individual registered
163 * loggers */
165{
166 OutputFileLoggerThreadData *td = SCCalloc(1, sizeof(*td));
167 if (td == NULL)
168 return TM_ECODE_FAILED;
169 *data = td;
170
171#ifdef HAVE_MAGIC
172 td->magic_ctx = MagicInitContext();
173 if (td->magic_ctx == NULL) {
174 SCFree(td);
175 return TM_ECODE_FAILED;
176 }
177#endif
178
179 SCLogDebug("OutputFileLogThreadInit happy (*data %p)", *data);
180
181 OutputFileLogger *logger = list;
182 while (logger) {
183 if (logger->ThreadInit) {
184 void *retptr = NULL;
185 if (logger->ThreadInit(tv, logger->initdata, &retptr) == TM_ECODE_OK) {
186 OutputLoggerThreadStore *ts = SCCalloc(1, sizeof(*ts));
187 /* todo */ BUG_ON(ts == NULL);
188
189 /* store thread handle */
190 ts->thread_data = retptr;
191
192 if (td->store == NULL) {
193 td->store = ts;
194 } else {
196 while (tmp->next != NULL)
197 tmp = tmp->next;
198 tmp->next = ts;
199 }
200
201 SCLogDebug("%s is now set up", logger->name);
202 }
203 }
204
205 logger = logger->next;
206 }
207
208 return TM_ECODE_OK;
209}
210
212{
213 OutputLoggerThreadStore *store = op_thread_data->store;
214 OutputFileLogger *logger = list;
215
216 while (logger && store) {
217 if (logger->ThreadDeinit) {
218 logger->ThreadDeinit(tv, store->thread_data);
219 }
220
221 OutputLoggerThreadStore *next_store = store->next;
222 SCFree(store);
223 store = next_store;
224 logger = logger->next;
225 }
226
227#ifdef HAVE_MAGIC
228 MagicDeinitContext(op_thread_data->magic_ctx);
229#endif
230
231 SCFree(op_thread_data);
232 return TM_ECODE_OK;
233}
234
236{
237}
238
240{
241 OutputFileLogger *logger = list;
242 while (logger) {
243 OutputFileLogger *next_logger = logger->next;
244 SCFree(logger);
245 logger = next_logger;
246 }
247
248 list = NULL;
249}
void FileApplyTxFlags(const AppLayerTxData *txd, const uint8_t direction, File *file)
Definition util-file.c:278
struct AppLayerTxData AppLayerTxData
@ ALPROTO_SMB
@ ALPROTO_FTPDATA
uint32_t id
ThreadVars * tv
TmEcode OutputFileLogThreadInit(ThreadVars *tv, OutputFileLoggerThreadData **data)
thread init for the file logger This will run the thread init functions for the individual registered...
void OutputFileLoggerRegister(void)
void OutputFileLogFfc(ThreadVars *tv, OutputFileLoggerThreadData *op_thread_data, Packet *p, FileContainer *ffc, void *txv, const uint64_t tx_id, AppLayerTxData *txd, const bool file_close, const bool file_trunc, uint8_t dir)
Definition output-file.c:96
TmEcode OutputFileLogThreadDeinit(ThreadVars *tv, OutputFileLoggerThreadData *op_thread_data)
void OutputFileShutdown(void)
int SCOutputRegisterFileLogger(LoggerId id, const char *name, SCFileLogger LogFunc, void *initdata, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Register a file logger.
Definition output-file.c:56
bool g_file_logger_enabled
Definition output-file.c:39
struct OutputFileLogger_ OutputFileLogger
int(* SCFileLogger)(ThreadVars *, void *thread_data, const Packet *, const File *, void *tx, const uint64_t tx_id, uint8_t direction)
Definition output-file.h:48
uint64_t ts
uint16_t flags
Definition util-file.h:80
Flow data structure.
Definition flow.h:356
AppProto alproto
application level protocol
Definition flow.h:450
OutputLoggerThreadStore * store
Definition output-file.h:34
SCFileLogger LogFunc
Definition output-file.c:45
struct OutputFileLogger_ * next
Definition output-file.c:47
ThreadInitFunc ThreadInit
Definition output-file.c:50
const char * name
Definition output-file.c:48
ThreadDeinitFunc ThreadDeinit
Definition output-file.c:51
struct OutputLoggerThreadStore_ * next
Definition output.h:35
struct Flow_ * flow
Definition decode.h:546
Per thread variable structure.
Definition threadvars.h:58
#define BUG_ON(x)
TmEcode(* ThreadDeinitFunc)(ThreadVars *, void *)
Definition tm-modules.h:44
TmEcode(* ThreadInitFunc)(ThreadVars *, const void *, void **)
Definition tm-modules.h:43
@ TM_ECODE_FAILED
@ TM_ECODE_OK
const char * name
#define SCLogDebug(...)
Definition util-debug.h:275
int FileForceMagic(void)
Definition util-file.c:141
#define FILE_LOGGED
Definition util-file.h:53
@ FILE_STATE_OPENED
Definition util-file.h:70
@ FILE_STATE_TRUNCATED
Definition util-file.h:73
@ FILE_STATE_CLOSED
Definition util-file.h:71
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define PACKET_PROFILING_LOGGER_END(p, id)
#define PACKET_PROFILING_LOGGER_START(p, id)
#define DEBUG_VALIDATE_BUG_ON(exp)