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