suricata
detect-bsize.c
Go to the documentation of this file.
1 /* Copyright (C) 2017-2022 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 bsize generic buffer length keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "util-unittest.h"
28 #include "util-unittest-helper.h"
29 
30 #include "detect.h"
31 #include "detect-parse.h"
32 #include "detect-engine.h"
33 #include "detect-content.h"
34 #include "detect-engine-uint.h"
35 
36 #include "detect-bsize.h"
37 
38 #include "util-misc.h"
39 
40 /*prototypes*/
41 static int DetectBsizeSetup (DetectEngineCtx *, Signature *, const char *);
42 static void DetectBsizeFree (DetectEngineCtx *, void *);
43 static int SigParseGetMaxBsize(DetectU64Data *bsz);
44 #ifdef UNITTESTS
45 static void DetectBsizeRegisterTests (void);
46 #endif
47 
49 {
50  int bsize = -1;
51  DetectU64Data *bsz;
52  for (const SigMatch *sm = s->init_data->smlists[list]; sm != NULL; sm = sm->next) {
53  if (sm->type == DETECT_BSIZE) {
54  bsz = (DetectU64Data *)sm->ctx;
55  bsize = SigParseGetMaxBsize(bsz);
56  break;
57  }
58  }
59 
60  if (bsize == -1) {
61  return true;
62  }
63 
64  uint64_t needed;
65  if (bsize >= 0) {
66  int len, offset;
67  SigParseRequiredContentSize(s, bsize, list, &len, &offset);
68  SCLogDebug("bsize: %d; len: %d; offset: %d [%s]", bsize, len, offset, s->sig_str);
69  needed = len;
70  if (len > bsize) {
71  goto value_error;
72  }
73  if ((len + offset) > bsize) {
74  needed += offset;
75  goto value_error;
76  }
77  }
78 
79  return true;
80 value_error:
81  if (bsz->mode == DETECT_UINT_RA) {
82  SCLogError("signature can't match as required content length %" PRIu64
83  " exceeds bsize range: %" PRIu64 "-%" PRIu64,
84  needed, bsz->arg1, bsz->arg2);
85  } else {
86  SCLogError("signature can't match as required content length %" PRIu64
87  " exceeds bsize value: "
88  "%" PRIu64,
89  needed, bsz->arg1);
90  }
91  return false;
92 }
93 
94 /**
95  * \brief Registration function for bsize: keyword
96  */
97 
99 {
100  sigmatch_table[DETECT_BSIZE].name = "bsize";
101  sigmatch_table[DETECT_BSIZE].desc = "match on the length of a buffer";
102  sigmatch_table[DETECT_BSIZE].url = "/rules/payload-keywords.html#bsize";
104  sigmatch_table[DETECT_BSIZE].Setup = DetectBsizeSetup;
105  sigmatch_table[DETECT_BSIZE].Free = DetectBsizeFree;
106 #ifdef UNITTESTS
107  sigmatch_table[DETECT_BSIZE].RegisterTests = DetectBsizeRegisterTests;
108 #endif
109 }
110 
111 /** \brief bsize match function
112  *
113  * \param ctx match ctx
114  * \param buffer_size size of the buffer
115  * \param eof is the buffer closed?
116  *
117  * \retval r 1 match, 0 no match, -1 can't match
118  */
119 int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
120 {
121  const DetectU64Data *bsz = (const DetectU64Data *)ctx;
122  if (DetectU64Match(buffer_size, bsz)) {
123  return 1;
124  }
125  switch (bsz->mode) {
126  case DETECT_UINT_LTE:
127  return -1;
128  case DETECT_UINT_LT:
129  return -1;
130 
131  case DETECT_UINT_GTE:
132  // fallthrough
133  case DETECT_UINT_GT:
134  if (eof) {
135  return -1;
136  }
137  return 0;
138 
139  case DETECT_UINT_EQ:
140  if (buffer_size > bsz->arg1) {
141  return -1;
142  } else if (eof) {
143  return -1;
144  } else {
145  return 0;
146  }
147 
148  case DETECT_UINT_RA:
149  if (buffer_size <= bsz->arg1 && eof) {
150  return -1;
151  } else if (buffer_size <= bsz->arg1) {
152  return 0;
153  } else if (buffer_size >= bsz->arg2) {
154  return -1;
155  }
156  }
157  return 0;
158 }
159 
160 /**
161  * \brief This function is used to parse bsize options passed via bsize: keyword
162  *
163  * \param bsizestr Pointer to the user provided bsize options
164  *
165  * \retval bsized pointer to DetectU64Data on success
166  * \retval NULL on failure
167  */
168 
169 static DetectU64Data *DetectBsizeParse(const char *str)
170 {
171  return DetectU64Parse(str);
172 }
173 
174 static int SigParseGetMaxBsize(DetectU64Data *bsz)
175 {
176  switch (bsz->mode) {
177  case DETECT_UINT_LT:
178  case DETECT_UINT_EQ:
179  return bsz->arg1;
180  case DETECT_UINT_RA:
181  return bsz->arg2;
182  case DETECT_UINT_GT:
183  default:
184  SCReturnInt(-2);
185  }
186  SCReturnInt(-1);
187 }
188 
189 /**
190  * \brief this function is used to parse bsize data into the current signature
191  *
192  * \param de_ctx pointer to the Detection Engine Context
193  * \param s pointer to the Current Signature
194  * \param sizestr pointer to the user provided bsize options
195  *
196  * \retval 0 on Success
197  * \retval -1 on Failure
198  */
199 static int DetectBsizeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *sizestr)
200 {
201  SCEnter();
202  SigMatch *sm = NULL;
203 
204  if (DetectBufferGetActiveList(de_ctx, s) == -1)
205  SCReturnInt(-1);
206 
207  int list = s->init_data->list;
208  if (list == DETECT_SM_LIST_NOTSET)
209  SCReturnInt(-1);
210 
211  DetectU64Data *bsz = DetectBsizeParse(sizestr);
212  if (bsz == NULL)
213  goto error;
214 
215  sm = SigMatchAlloc();
216  if (sm == NULL)
217  goto error;
218  sm->type = DETECT_BSIZE;
219  sm->ctx = (void *)bsz;
220 
221  SigMatchAppendSMToList(s, sm, list);
222 
223  SCReturnInt(0);
224 
225 error:
226  DetectBsizeFree(de_ctx, bsz);
227  SCReturnInt(-1);
228 }
229 
230 /**
231  * \brief this function will free memory associated with DetectU64Data
232  *
233  * \param ptr pointer to DetectU64Data
234  */
235 void DetectBsizeFree(DetectEngineCtx *de_ctx, void *ptr)
236 {
237  if (ptr == NULL)
238  return;
239 
240  DetectU64Data *bsz = (DetectU64Data *)ptr;
241  rs_detect_u64_free(bsz);
242 }
243 
244 #ifdef UNITTESTS
245 #include "tests/detect-bsize.c"
246 #endif
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1241
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1240
Signature_::sig_str
char * sig_str
Definition: detect.h:609
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1228
SigTableElmt_::name
const char * name
Definition: detect.h:1238
DETECT_UINT_LT
#define DETECT_UINT_LT
Definition: detect-engine-uint.h:37
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
detect-bsize.c
detect-bsize.h
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:785
DETECT_UINT_EQ
#define DETECT_UINT_EQ
Definition: detect-engine-uint.h:35
DetectBsizeValidateContentCallback
bool DetectBsizeValidateContentCallback(Signature *s, int list)
Definition: detect-bsize.c:48
DETECT_UINT_GT
#define DETECT_UINT_GT
Definition: detect-engine-uint.h:32
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1306
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1223
util-unittest.h
util-unittest-helper.h
DetectBsizeRegister
void DetectBsizeRegister(void)
Registration function for bsize: keyword.
Definition: detect-bsize.c:98
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectBsizeMatch
int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
bsize match function
Definition: detect-bsize.c:119
DETECT_BSIZE
@ DETECT_BSIZE
Definition: detect-engine-register.h:108
SignatureInitData_::list
int list
Definition: detect.h:517
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:317
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:316
DETECT_UINT_GTE
#define DETECT_UINT_GTE
Definition: detect-engine-uint.h:33
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:611
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1206
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:534
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:239
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:308
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:104
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:314
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
DetectU64Parse
DetectUintData_u64 * DetectU64Parse(const char *u64str)
Definition: detect-engine-uint.c:147
SigParseRequiredContentSize
void SigParseRequiredContentSize(const Signature *s, const int max_size, int list, int *len, int *offset)
Definition: detect-content.c:414
DETECT_UINT_LTE
#define DETECT_UINT_LTE
Definition: detect-engine-uint.h:38
str
#define str(s)
Definition: suricata-common.h:280
DetectU64Data
DetectUintData_u64 DetectU64Data
Definition: detect-engine-uint.h:40
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
detect-parse.h
Signature_
Signature container.
Definition: detect.h:540
SigMatch_
a single match condition for a signature
Definition: detect.h:313
DetectU64Match
int DetectU64Match(const uint64_t parg, const DetectUintData_u64 *du64)
Definition: detect-engine-uint.c:142
util-misc.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:354
DETECT_UINT_RA
#define DETECT_UINT_RA
Definition: detect-engine-uint.h:34
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1230