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-helper.h"
28 
29 #include "detect.h"
30 #include "detect-parse.h"
31 #include "detect-engine.h"
32 #include "detect-engine-buffer.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(const DetectU64Data *bsz, uint64_t *bsize);
44 #ifdef UNITTESTS
45 static void DetectBsizeRegisterTests (void);
46 #endif
47 
49 {
50  uint64_t bsize;
51  int retval = -1;
52  const DetectU64Data *bsz;
53  for (const SigMatch *sm = b->head; sm != NULL; sm = sm->next) {
54  if (sm->type == DETECT_BSIZE) {
55  bsz = (const DetectU64Data *)sm->ctx;
56  retval = SigParseGetMaxBsize(bsz, &bsize);
57  break;
58  }
59  }
60 
61  if (retval == -1) {
62  return true;
63  }
64 
65  uint64_t needed;
66  if (retval == 0) {
67  int len, offset;
68  SigParseRequiredContentSize(s, bsize, b->head, &len, &offset);
69  SCLogDebug("bsize: %" PRIu64 "; len: %d; offset: %d [%s]", bsize, len, offset, s->sig_str);
70  needed = len;
71  if ((uint64_t)len > bsize) {
72  goto value_error;
73  }
74  if ((uint64_t)(len + offset) > bsize) {
75  needed += offset;
76  goto value_error;
77  }
78  }
79 
80  return true;
81 value_error:
82  if (bsz->mode == DETECT_UINT_RA) {
83  SCLogError("signature can't match as required content length %" PRIu64
84  " exceeds bsize range: %" PRIu64 "-%" PRIu64,
85  needed, bsz->arg1, bsz->arg2);
86  } else {
87  SCLogError("signature can't match as required content length %" PRIu64
88  " exceeds bsize value: "
89  "%" PRIu64,
90  needed, bsz->arg1);
91  }
92  return false;
93 }
94 
95 /**
96  * \brief Registration function for bsize: keyword
97  */
98 
100 {
101  sigmatch_table[DETECT_BSIZE].name = "bsize";
102  sigmatch_table[DETECT_BSIZE].desc = "match on the length of a buffer";
103  sigmatch_table[DETECT_BSIZE].url = "/rules/payload-keywords.html#bsize";
105  sigmatch_table[DETECT_BSIZE].Setup = DetectBsizeSetup;
106  sigmatch_table[DETECT_BSIZE].Free = DetectBsizeFree;
108 #ifdef UNITTESTS
109  sigmatch_table[DETECT_BSIZE].RegisterTests = DetectBsizeRegisterTests;
110 #endif
111 }
112 
113 /** \brief bsize match function
114  *
115  * \param ctx match ctx
116  * \param buffer_size size of the buffer
117  * \param eof is the buffer closed?
118  *
119  * \retval r 1 match, 0 no match, -1 can't match
120  */
121 int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
122 {
123  const DetectU64Data *bsz = (const DetectU64Data *)ctx;
124  if (DetectU64Match(buffer_size, bsz)) {
125  return 1;
126  }
127  switch (bsz->mode) {
128  case DETECT_UINT_LTE:
129  return -1;
130  case DETECT_UINT_LT:
131  return -1;
132 
133  case DETECT_UINT_GTE:
134  // fallthrough
135  case DETECT_UINT_GT:
136  if (eof) {
137  return -1;
138  }
139  return 0;
140 
141  case DETECT_UINT_EQ:
142  if (buffer_size > bsz->arg1) {
143  return -1;
144  } else if (eof) {
145  return -1;
146  } else {
147  return 0;
148  }
149 
150  case DETECT_UINT_RA:
151  if (buffer_size <= bsz->arg1 && eof) {
152  return -1;
153  } else if (buffer_size <= bsz->arg1) {
154  return 0;
155  } else if (buffer_size >= bsz->arg2) {
156  return -1;
157  }
158  }
159  return 0;
160 }
161 
162 static int SigParseGetMaxBsize(const DetectU64Data *bsz, uint64_t *bsize)
163 {
164  switch (bsz->mode) {
165  case DETECT_UINT_LT:
166  case DETECT_UINT_EQ:
167  *bsize = bsz->arg1;
168  SCReturnInt(0);
169  case DETECT_UINT_RA:
170  *bsize = bsz->arg2;
171  SCReturnInt(0);
172  case DETECT_UINT_GT:
173  default:
174  SCReturnInt(-2);
175  }
176  SCReturnInt(-1);
177 }
178 
179 /**
180  * \brief this function is used to parse bsize data into the current signature
181  *
182  * \param de_ctx pointer to the Detection Engine Context
183  * \param s pointer to the Current Signature
184  * \param sizestr pointer to the user provided bsize options
185  *
186  * \retval 0 on Success
187  * \retval -1 on Failure
188  */
189 static int DetectBsizeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *sizestr)
190 {
191  SCEnter();
192 
193  if (DetectBufferGetActiveList(de_ctx, s) == -1)
194  SCReturnInt(-1);
195 
196  int list = s->init_data->list;
197  if (list == DETECT_SM_LIST_NOTSET)
198  SCReturnInt(-1);
199 
200  DetectU64Data *bsz = DetectU64Parse(sizestr);
201  if (bsz == NULL)
202  SCReturnInt(-1);
203 
204  if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BSIZE, (SigMatchCtx *)bsz, list) == NULL) {
205  goto error;
206  }
207 
208  SCReturnInt(0);
209 
210 error:
211  DetectBsizeFree(de_ctx, bsz);
212  SCReturnInt(-1);
213 }
214 
215 /**
216  * \brief this function will free memory associated with DetectU64Data
217  *
218  * \param ptr pointer to DetectU64Data
219  */
220 void DetectBsizeFree(DetectEngineCtx *de_ctx, void *ptr)
221 {
222  if (ptr == NULL)
223  return;
224 
225  DetectU64Data *bsz = (DetectU64Data *)ptr;
226  SCDetectU64Free(bsz);
227 }
228 
229 #ifdef UNITTESTS
230 #include "tests/detect-bsize.c"
231 #endif
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1545
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:543
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1544
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:78
Signature_::sig_str
char * sig_str
Definition: detect.h:773
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1529
SigTableElmt_::name
const char * name
Definition: detect.h:1542
DETECT_UINT_LT
#define DETECT_UINT_LT
Definition: detect-engine-uint.h:37
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1533
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
detect-bsize.c
detect-bsize.h
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DETECT_UINT_EQ
#define DETECT_UINT_EQ
Definition: detect-engine-uint.h:35
DETECT_UINT_GT
#define DETECT_UINT_GT
Definition: detect-engine-uint.h:32
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1524
util-unittest-helper.h
DetectBsizeRegister
void DetectBsizeRegister(void)
Registration function for bsize: keyword.
Definition: detect-bsize.c:99
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectBsizeMatch
int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
bsize match function
Definition: detect-bsize.c:121
DETECT_BSIZE
@ DETECT_BSIZE
Definition: detect-engine-register.h:99
SignatureInitData_::list
int list
Definition: detect.h:645
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
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:424
detect.h
SIGMATCH_INFO_UINT64
#define SIGMATCH_INFO_UINT64
Definition: detect-engine-register.h:348
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:364
DETECT_UINT_GTE
#define DETECT_UINT_GTE
Definition: detect-engine-uint.h:33
SigParseRequiredContentSize
void SigParseRequiredContentSize(const Signature *s, const uint64_t max_size, const SigMatch *sm, int *len, int *offset)
Determine the size needed to accommodate the content elements of a signature.
Definition: detect-content.c:404
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1504
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:355
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:145
suricata-common.h
detect-engine-buffer.h
DetectBsizeValidateContentCallback
bool DetectBsizeValidateContentCallback(const Signature *s, const SignatureInitDataBuffer *b)
Definition: detect-bsize.c:48
DetectU64Parse
DetectUintData_u64 * DetectU64Parse(const char *u64str)
Definition: detect-engine-uint.c:143
DETECT_UINT_LTE
#define DETECT_UINT_LTE
Definition: detect-engine-uint.h:38
DetectU64Data
DetectUintData_u64 DetectU64Data
Definition: detect-engine-uint.h:40
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
detect-parse.h
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
DetectU64Match
int DetectU64Match(const uint64_t parg, const DetectUintData_u64 *du64)
Definition: detect-engine-uint.c:138
SIGMATCH_SUPPORT_FIREWALL
#define SIGMATCH_SUPPORT_FIREWALL
Definition: detect-engine-register.h:336
util-misc.h
SignatureInitDataBuffer_
Definition: detect.h:533
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-buffer.c:109
DETECT_UINT_RA
#define DETECT_UINT_RA
Definition: detect-engine-uint.h:34
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1531