summaryrefslogtreecommitdiffstats
path: root/src/util-file.h
blob: 55d91192fe1225fb33e2774f1000cc2afd9e0115 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* Copyright (C) 2007-2021 Open Information Security Foundation
 *
 * You can copy, redistribute or modify this Program under the terms of
 * the GNU General Public License version 2 as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

/**
 * \file
 *
 * \author Victor Julien <victor@inliniac.net>
 *
 */

#ifndef __UTIL_FILE_H__
#define __UTIL_FILE_H__

#include "conf.h"
#include "util-streaming-buffer.h"
#include "flow.h"

/* Hack: Pulling rust.h to get the SCSha256 causes all sorts of problems with
 *   header include orders, which is something we'll have to resolve as we provide
 *   more functionality via Rust. But this lets me continue with replacing nss
 *   without fighting the headers at this time. */
typedef struct SCSha256 SCSha256;
#define SC_SHA256_LEN 32

typedef struct SCSha1 SCSha1;
#define SC_SHA1_LEN 20

typedef struct SCMd5 SCMd5;
#define SC_MD5_LEN 16

#define FILE_TRUNCATED  BIT_U16(0)
#define FILE_NOMAGIC    BIT_U16(1)
#define FILE_NOMD5      BIT_U16(2)
#define FILE_MD5        BIT_U16(3)
#define FILE_NOSHA1     BIT_U16(4)
#define FILE_SHA1       BIT_U16(5)
#define FILE_NOSHA256   BIT_U16(6)
#define FILE_SHA256     BIT_U16(7)
#define FILE_LOGGED     BIT_U16(8)
#define FILE_NOSTORE    BIT_U16(9)
#define FILE_STORE      BIT_U16(10)
#define FILE_STORED     BIT_U16(11)
#define FILE_NOTRACK    BIT_U16(12) /**< track size of file */
#define FILE_USE_DETECT BIT_U16(13) /**< use content_inspected tracker */
#define FILE_HAS_GAPS   BIT_U16(15)

// to be used instead of PATH_MAX which depends on the OS
#define SC_FILENAME_MAX 4096

#define FILEDATA_CONTENT_LIMIT            100000
#define FILEDATA_CONTENT_INSPECT_MIN_SIZE 32768
#define FILEDATA_CONTENT_INSPECT_WINDOW   4096

typedef enum FileState_ {
    FILE_STATE_NONE = 0,    /**< no state */
    FILE_STATE_OPENED,      /**< flow file is opened */
    FILE_STATE_CLOSED,      /**< flow file is completed,
                                     there will be no more data. */
    FILE_STATE_TRUNCATED,   /**< flow file is not complete, but
                                     there will be no more data. */
    FILE_STATE_ERROR,       /**< file is in an error state */
    FILE_STATE_MAX
} FileState;

typedef struct File_ {
    uint16_t flags;
    uint16_t name_len;
    FileState state;
    StreamingBuffer *sb;
    uint32_t file_track_id;         /**< id used by protocol parser */
    uint32_t file_store_id;         /**< id used in store file name file.<id> */
    int fd;                         /**< file descriptor for filestore, not
                                        open if equal to -1 */
    uint8_t *name;
#ifdef HAVE_MAGIC
    char *magic;
#endif
    struct File_ *next;
    SCMd5 *md5_ctx;
    uint8_t md5[SC_MD5_LEN];
    SCSha1 *sha1_ctx;
    uint8_t sha1[SC_SHA1_LEN];
    SCSha256 *sha256_ctx;
    uint8_t sha256[SC_SHA256_LEN];
    uint64_t content_inspected;     /**< used in pruning if FILE_USE_DETECT
                                     *   flag is set */
    uint64_t content_stored;
    uint64_t size;
    uint32_t inspect_window;
    uint32_t inspect_min_size;
    uint64_t start;
    uint64_t end;

    uint32_t *sid; /* signature id of a rule that triggered the filestore event */
    uint32_t sid_cnt;
    uint32_t sid_max;
} File;

typedef struct FileContainer_ {
    File *head;
    File *tail;
} FileContainer;

FileContainer *FileContainerAlloc(void);
void FileContainerFree(FileContainer *, const StreamingBufferConfig *cfg);

void FileContainerRecycle(FileContainer *, const StreamingBufferConfig *cfg);

void FileContainerAdd(FileContainer *, File *);

/**
 *  \brief Open a new File
 *
 *  \param ffc flow container
 *  \param sbcfg buffer config
 *  \param name filename character array
 *  \param name_len filename len
 *  \param data initial data
 *  \param data_len initial data len
 *  \param flags open flags
 *
 *  \retval ff flowfile object
 *
 *  \note filename is not a string, so it's not nul terminated.
 *
 *  If flags contains the FILE_USE_DETECT bit, the pruning code will
 *  consider not just the content_stored tracker, but also content_inspected.
 *  It's the responsibility of the API user to make sure this tracker is
 *  properly updated.
 */
int FileOpenFileWithId(FileContainer *, const StreamingBufferConfig *,
        uint32_t track_id, const uint8_t *name, uint16_t name_len,
        const uint8_t *data, uint32_t data_len, uint16_t flags);

/**
 *  \brief Close a File
 *
 *  \param ffc the container
 *  \param data final data if any
 *  \param data_len data len if any
 *  \param flags flags
 *
 *  \retval 0 ok
 *  \retval -1 error
 */
int FileCloseFile(FileContainer *, const StreamingBufferConfig *sbcfg, const uint8_t *data,
        uint32_t data_len, uint16_t flags);
int FileCloseFileById(FileContainer *, const StreamingBufferConfig *sbcfg, uint32_t track_id,
        const uint8_t *data, uint32_t data_len, uint16_t flags);
int FileCloseFilePtr(File *ff, const StreamingBufferConfig *sbcfg, const uint8_t *data,
        uint32_t data_len, uint16_t flags);

/**
 *  \brief Store a chunk of file data in the flow. The open "flowfile"
 *         will be used.
 *
 *  \param ffc the container
 *  \param data data chunk
 *  \param data_len data chunk len
 *
 *  \retval 0 ok
 *  \retval -1 error
 */
int FileAppendData(FileContainer *, const StreamingBufferConfig *sbcfg, const uint8_t *data,
        uint32_t data_len);
int FileAppendDataById(FileContainer *, const StreamingBufferConfig *sbcfg, uint32_t track_id,
        const uint8_t *data, uint32_t data_len);
int FileAppendGAPById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id,
        const uint8_t *data, uint32_t data_len);

void FileSetInspectSizes(File *file, const uint32_t win, const uint32_t min);

/**
 *  \brief Sets the offset range for a file.
 *
 *  \param ffc the container
 *  \param start start offset
 *  \param end end offset
 *
 *  \retval 0 ok
 *  \retval -1 error
 */
int FileSetRange(FileContainer *, uint64_t start, uint64_t end);

/**
 *  \brief Tag a file for storing
 *
 *  \param ff The file to store
 */
int FileStore(File *);

/**
 *  \brief disable file storing for a transaction
 *
 *  \param f flow
 *  \param direction STREAM_TOSERVER or STREAM_TOCLIENT
 *  \param tx transaction pointer
 *  \param tx_id transaction id
 */
void FileDisableStoringForTransaction(Flow *f, const uint8_t direction, void *tx, uint64_t tx_id);

void FileForceFilestoreEnable(void);
int FileForceFilestore(void);
void FileReassemblyDepthEnable(uint32_t size);
uint32_t FileReassemblyDepth(void);

void FileForceMagicEnable(void);
int FileForceMagic(void);

void FileForceMd5Enable(void);
int FileForceMd5(void);

void FileForceSha1Enable(void);
int FileForceSha1(void);

void FileForceSha256Enable(void);
int FileForceSha256(void);

void FileUpdateFlowFileFlags(Flow *f, uint16_t set_file_flags, uint8_t direction);

void FileForceHashParseCfg(ConfNode *);

void FileForceTrackingEnable(void);

void FileStoreFileById(FileContainer *fc, uint32_t);

uint64_t FileDataSize(const File *file);
uint64_t FileTrackedSize(const File *file);

uint16_t FileFlowFlagsToFlags(const uint16_t flow_file_flags, uint8_t direction);
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction);

#ifdef DEBUG
void FilePrintFlags(const File *file);
#else
#define FilePrintFlags(file)
#endif

void FilesPrune(FileContainer *fc, const StreamingBufferConfig *sbcfg, const bool trunc);

#endif /* __UTIL_FILE_H__ */