suricata
detect-nfs-procedure.c
Go to the documentation of this file.
1/* Copyright (C) 2017-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
24#include "suricata-common.h"
25#include "threads.h"
26#include "decode.h"
27#include "detect.h"
28
29#include "detect-parse.h"
30#include "detect-engine.h"
31#include "detect-engine-mpm.h"
32#include "detect-content.h"
33#include "detect-pcre.h"
35#include "detect-engine-uint.h"
36
37#include "app-layer-parser.h"
38
39#include "flow.h"
40#include "flow-util.h"
41#include "flow-var.h"
42
43#include "util-unittest.h"
45#include "util-byte.h"
46
47#include "app-layer-nfs-tcp.h"
48#include "rust.h"
49
50static int DetectNfsProcedureSetup (DetectEngineCtx *, Signature *s, const char *str);
51static void DetectNfsProcedureFree(DetectEngineCtx *, void *);
52#ifdef UNITTESTS
53static void DetectNfsProcedureRegisterTests(void);
54#endif
55static int g_nfs_request_buffer_id = 0;
56
57static int DetectNfsProcedureMatch (DetectEngineThreadCtx *, Flow *,
58 uint8_t, void *, void *, const Signature *,
59 const SigMatchCtx *);
60
61/**
62 * \brief Registration function for nfs_procedure keyword.
63 */
65{
66 sigmatch_table[DETECT_NFS_PROCEDURE].name = "nfs_procedure";
67 sigmatch_table[DETECT_NFS_PROCEDURE].desc = "match NFS procedure";
68 sigmatch_table[DETECT_NFS_PROCEDURE].url = "/rules/nfs-keywords.html#procedure";
70 sigmatch_table[DETECT_NFS_PROCEDURE].AppLayerTxMatch = DetectNfsProcedureMatch;
71 sigmatch_table[DETECT_NFS_PROCEDURE].Setup = DetectNfsProcedureSetup;
72 sigmatch_table[DETECT_NFS_PROCEDURE].Free = DetectNfsProcedureFree;
73#ifdef UNITTESTS
74 sigmatch_table[DETECT_NFS_PROCEDURE].RegisterTests = DetectNfsProcedureRegisterTests;
75#endif
76
79
80 g_nfs_request_buffer_id = DetectBufferTypeGetByName("nfs_request");
81
82 SCLogDebug("g_nfs_request_buffer_id %d", g_nfs_request_buffer_id);
83}
84
85/**
86 * \internal
87 * \brief Function to match procedure of a TX
88 *
89 * For 'file txs'
90 *
91 * \param t Pointer to thread vars.
92 * \param det_ctx Pointer to the pattern matcher thread.
93 * \param f Pointer to the current flow.
94 * \param flags Flags.
95 * \param state App layer state.
96 * \param s Pointer to the Signature.
97 * \param m Pointer to the sigmatch that we will cast into
98 * DetectU32Data.
99 *
100 * \retval 0 no match.
101 * \retval 1 match.
102 */
103static int DetectNfsProcedureMatch (DetectEngineThreadCtx *det_ctx,
104 Flow *f, uint8_t flags, void *state,
105 void *txv, const Signature *s,
106 const SigMatchCtx *ctx)
107{
108 SCEnter();
109
110 const DetectU32Data *dd = (const DetectU32Data *)ctx;
111 uint16_t i;
112 for (i = 0; i < 256; i++) {
113 uint32_t procedure;
114 if (SCNfsTxGetProcedures(txv, i, &procedure) == 1) {
115 SCLogDebug("proc %u mode %u lo %u hi %u", procedure, dd->mode, dd->arg1, dd->arg2);
116 if (DetectU32Match(procedure, dd))
117 SCReturnInt(1);
118 continue;
119 }
120 break;
121 }
122 SCReturnInt(0);
123}
124
125/**
126 * \internal
127 * \brief Function to parse options passed via tls validity keywords.
128 *
129 * \param rawstr Pointer to the user provided options.
130 *
131 * \retval dd pointer to DetectU32Data on success.
132 * \retval NULL on failure.
133 */
134static DetectU32Data *DetectNfsProcedureParse(const char *rawstr)
135{
136 return SCDetectU32ParseInclusive(rawstr);
137}
138
139
140
141/**
142 * \brief Function to add the parsed tls validity field into the current signature.
143 *
144 * \param de_ctx Pointer to the Detection Engine Context.
145 * \param s Pointer to the Current Signature.
146 * \param rawstr Pointer to the user provided flags options.
147 * \param type Defines if this is notBefore or notAfter.
148 *
149 * \retval 0 on Success.
150 * \retval -1 on Failure.
151 */
152static int DetectNfsProcedureSetup (DetectEngineCtx *de_ctx, Signature *s,
153 const char *rawstr)
154{
155 DetectU32Data *dd = NULL;
156
157 SCLogDebug("\'%s\'", rawstr);
158
160 return -1;
161
162 dd = DetectNfsProcedureParse(rawstr);
163 if (dd == NULL) {
164 SCLogError("Parsing \'%s\' failed", rawstr);
165 return -1;
166 }
167
168 /* okay so far so good, lets get this into a SigMatch
169 * and put it in the Signature. */
170
171 SCLogDebug("low %u hi %u", dd->arg1, dd->arg2);
173 g_nfs_request_buffer_id) == NULL) {
174 DetectNfsProcedureFree(de_ctx, dd);
175 return -1;
176 }
177 return 0;
178}
179
180/**
181 * \internal
182 * \brief Function to free memory associated with DetectU32Data.
183 *
184 * \param de_ptr Pointer to DetectU32Data.
185 */
186void DetectNfsProcedureFree(DetectEngineCtx *de_ctx, void *ptr)
187{
188 SCDetectU32Free(ptr);
189}
190
191#ifdef UNITTESTS
192
193/**
194 * \test This is a test for a valid value 1430000000.
195 *
196 * \retval 1 on success.
197 * \retval 0 on failure.
198 */
199static int ValidityTestParse01 (void)
200{
201 DetectU32Data *dd = NULL;
202 dd = DetectNfsProcedureParse("1430000000");
203 FAIL_IF_NULL(dd);
204 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->mode == DETECT_UINT_EQ);
205 DetectNfsProcedureFree(NULL, dd);
206 PASS;
207}
208
209/**
210 * \test This is a test for a valid value >1430000000.
211 *
212 * \retval 1 on success.
213 * \retval 0 on failure.
214 */
215static int ValidityTestParse02 (void)
216{
217 DetectU32Data *dd = NULL;
218 dd = DetectNfsProcedureParse(">1430000000");
219 FAIL_IF_NULL(dd);
220 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->mode == DETECT_UINT_GT);
221 DetectNfsProcedureFree(NULL, dd);
222 PASS;
223}
224
225/**
226 * \test This is a test for a valid value <1430000000.
227 *
228 * \retval 1 on success.
229 * \retval 0 on failure.
230 */
231static int ValidityTestParse03 (void)
232{
233 DetectU32Data *dd = NULL;
234 dd = DetectNfsProcedureParse("<1430000000");
235 FAIL_IF_NULL(dd);
236 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->mode == DETECT_UINT_LT);
237 DetectNfsProcedureFree(NULL, dd);
238 PASS;
239}
240
241/**
242 * \test This is a test for a valid value 1430000000<>1470000000.
243 *
244 * \retval 1 on success.
245 * \retval 0 on failure.
246 */
247static int ValidityTestParse04 (void)
248{
249 DetectU32Data *dd = NULL;
250 dd = DetectNfsProcedureParse("1430000001<>1470000000");
251 FAIL_IF_NULL(dd);
252 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->arg2 == 1470000001 && dd->mode == DETECT_UINT_RA);
253 DetectNfsProcedureFree(NULL, dd);
254 PASS;
255}
256
257/**
258 * \test This is a test for a invalid value A.
259 *
260 * \retval 1 on success.
261 * \retval 0 on failure.
262 */
263static int ValidityTestParse05 (void)
264{
265 DetectU32Data *dd = NULL;
266 dd = DetectNfsProcedureParse("A");
268 PASS;
269}
270
271/**
272 * \test This is a test for a invalid value >1430000000<>1470000000.
273 *
274 * \retval 1 on success.
275 * \retval 0 on failure.
276 */
277static int ValidityTestParse06 (void)
278{
279 DetectU32Data *dd = NULL;
280 dd = DetectNfsProcedureParse(">1430000000<>1470000000");
282 PASS;
283}
284
285/**
286 * \test This is a test for a invalid value 1430000000<>.
287 *
288 * \retval 1 on success.
289 * \retval 0 on failure.
290 */
291static int ValidityTestParse07 (void)
292{
293 DetectU32Data *dd = NULL;
294 dd = DetectNfsProcedureParse("1430000000<>");
296 PASS;
297}
298
299/**
300 * \test This is a test for a invalid value <>1430000000.
301 *
302 * \retval 1 on success.
303 * \retval 0 on failure.
304 */
305static int ValidityTestParse08 (void)
306{
307 DetectU32Data *dd = NULL;
308 dd = DetectNfsProcedureParse("<>1430000000");
310 PASS;
311}
312
313/**
314 * \test This is a test for a invalid value "".
315 *
316 * \retval 1 on success.
317 * \retval 0 on failure.
318 */
319static int ValidityTestParse09 (void)
320{
321 DetectU32Data *dd = NULL;
322 dd = DetectNfsProcedureParse("");
324 PASS;
325}
326
327/**
328 * \test This is a test for a invalid value " ".
329 *
330 * \retval 1 on success.
331 * \retval 0 on failure.
332 */
333static int ValidityTestParse10 (void)
334{
335 DetectU32Data *dd = NULL;
336 dd = DetectNfsProcedureParse(" ");
338 PASS;
339}
340
341/**
342 * \test This is a test for a invalid value 1490000000<>1430000000.
343 *
344 * \retval 1 on success.
345 * \retval 0 on failure.
346 */
347static int ValidityTestParse11 (void)
348{
349 DetectU32Data *dd = NULL;
350 dd = DetectNfsProcedureParse("1490000000<>1430000000");
352 PASS;
353}
354
355/**
356 * \test This is a test for a valid value 1430000000 <> 1490000000.
357 *
358 * \retval 1 on success.
359 * \retval 0 on failure.
360 */
361static int ValidityTestParse12 (void)
362{
363 DetectU32Data *dd = NULL;
364 dd = DetectNfsProcedureParse("1430000001 <> 1490000000");
365 FAIL_IF_NULL(dd);
366 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->arg2 == 1490000001 && dd->mode == DETECT_UINT_RA);
367 DetectNfsProcedureFree(NULL, dd);
368 PASS;
369}
370
371/**
372 * \test This is a test for a valid value > 1430000000.
373 *
374 * \retval 1 on success.
375 * \retval 0 on failure.
376 */
377static int ValidityTestParse13 (void)
378{
379 DetectU32Data *dd = NULL;
380 dd = DetectNfsProcedureParse("> 1430000000 ");
381 FAIL_IF_NULL(dd);
382 FAIL_IF_NOT(dd->arg1 == 1430000000 && dd->mode == DETECT_UINT_GT);
383 DetectNfsProcedureFree(NULL, dd);
384 PASS;
385}
386
387/**
388 * \test This is a test for a valid value < 1490000000.
389 *
390 * \retval 1 on success.
391 * \retval 0 on failure.
392 */
393static int ValidityTestParse14 (void)
394{
395 DetectU32Data *dd = NULL;
396 dd = DetectNfsProcedureParse("< 1490000000 ");
397 FAIL_IF_NULL(dd);
398 FAIL_IF_NOT(dd->arg1 == 1490000000 && dd->mode == DETECT_UINT_LT);
399 DetectNfsProcedureFree(NULL, dd);
400 PASS;
401}
402
403/**
404 * \test This is a test for a valid value 1490000000.
405 *
406 * \retval 1 on success.
407 * \retval 0 on failure.
408 */
409static int ValidityTestParse15 (void)
410{
411 DetectU32Data *dd = NULL;
412 dd = DetectNfsProcedureParse(" 1490000000 ");
413 FAIL_IF_NULL(dd);
414 FAIL_IF_NOT(dd->arg1 == 1490000000 && dd->mode == DETECT_UINT_EQ);
415 DetectNfsProcedureFree(NULL, dd);
416 PASS;
417}
418
419/**
420 * \brief Register unit tests for nfs_procedure.
421 */
422void DetectNfsProcedureRegisterTests(void)
423{
424 UtRegisterTest("ValidityTestParse01", ValidityTestParse01);
425 UtRegisterTest("ValidityTestParse02", ValidityTestParse02);
426 UtRegisterTest("ValidityTestParse03", ValidityTestParse03);
427 UtRegisterTest("ValidityTestParse04", ValidityTestParse04);
428 UtRegisterTest("ValidityTestParse05", ValidityTestParse05);
429 UtRegisterTest("ValidityTestParse06", ValidityTestParse06);
430 UtRegisterTest("ValidityTestParse07", ValidityTestParse07);
431 UtRegisterTest("ValidityTestParse08", ValidityTestParse08);
432 UtRegisterTest("ValidityTestParse09", ValidityTestParse09);
433 UtRegisterTest("ValidityTestParse10", ValidityTestParse10);
434 UtRegisterTest("ValidityTestParse11", ValidityTestParse11);
435 UtRegisterTest("ValidityTestParse12", ValidityTestParse12);
436 UtRegisterTest("ValidityTestParse13", ValidityTestParse13);
437 UtRegisterTest("ValidityTestParse14", ValidityTestParse14);
438 UtRegisterTest("ValidityTestParse15", ValidityTestParse15);
439}
440#endif /* UNITTESTS */
@ ALPROTO_NFS
uint8_t flags
Definition decode-gre.h:0
@ DETECT_NFS_PROCEDURE
int DetectU32Match(const uint32_t parg, const DetectUintData_u32 *du32)
#define DETECT_UINT_LT
#define DETECT_UINT_EQ
#define DETECT_UINT_GT
#define DETECT_UINT_RA
DetectUintData_u32 DetectU32Data
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
int DetectBufferTypeGetByName(const char *name)
uint8_t DetectEngineInspectGenericList(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
void DetectNfsProcedureRegister(void)
Registration function for nfs_procedure keyword.
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
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 SIG_FLAG_TOSERVER
Definition detect.h:271
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
struct Thresholds ctx
main detection engine ctx
Definition detect.h:932
Flow data structure.
Definition flow.h:356
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
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
const char * desc
Definition detect.h:1461
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition detect.h:1424
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
#define str(s)
#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