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