suricata
detect-filesize.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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  * Implements the filesize keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "app-layer-protos.h"
28 #include "app-layer-htp.h"
29 #include "util-unittest.h"
30 #include "util-unittest-helper.h"
31 #include "util-misc.h"
32 
33 #include "detect.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-engine-state.h"
37 #include "detect-engine-uint.h"
38 #include "detect-engine-build.h"
39 
40 #include "detect-filesize.h"
41 #include "util-debug.h"
42 #include "util-byte.h"
43 #include "flow-util.h"
44 #include "stream-tcp.h"
45 
46 
47 /*prototypes*/
48 static int DetectFilesizeMatch (DetectEngineThreadCtx *det_ctx, Flow *f,
49  uint8_t flags, File *file, const Signature *s, const SigMatchCtx *m);
50 static int DetectFilesizeSetup (DetectEngineCtx *, Signature *, const char *);
51 static void DetectFilesizeFree (DetectEngineCtx *, void *);
52 #ifdef UNITTESTS
53 static void DetectFilesizeRegisterTests (void);
54 #endif
55 static int g_file_match_list_id = 0;
56 
57 /**
58  * \brief Registration function for filesize: keyword
59  */
60 
62 {
63  sigmatch_table[DETECT_FILESIZE].name = "filesize";
64  sigmatch_table[DETECT_FILESIZE].desc = "match on the size of the file as it is being transferred";
65  sigmatch_table[DETECT_FILESIZE].url = "/rules/file-keywords.html#filesize";
66  sigmatch_table[DETECT_FILESIZE].FileMatch = DetectFilesizeMatch;
67  sigmatch_table[DETECT_FILESIZE].Setup = DetectFilesizeSetup;
68  sigmatch_table[DETECT_FILESIZE].Free = DetectFilesizeFree;
71 #ifdef UNITTESTS
72  sigmatch_table[DETECT_FILESIZE].RegisterTests = DetectFilesizeRegisterTests;
73 #endif
74 
75  g_file_match_list_id = DetectBufferTypeRegister("files");
76 }
77 
78 /**
79  * \brief This function is used to match filesize rule option.
80  *
81  * \param t thread local vars
82  * \param det_ctx pattern matcher thread local data
83  * \param f *LOCKED* flow
84  * \param flags direction flags
85  * \param file file being inspected
86  * \param s signature being inspected
87  * \param m sigmatch that we will cast into DetectU64Data
88  *
89  * \retval 0 no match
90  * \retval 1 match
91  */
92 static int DetectFilesizeMatch (DetectEngineThreadCtx *det_ctx, Flow *f,
93  uint8_t flags, File *file, const Signature *s, const SigMatchCtx *m)
94 {
95  SCEnter();
96 
97  DetectU64Data *fsd = (DetectU64Data *)m;
98  int ret = 0;
99  uint64_t file_size = FileTrackedSize(file);
100 
101  SCLogDebug("file size %" PRIu64 ", check %" PRIu64, file_size, fsd->arg1);
102 
103  if (file->state == FILE_STATE_CLOSED) {
104  return DetectU64Match(file_size, fsd);
105  /* truncated, error: only see if what we have meets the GT condition */
106  } else if (file->state > FILE_STATE_CLOSED) {
107  if (fsd->mode == DETECT_UINT_GT || fsd->mode == DETECT_UINT_GTE) {
108  ret = DetectU64Match(file_size, fsd);
109  }
110  }
111  SCReturnInt(ret);
112 }
113 
114 /**
115  * \brief this function is used to parse filesize data into the current signature
116  *
117  * \param de_ctx pointer to the Detection Engine Context
118  * \param s pointer to the Current Signature
119  * \param str pointer to the user provided options
120  *
121  * \retval 0 on Success
122  * \retval -1 on Failure
123  */
124 static int DetectFilesizeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
125 {
126  SCEnter();
128  if (fsd == NULL)
129  SCReturnInt(-1);
130 
132  de_ctx, s, DETECT_FILESIZE, (SigMatchCtx *)fsd, g_file_match_list_id) == NULL) {
133  DetectFilesizeFree(de_ctx, fsd);
134  SCReturnInt(-1);
135  }
136 
138  SCReturnInt(0);
139 }
140 
141 /**
142  * \brief this function will free memory associated with DetectU64Data
143  *
144  * \param ptr pointer to DetectU64Data
145  */
146 static void DetectFilesizeFree(DetectEngineCtx *de_ctx, void *ptr)
147 {
148  SCDetectU64Free(ptr);
149 }
150 
151 #ifdef UNITTESTS
152 #include "stream.h"
153 #include "stream-tcp-private.h"
154 #include "stream-tcp-reassemble.h"
155 #include "detect-engine-mpm.h"
156 #include "app-layer-parser.h"
157 
158 /** \test Test the Filesize keyword setup */
159 static int DetectFilesizeParseTest01(void)
160 {
161  DetectU64Data *fsd = DetectU64Parse("10");
162  FAIL_IF_NULL(fsd);
163  FAIL_IF_NOT(fsd->arg1 == 10);
164  FAIL_IF_NOT(fsd->mode == DETECT_UINT_EQ);
165  DetectFilesizeFree(NULL, fsd);
166 
167  PASS;
168 }
169 
170 /** \test Test the Filesize keyword setup */
171 static int DetectFilesizeParseTest02(void)
172 {
173  DetectU64Data *fsd = DetectU64Parse(" < 10 ");
174  FAIL_IF_NULL(fsd);
175  FAIL_IF_NOT(fsd->arg1 == 10);
176  FAIL_IF_NOT(fsd->mode == DETECT_UINT_LT);
177  DetectFilesizeFree(NULL, fsd);
178 
179  PASS;
180 }
181 
182 /** \test Test the Filesize keyword setup */
183 static int DetectFilesizeParseTest03(void)
184 {
185  DetectU64Data *fsd = DetectU64Parse(" > 10 ");
186  FAIL_IF_NULL(fsd);
187  FAIL_IF_NOT(fsd->arg1 == 10);
188  FAIL_IF_NOT(fsd->mode == DETECT_UINT_GT);
189  DetectFilesizeFree(NULL, fsd);
190 
191  PASS;
192 }
193 
194 /** \test Test the Filesize keyword setup */
195 static int DetectFilesizeParseTest04(void)
196 {
197  DetectU64Data *fsd = DetectU64Parse(" 5 <> 10 ");
198  FAIL_IF_NULL(fsd);
199  FAIL_IF_NOT(fsd->arg1 == 5);
200  FAIL_IF_NOT(fsd->arg2 == 10);
201  FAIL_IF_NOT(fsd->mode == DETECT_UINT_RA);
202  DetectFilesizeFree(NULL, fsd);
203 
204  PASS;
205 }
206 
207 /** \test Test the Filesize keyword setup */
208 static int DetectFilesizeParseTest05(void)
209 {
210  DetectU64Data *fsd = DetectU64Parse("5<>10");
211  FAIL_IF_NULL(fsd);
212  FAIL_IF_NOT(fsd->arg1 == 5);
213  FAIL_IF_NOT(fsd->arg2 == 10);
214  FAIL_IF_NOT(fsd->mode == DETECT_UINT_RA);
215  DetectFilesizeFree(NULL, fsd);
216 
217  PASS;
218 }
219 
220 /**
221  * \brief this function is used to initialize the detection engine context and
222  * setup the signature with passed values.
223  *
224  */
225 
226 static int DetectFilesizeInitTest(
227  DetectEngineCtx **de_ctx, Signature **sig, DetectU64Data **fsd, const char *str)
228 {
229  char fullstr[1024];
230  *de_ctx = NULL;
231 
233  (*de_ctx)->flags |= DE_QUIET;
234  FAIL_IF_NULL((*de_ctx));
235 
236  *sig = NULL;
237 
238  FAIL_IF(snprintf(fullstr, 1024,
239  "alert http any any -> any any (msg:\"Filesize "
240  "test\"; filesize:%s; sid:1;)",
241  str) >= 1024);
242 
243  Signature *s = DetectEngineAppendSig(*de_ctx, fullstr);
244  FAIL_IF_NULL(s);
245 
246  *sig = (*de_ctx)->sig_list;
247 
248  *fsd = DetectU64Parse(str);
249 
250  PASS;
251 }
252 
253 /**
254  * \test DetectFilesizeSetpTest01 is a test for setting up an valid filesize values
255  * with valid "<>" operator and include spaces arround the given values.
256  * In the test the values are setup with initializing the detection engine
257  * context and setting up the signature itself.
258  */
259 
260 static int DetectFilesizeSetpTest01(void)
261 {
262 
263  DetectU64Data *fsd = NULL;
264  uint8_t res = 0;
265  Signature *sig = NULL;
266  DetectEngineCtx *de_ctx = NULL;
267 
268  res = DetectFilesizeInitTest(&de_ctx, &sig, &fsd, "1 <> 3 ");
269  FAIL_IF(res == 0);
270 
271  FAIL_IF_NULL(fsd);
272  FAIL_IF_NOT(fsd->arg1 == 1);
273  FAIL_IF_NOT(fsd->arg2 == 3);
274  FAIL_IF_NOT(fsd->mode == DETECT_UINT_RA);
275 
276  DetectFilesizeFree(NULL, fsd);
278 
279  PASS;
280 }
281 
282 /**
283  * \brief this function registers unit tests for DetectFilesize
284  */
285 void DetectFilesizeRegisterTests(void)
286 {
287  UtRegisterTest("DetectFilesizeParseTest01", DetectFilesizeParseTest01);
288  UtRegisterTest("DetectFilesizeParseTest02", DetectFilesizeParseTest02);
289  UtRegisterTest("DetectFilesizeParseTest03", DetectFilesizeParseTest03);
290  UtRegisterTest("DetectFilesizeParseTest04", DetectFilesizeParseTest04);
291  UtRegisterTest("DetectFilesizeParseTest05", DetectFilesizeParseTest05);
292  UtRegisterTest("DetectFilesizeSetpTest01", DetectFilesizeSetpTest01);
293 }
294 #endif /* UNITTESTS */
util-byte.h
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1460
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigTableElmt_::desc
const char * desc
Definition: detect.h:1459
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1444
flow-util.h
SigTableElmt_::name
const char * name
Definition: detect.h:1457
stream-tcp.h
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DETECT_UINT_LT
#define DETECT_UINT_LT
Definition: detect-engine-uint.h:37
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1448
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
Flow_
Flow data structure.
Definition: flow.h:348
SigTableElmt_::FileMatch
int(* FileMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, File *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1427
File_::state
FileState state
Definition: util-file.h:110
DetectFilesizeRegister
void DetectFilesizeRegister(void)
Registration function for filesize: keyword.
Definition: detect-filesize.c:61
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2633
DETECT_UINT_EQ
#define DETECT_UINT_EQ
Definition: detect-engine-uint.h:35
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
stream-tcp-reassemble.h
m
SCMutex m
Definition: flow-hash.h:6
DETECT_UINT_GT
#define DETECT_UINT_GT
Definition: detect-engine-uint.h:32
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3437
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1439
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DETECT_FILESIZE
@ DETECT_FILESIZE
Definition: detect-engine-register.h:240
app-layer-htp.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1244
SIGMATCH_INFO_MULTI_UINT
#define SIGMATCH_INFO_MULTI_UINT
Definition: detect.h:1694
SIGMATCH_SUPPORT_DIR
#define SIGMATCH_SUPPORT_DIR
Definition: detect.h:1682
SCEnter
#define SCEnter(...)
Definition: util-debug.h:281
detect-engine-mpm.h
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:388
detect.h
FileTrackedSize
uint64_t FileTrackedSize(const File *file)
get the size of the file
Definition: util-file.c:325
app-layer-parser.h
stream.h
detect-engine-build.h
DETECT_UINT_GTE
#define DETECT_UINT_GTE
Definition: detect-engine-uint.h:33
stream-tcp-private.h
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:351
FILE_STATE_CLOSED
@ FILE_STATE_CLOSED
Definition: util-file.h:99
File_
Definition: util-file.h:107
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1214
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
Signature_::file_flags
uint8_t file_flags
Definition: detect.h:684
SIGMATCH_INFO_UINT64
#define SIGMATCH_INFO_UINT64
Definition: detect.h:1692
DetectU64Parse
DetectUintData_u64 * DetectU64Parse(const char *u64str)
Definition: detect-engine-uint.c:147
str
#define str(s)
Definition: suricata-common.h:308
DetectU64Data
DetectUintData_u64 DetectU64Data
Definition: detect-engine-uint.h:40
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
DetectU64Match
int DetectU64Match(const uint64_t parg, const DetectUintData_u64 *du64)
Definition: detect-engine-uint.c:142
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2594
detect-filesize.h
app-layer-protos.h
FILE_SIG_NEED_FILE
#define FILE_SIG_NEED_FILE
Definition: detect.h:320
util-misc.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:285
DETECT_UINT_RA
#define DETECT_UINT_RA
Definition: detect-engine-uint.h:34
FILE_SIG_NEED_SIZE
#define FILE_SIG_NEED_SIZE
Definition: detect.h:327
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1446