filestore v2: use fileinfo records as metadata

As fileinfo records are logged to the main eve log, disable
metadata by default. But when enabled, just use the fileinfo
record.

Metadata is stored in a file named:
  <sha256>.<seconds>.<file_id>.json

where the sha256 is the same as the file logged, the seconds
is the unix timestamp in seconds for the fileinfo record,
and the file_id is an atomically incremented integer per
Suricata instance.

This should allow for each occurrence of the same file to have
its own metadata file. But a collision is expected when running
Suricata repeatedly over the same pcap, as that would be the
exact same occurrence of a file.
pull/3175/head
Jason Ish 8 years ago
parent f631e8cd90
commit f7c3f30186

@ -15,6 +15,8 @@
* 02110-1301, USA.
*/
#include <utime.h>
#include "suricata-common.h"
#include "app-layer-parser.h"
@ -23,6 +25,7 @@
#include "output.h"
#include "output-filestore.h"
#include "output-json-file.h"
#include "util-print.h"
#include "util-misc.h"
@ -31,21 +34,23 @@
#define MODULE_NAME "OutputFilestore"
/* Create a filestore specific PATH_MAX that is less than the system
* PATH_MAX to prevent newer gcc truncation warnings with snprint. */
#define SHA256_STRING_LEN (SHA256_LENGTH * 2)
#define LEAF_DIR_MAX_LEN 4
#define FILESTORE_PREFIX_MAX (PATH_MAX - SHA256_STRING_LEN - LEAF_DIR_MAX_LEN)
/* The default log directory, relative to the default log
* directory. */
static const char *default_log_dir = "filestore";
SC_ATOMIC_DECLARE(uint32_t, filestore_open_file_cnt); /**< Atomic
* counter of
* simultaneously
* open
* files */
/* Atomic counter of simultaneously open files. */
static SC_ATOMIC_DECLARE(uint32_t, filestore_open_file_cnt);
typedef struct OutputFilestoreCtx_ {
char prefix[FILESTORE_PREFIX_MAX];
char tmpdir[FILESTORE_PREFIX_MAX];
bool fileinfo;
} OutputFilestoreCtx;
typedef struct OutputFilestoreLogThread_ {
@ -56,106 +61,7 @@ typedef struct OutputFilestoreLogThread_ {
static uint64_t OutputFilestoreOpenFilesCounter(void)
{
uint64_t fcopy = SC_ATOMIC_GET(filestore_open_file_cnt);
return fcopy;
}
static void OutputFilestoreMetaGetUri(FILE *fp, const Packet *p, const File *ff)
{
HtpState *htp_state = (HtpState *)p->flow->alstate;
if (htp_state != NULL) {
htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
if (tx != NULL) {
HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
if (tx_ud->request_uri_normalized != NULL) {
PrintRawUriFp(fp, bstr_ptr(tx_ud->request_uri_normalized),
bstr_len(tx_ud->request_uri_normalized));
}
return;
}
}
fprintf(fp, "<unknown>");
}
static void OutputFilestoreMetaGetHost(FILE *fp, const Packet *p, const File *ff)
{
HtpState *htp_state = (HtpState *)p->flow->alstate;
if (htp_state != NULL) {
htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
if (tx != NULL && tx->request_hostname != NULL) {
PrintRawUriFp(fp, (uint8_t *)bstr_ptr(tx->request_hostname),
bstr_len(tx->request_hostname));
return;
}
}
fprintf(fp, "<unknown>");
}
static void OutputFilestoreMetaGetReferer(FILE *fp, const Packet *p, const File *ff)
{
HtpState *htp_state = (HtpState *)p->flow->alstate;
if (htp_state != NULL) {
htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
if (tx != NULL) {
htp_header_t *h = NULL;
h = (htp_header_t *)htp_table_get_c(tx->request_headers,
"Referer");
if (h != NULL) {
PrintRawUriFp(fp, (uint8_t *)bstr_ptr(h->value),
bstr_len(h->value));
return;
}
}
}
fprintf(fp, "<unknown>");
}
static void OutputFilestoreMetaGetUserAgent(FILE *fp, const Packet *p, const File *ff)
{
HtpState *htp_state = (HtpState *)p->flow->alstate;
if (htp_state != NULL) {
htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
if (tx != NULL) {
htp_header_t *h = NULL;
h = (htp_header_t *)htp_table_get_c(tx->request_headers,
"User-Agent");
if (h != NULL) {
PrintRawUriFp(fp, (uint8_t *)bstr_ptr(h->value),
bstr_len(h->value));
return;
}
}
}
fprintf(fp, "<unknown>");
}
static void OutputFilestoreMetaGetSmtp(FILE *fp, const Packet *p, const File *ff)
{
SMTPState *state = (SMTPState *) p->flow->alstate;
if (state != NULL) {
SMTPTransaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_SMTP, state, ff->txid);
if (tx == NULL || tx->msg_tail == NULL)
return;
/* Message Id */
if (tx->msg_tail->msg_id != NULL) {
fprintf(fp, "MESSAGE-ID: ");
PrintRawUriFp(fp, (uint8_t *) tx->msg_tail->msg_id, tx->msg_tail->msg_id_len);
fprintf(fp, "\n");
}
/* Sender */
MimeDecField *field = MimeDecFindField(tx->msg_tail, "from");
if (field != NULL) {
fprintf(fp, "SENDER: ");
PrintRawUriFp(fp, (uint8_t *) field->value, field->value_len);
fprintf(fp, "\n");
}
}
return SC_ATOMIC_GET(filestore_open_file_cnt);
}
static uint32_t g_file_store_max_open_files = 0;
@ -170,136 +76,6 @@ static uint32_t FileGetMaxOpenFiles(void)
return g_file_store_max_open_files;
}
static void OutputFilestoreLogCreateMetaFile(const Packet *p, const File *ff,
char *base_filename, int ipver) {
char metafilename[PATH_MAX] = "";
snprintf(metafilename, sizeof(metafilename), "%s.meta", base_filename);
SCLogNotice("Opening %s.", metafilename);
FILE *fp = fopen(metafilename, "w+");
if (fp != NULL) {
char timebuf[64];
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
fprintf(fp, "TIME: %s\n", timebuf);
if (p->pcap_cnt > 0) {
fprintf(fp, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt);
}
char srcip[46], dstip[46];
Port sp, dp;
switch (ipver) {
case AF_INET:
PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
break;
case AF_INET6:
PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
break;
default:
strlcpy(srcip, "<unknown>", sizeof(srcip));
strlcpy(dstip, "<unknown>", sizeof(dstip));
break;
}
sp = p->sp;
dp = p->dp;
fprintf(fp, "SRC IP: %s\n", srcip);
fprintf(fp, "DST IP: %s\n", dstip);
fprintf(fp, "PROTO: %" PRIu32 "\n", p->proto);
if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) {
fprintf(fp, "SRC PORT: %" PRIu16 "\n", sp);
fprintf(fp, "DST PORT: %" PRIu16 "\n", dp);
}
fprintf(fp, "APP PROTO: %s\n",
AppProtoToString(p->flow->alproto));
/* Only applicable to HTTP traffic */
if (p->flow->alproto == ALPROTO_HTTP) {
fprintf(fp, "HTTP URI: ");
OutputFilestoreMetaGetUri(fp, p, ff);
fprintf(fp, "\n");
fprintf(fp, "HTTP HOST: ");
OutputFilestoreMetaGetHost(fp, p, ff);
fprintf(fp, "\n");
fprintf(fp, "HTTP REFERER: ");
OutputFilestoreMetaGetReferer(fp, p, ff);
fprintf(fp, "\n");
fprintf(fp, "HTTP USER AGENT: ");
OutputFilestoreMetaGetUserAgent(fp, p, ff);
fprintf(fp, "\n");
} else if (p->flow->alproto == ALPROTO_SMTP) {
/* Only applicable to SMTP */
OutputFilestoreMetaGetSmtp(fp, p, ff);
}
fprintf(fp, "FILENAME: ");
PrintRawUriFp(fp, ff->name, ff->name_len);
fprintf(fp, "\n");
fclose(fp);
}
}
static void OutputFilestoreLogCloseMetaFile(const OutputFilestoreCtx *ctx,
const File *ff, const char *filename)
{
FILE *fp = fopen(filename, "a");
if (fp == NULL) {
SCLogInfo("Failed to open %s: %s", filename, strerror(errno));
return;
}
#ifdef HAVE_MAGIC
fprintf(fp, "MAGIC: %s\n",
ff->magic ? ff->magic : "<unknown>");
#endif
switch (ff->state) {
case FILE_STATE_CLOSED:
fprintf(fp, "STATE: CLOSED\n");
#ifdef HAVE_NSS
if (ff->flags & FILE_MD5) {
fprintf(fp, "MD5: ");
size_t x;
for (x = 0; x < sizeof(ff->md5); x++) {
fprintf(fp, "%02x", ff->md5[x]);
}
fprintf(fp, "\n");
}
if (ff->flags & FILE_SHA1) {
fprintf(fp, "SHA1: ");
size_t x;
for (x = 0; x < sizeof(ff->sha1); x++) {
fprintf(fp, "%02x", ff->sha1[x]);
}
fprintf(fp, "\n");
}
if (ff->flags & FILE_SHA256) {
fprintf(fp, "SHA256: ");
size_t x;
for (x = 0; x < sizeof(ff->sha256); x++) {
fprintf(fp, "%02x", ff->sha256[x]);
}
fprintf(fp, "\n");
}
#endif
break;
case FILE_STATE_TRUNCATED:
fprintf(fp, "STATE: TRUNCATED\n");
break;
case FILE_STATE_ERROR:
fprintf(fp, "STATE: ERROR\n");
break;
default:
fprintf(fp, "STATE: UNKNOWN\n");
break;
}
fprintf(fp, "SIZE: %"PRIu64"\n", FileTrackedSize(ff));
fclose(fp);
}
static void PrintHexString(char *str, size_t size, uint8_t *buf, size_t buf_len)
{
int i = 0;
@ -309,39 +85,80 @@ static void PrintHexString(char *str, size_t size, uint8_t *buf, size_t buf_len)
}
}
/**
* \brief Update the timestamps on a file to match those of another
* file.
*
* \param src_filename Filename to use as timestamp source.
* \param filename Filename to apply timestamps to.
*/
static void OutputFilestoreUpdateFileTime(const char *src_filename,
const char *filename)
{
struct stat sb;
if (stat(src_filename, &sb) != 0) {
SCLogDebug("Failed to stat %s: %s", filename, strerror(errno));
return;
}
struct utimbuf utimbuf = {
.actime = sb.st_atime,
.modtime = sb.st_mtime,
};
if (utime(filename, &utimbuf) != 0) {
SCLogDebug("Failed to update file timestamps: %s: %s", filename,
strerror(errno));
}
}
static void OutputFilestoreFinalizeFiles(const OutputFilestoreCtx *ctx,
File *ff) {
char final_filename[PATH_MAX] = "";
snprintf(final_filename, sizeof(final_filename), "%s/file.%u",
ctx->tmpdir, ff->file_store_id);
char working_filename[PATH_MAX] = "";
snprintf(working_filename, sizeof(working_filename), "%s",
final_filename);
const Packet *p, File *ff) {
/* Stringify the SHA256 which will be used in the final
* filename. */
char sha256string[(SHA256_LENGTH * 2) + 1];
PrintHexString(sha256string, sizeof(sha256string), ff->sha256,
sizeof(ff->sha256));
char tmp_filename[PATH_MAX] = "";
snprintf(tmp_filename, sizeof(tmp_filename), "%s/file.%u", ctx->tmpdir,
ff->file_store_id);
char final_filename[PATH_MAX] = "";
snprintf(final_filename, sizeof(final_filename), "%s/%c%c/%s",
ctx->prefix, sha256string[0], sha256string[1], sha256string);
if (rename(working_filename, final_filename) != 0) {
SCLogWarning(SC_WARN_RENAMING_FILE, "renaming file %s to %s failed",
working_filename, final_filename);
if (SCPathExists(final_filename)) {
OutputFilestoreUpdateFileTime(tmp_filename, final_filename);
if (unlink(tmp_filename) != 0) {
SCLogWarning(SC_WARN_REMOVE_FILE,
"Failed to remove temporary file %s: %s", tmp_filename,
strerror(errno));
}
} else if (rename(tmp_filename, final_filename) != 0) {
SCLogWarning(SC_WARN_RENAMING_FILE, "Failed to rename %s to %s: %s",
tmp_filename, final_filename, strerror(errno));
if (unlink(tmp_filename) != 0) {
SCLogWarning(SC_WARN_REMOVE_FILE,
"Failed to remove temporary file %s: %s", tmp_filename,
strerror(errno));
}
return;
}
/* Write metadata. */
char final_metafilename[PATH_MAX] = "";
snprintf(final_metafilename, sizeof(final_metafilename),
"%s.meta", final_filename);
char working_metafilename[PATH_MAX] = "";
snprintf(working_metafilename, sizeof(working_metafilename),
"%s.meta", working_filename);
OutputFilestoreLogCloseMetaFile(ctx, ff, working_metafilename);
if (rename(working_metafilename, final_metafilename) != 0) {
SCLogWarning(SC_WARN_RENAMING_FILE,
"renaming metafile %s to %s failed", working_metafilename,
final_metafilename);
#ifdef HAVE_LIBJANSSON
if (ctx->fileinfo) {
char js_metadata_filename[PATH_MAX];
snprintf(js_metadata_filename, sizeof(js_metadata_filename),
"%s.%"PRIuMAX".%d.json", final_filename, p->ts.tv_sec,
ff->file_store_id);
json_t *js_fileinfo = JsonBuildFileInfoRecord(p, ff, true);
if (likely(js_fileinfo != NULL)) {
json_dump_file(js_fileinfo, js_metadata_filename, 0);
json_decref(js_fileinfo);
}
}
#endif
}
static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
const Packet *p, File *ff, const uint8_t *data, uint32_t data_len,
@ -352,18 +169,13 @@ static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
OutputFilestoreCtx *ctx = aft->ctx;
char filename[PATH_MAX] = "";
int file_fd = -1;
int ipver = -1;
/* no flow, no htp state */
/* no flow, no files */
if (p->flow == NULL) {
SCReturnInt(TM_ECODE_OK);
}
if (PKT_IS_IPV4(p)) {
ipver = AF_INET;
} else if (PKT_IS_IPV6(p)) {
ipver = AF_INET6;
} else {
if (!(PKT_IS_IPV4(p) || PKT_IS_IPV6(p))) {
return 0;
}
@ -377,12 +189,8 @@ static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
if (flags & OUTPUT_FILEDATA_FLAG_OPEN) {
aft->file_cnt++;
/* create a .meta file that contains time, src/dst/sp/dp/proto */
OutputFilestoreLogCreateMetaFile(p, ff, base_filename, ipver);
if (SC_ATOMIC_GET(filestore_open_file_cnt) < FileGetMaxOpenFiles()) {
SC_ATOMIC_ADD(filestore_open_file_cnt, 1);
SCLogNotice("Opening %s.", filename);
ff->fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
if (ff->fd == -1) {
SCLogNotice("failed to create file");
@ -390,7 +198,6 @@ static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
}
file_fd = ff->fd;
} else {
SCLogNotice("Opening %s.", filename);
file_fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
if (file_fd == -1) {
SCLogNotice("failed to create file");
@ -403,7 +210,6 @@ static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
/* we can get called with a NULL ffd when we need to close */
} else if (data != NULL) {
if (ff->fd == -1) {
SCLogNotice("Opening %s.", filename);
file_fd = open(filename, O_APPEND | O_NOFOLLOW | O_WRONLY);
if (file_fd == -1) {
SCLogNotice("failed to open file %s: %s", filename, strerror(errno));
@ -434,7 +240,7 @@ static int OutputFilestoreLogger(ThreadVars *tv, void *thread_data,
ff->fd = -1;
SC_ATOMIC_SUB(filestore_open_file_cnt, 1);
}
OutputFilestoreFinalizeFiles(ctx, ff);
OutputFilestoreFinalizeFiles(ctx, p, ff);
}
return 0;
@ -448,8 +254,7 @@ static TmEcode OutputFilestoreLogThreadInit(ThreadVars *t, const void *initdata,
return TM_ECODE_FAILED;
memset(aft, 0, sizeof(OutputFilestoreLogThread));
if (initdata == NULL)
{
if (initdata == NULL) {
SCLogDebug("Error getting context for LogFileStore. \"initdata\" argument NULL");
SCFree(aft);
return TM_ECODE_FAILED;
@ -500,7 +305,7 @@ static void GetLogDirectory(const ConfNode *conf, char *out, size_t out_size)
{
const char *log_base_dir = ConfNodeLookupChildValue(conf, "dir");
if (log_base_dir == NULL) {
SCLogNotice("Using default log directory %s", default_log_dir);
SCLogConfig("Filestore (v2) default log directory %s", default_log_dir);
log_base_dir = default_log_dir;
}
if (PathIsAbsolute(log_base_dir)) {
@ -516,10 +321,11 @@ static bool InitFilestoreDirectory(const char *dir)
const uint8_t dir_count = 0xff;
if (!SCPathExists(dir)) {
SCLogNotice("Creating directory %s", dir);
SCLogInfo("Filestore (v2) creating directory %s", dir);
if (SCCreateDirectoryTree(dir, true) != 0) {
SCLogError(SC_ERR_CREATE_DIRECTORY,
"Failed to create directory %s: %s", dir, strerror(errno));
"Filestore (v2) failed to create directory %s: %s", dir,
strerror(errno));
return false;
}
}
@ -528,11 +334,11 @@ static bool InitFilestoreDirectory(const char *dir)
char leaf[PATH_MAX];
snprintf(leaf, sizeof(leaf) - 1, "%s/%02x", dir, i);
if (!SCPathExists(leaf)) {
SCLogNotice("Creating directory %s", leaf);
SCLogInfo("Filestore (v2) creating directory %s", leaf);
if (SCDefaultMkDir(leaf) != 0) {
SCLogError(SC_ERR_CREATE_DIRECTORY,
"Failed to create directory %s: %s", leaf,
strerror(errno));
"Filestore (v2) failed to create directory %s: %s",
leaf, strerror(errno));
return false;
}
}
@ -542,10 +348,10 @@ static bool InitFilestoreDirectory(const char *dir)
char tmpdir[PATH_MAX];
snprintf(tmpdir, sizeof(tmpdir) - 1, "%s/tmp", dir);
if (!SCPathExists(tmpdir)) {
SCLogNotice("Creating directory %s", tmpdir);
SCLogInfo("Filestore (v2) creating directory %s", tmpdir);
if (SCDefaultMkDir(tmpdir) != 0) {
SCLogError(SC_ERR_CREATE_DIRECTORY,
"Failed to create directory %s: %s", tmpdir,
"Filestore (v2) failed to create directory %s: %s", tmpdir,
strerror(errno));
return false;
}
@ -558,36 +364,50 @@ static bool InitFilestoreDirectory(const char *dir)
* \param conf Pointer to ConfNode containing this loggers configuration.
* \return NULL if failure, OutputFilestoreCtx* to the file_ctx if succesful
* */
static OutputCtx *OutputFilestoreLogInitCtx(ConfNode *conf)
static OutputInitResult OutputFilestoreLogInitCtx(ConfNode *conf)
{
OutputInitResult result = { NULL, false };
intmax_t version = 0;
if (!ConfGetChildValueInt(conf, "version", &version)) {
return NULL;
}
if (version < 2) {
return NULL;
if (!ConfGetChildValueInt(conf, "version", &version) || version < 2) {
result.ok = true;
return result;
}
char log_directory[PATH_MAX] = "";
GetLogDirectory(conf, log_directory, sizeof(log_directory));
if (!InitFilestoreDirectory(log_directory)) {
return NULL;
return result;
}
OutputFilestoreCtx *ctx = SCCalloc(1, sizeof(*ctx));
if (unlikely(ctx == NULL)) {
return NULL;
return result;
}
strlcpy(ctx->prefix, log_directory, sizeof(ctx->prefix));
snprintf(ctx->tmpdir, sizeof(ctx->tmpdir) - 1, "%s/tmp", log_directory);
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
if (unlikely(output_ctx == NULL))
return NULL;
if (unlikely(output_ctx == NULL)) {
SCFree(ctx);
return result;
}
output_ctx->data = ctx;
output_ctx->DeInit = OutputFilestoreLogDeInitCtx;
const char *write_fileinfo = ConfNodeLookupChildValue(conf,
"write-fileinfo");
if (write_fileinfo != NULL && ConfValIsTrue(write_fileinfo)) {
#ifdef HAVE_LIBJANSSON
SCLogConfig("Filestore (v2) will output fileinfo records.");
ctx->fileinfo = true;
#else
SCLogWarning(SC_ERR_NO_JSON_SUPPORT,
"Filestore (v2) requires JSON support to log fileinfo records");
#endif
}
const char *force_filestore = ConfNodeLookupChildValue(conf,
"force-filestore");
if (force_filestore != NULL && ConfValIsTrue(force_filestore)) {
@ -598,7 +418,7 @@ static OutputCtx *OutputFilestoreLogInitCtx(ConfNode *conf)
const char *force_magic = ConfNodeLookupChildValue(conf, "force-magic");
if (force_magic != NULL && ConfValIsTrue(force_magic)) {
FileForceMagicEnable();
SCLogInfo("forcing magic lookup for stored files");
SCLogConfig("Filestore (v2) forcing magic lookup for stored files");
}
FileForceHashParseCfg(conf);
@ -606,8 +426,6 @@ static OutputCtx *OutputFilestoreLogInitCtx(ConfNode *conf)
/* The new filestore requires SHA256. */
FileForceSha256Enable();
SCLogInfo("storing files in %s", ctx->prefix);
const char *stream_depth_str = ConfNodeLookupChildValue(conf,
"stream-depth");
if (stream_depth_str != NULL && strcmp(stream_depth_str, "no")) {
@ -638,25 +456,22 @@ static OutputCtx *OutputFilestoreLogInitCtx(ConfNode *conf)
} else {
if (file_count != 0) {
FileSetMaxOpenFiles(file_count);
SCLogInfo("file-store will keep a max of %d simultaneously"
" open files", file_count);
}
SCLogConfig("Filestore (v2) will keep a max of %d "
"simultaneously open files", file_count);
}
}
SCReturnPtr(output_ctx, "OutputCtx");
}
#endif /* HAVE_NSS */
void OutputFilestoreInitConfig(void)
{
#ifdef HAVE_NSS
StatsRegisterGlobalCounter("file_store.open_files",
OutputFilestoreOpenFilesCounter);
#endif /* HAVE_NSS */
result.ctx = output_ctx;
result.ok = true;
SCReturnCT(result, "OutputInitResult");
}
#endif /* HAVE_NSS */
void OutputFilestoreRegister(void)
{
#ifdef HAVE_NSS

@ -200,6 +200,10 @@
#include <pcap/bpf.h>
#endif
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#if __CYGWIN__
#if !defined _X86_ && !defined __x86_64
#define _X86_

@ -421,7 +421,54 @@ outputs:
append: yes
#filetype: regular # 'regular', 'unix_stream' or 'unix_dgram'
# output module to store extracted files to disk
# Output module for storing files on disk. Files are stored in a
# directory names consisting of the first 2 characaters of the
# SHA256 of the file. Each file is given its SHA256 as a filename.
#
# When a duplicate file is found, the existing file is touched to
# have its timestamps updated.
#
# Unlike the older filestore, metadata is not written out by default
# as each file should already have a "fileinfo" record in the
# eve.log. If write-fileinfo is set to yes, the each file will have
# one more associated .json files that consists of the fileinfo
# record. A fileinfo file will be written for each occurrence of the
# file seen using a filename suffix to ensure uniqueness.
#
# To prune the filestore directory see the "suricatactl filestore
# prune" command which can delete files over a certain age.
- file-store:
version: 2
enabled: no
# Set the directory for the filestore. If the path is not
# absolute will be be relative to the default-log-dir.
#dir: filestore
# Write out a fileinfo record for each occurrence of a
# file. Disabled by default as each occurrence is already logged
# as a fileinfo record to the main eve-log.
#write-fileinfo: yes
# Force storing of all files. Default: no.
#force-filestore: yes
# Override the global stream-depth for sessions in which we want
# to perform file extraction. Set to 0 for unlimited.
#stream-depth: 0
# Uncomment the following variable to define how many files can
# remain open for filestore by Suricata. Default value is 0 which
# means files get closed after each write
#max-open-files: 1000
# Force logging of checksums, available hash functions are md5,
# sha1 and sha256. Note that SHA256 is automatically forced by
# the use of this output module as it uses the SHA256 as the
# file naming scheme.
#force-hash: [sha1, md5]
# output module to store extracted files to disk (old style, deprecated)
#
# The files are stored to the log-dir in a format "file.<id>" where <id> is
# an incrementing number starting at 1. For each file "file.<id>" a meta
@ -455,13 +502,6 @@ outputs:
#max-open-files: 1000
include-pid: no # set to yes to include pid in file names
- file-store:
version: 2
enabled: no
# Force storing of all files. Default: no.
#force-filestore: yes
# output module to log files tracked in a easily parsable json format
- file-log:
enabled: no

Loading…
Cancel
Save