suricata
detect-tcp-seq.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 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 Brian Rectanus <brectanu@gmail.com>
22  *
23  * Implements the seq keyword.
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "decode.h"
29 #include "detect.h"
30 
31 #include "detect-parse.h"
32 #include "detect-engine.h"
35 
36 #include "detect-tcp-seq.h"
37 
38 #include "util-byte.h"
39 #include "util-unittest.h"
40 #include "util-unittest-helper.h"
41 #include "util-debug.h"
42 
43 static int DetectSeqSetup(DetectEngineCtx *, Signature *, const char *);
44 static int DetectSeqMatch(DetectEngineThreadCtx *,
45  Packet *, const Signature *, const SigMatchCtx *);
46 #ifdef UNITTESTS
47 static void DetectSeqRegisterTests(void);
48 #endif
49 static void DetectSeqFree(DetectEngineCtx *, void *);
50 static int PrefilterSetupTcpSeq(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
51 static bool PrefilterTcpSeqIsPrefilterable(const Signature *s);
52 
54 {
55  sigmatch_table[DETECT_SEQ].name = "tcp.seq";
57  sigmatch_table[DETECT_SEQ].desc = "check for a specific TCP sequence number";
58  sigmatch_table[DETECT_SEQ].url = "/rules/header-keywords.html#seq";
59  sigmatch_table[DETECT_SEQ].Match = DetectSeqMatch;
60  sigmatch_table[DETECT_SEQ].Setup = DetectSeqSetup;
61  sigmatch_table[DETECT_SEQ].Free = DetectSeqFree;
62 #ifdef UNITTESTS
63  sigmatch_table[DETECT_SEQ].RegisterTests = DetectSeqRegisterTests;
64 #endif
65  sigmatch_table[DETECT_SEQ].SupportsPrefilter = PrefilterTcpSeqIsPrefilterable;
66  sigmatch_table[DETECT_SEQ].SetupPrefilter = PrefilterSetupTcpSeq;
67 }
68 
69 /**
70  * \internal
71  * \brief This function is used to match packets with a given Seq number
72  *
73  * \param t pointer to thread vars
74  * \param det_ctx pointer to the pattern matcher thread
75  * \param p pointer to the current packet
76  * \param m pointer to the sigmatch that we will cast into DetectSeqData
77  *
78  * \retval 0 no match
79  * \retval 1 match
80  */
81 static int DetectSeqMatch(DetectEngineThreadCtx *det_ctx,
82  Packet *p, const Signature *s, const SigMatchCtx *ctx)
83 {
84  const DetectSeqData *data = (const DetectSeqData *)ctx;
85 
86  /* This is only needed on TCP packets */
87  if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
88  return 0;
89  }
90 
91  return (data->seq == TCP_GET_SEQ(p)) ? 1 : 0;
92 }
93 
94 /**
95  * \internal
96  * \brief this function is used to add the seq option into the signature
97  *
98  * \param de_ctx pointer to the Detection Engine Context
99  * \param s pointer to the Current Signature
100  * \param optstr pointer to the user provided options
101  *
102  * \retval 0 on Success
103  * \retval -1 on Failure
104  */
105 static int DetectSeqSetup (DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
106 {
107  DetectSeqData *data = NULL;
108  SigMatch *sm = NULL;
109 
110  data = SCMalloc(sizeof(DetectSeqData));
111  if (unlikely(data == NULL))
112  goto error;
113 
114  sm = SigMatchAlloc();
115  if (sm == NULL)
116  goto error;
117 
118  sm->type = DETECT_SEQ;
119 
120  if (StringParseUint32(&data->seq, 10, 0, optstr) < 0) {
121  goto error;
122  }
123  sm->ctx = (SigMatchCtx*)data;
124 
127 
128  return 0;
129 
130 error:
131  if (data)
132  SCFree(data);
133  if (sm)
134  SigMatchFree(de_ctx, sm);
135  return -1;
136 
137 }
138 
139 /**
140  * \internal
141  * \brief this function will free memory associated with seq option
142  *
143  * \param data pointer to seq configuration data
144  */
145 static void DetectSeqFree(DetectEngineCtx *de_ctx, void *ptr)
146 {
147  DetectSeqData *data = (DetectSeqData *)ptr;
148  SCFree(data);
149 }
150 
151 /* prefilter code */
152 
153 static void
154 PrefilterPacketSeqMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
155 {
156  const PrefilterPacketHeaderCtx *ctx = pectx;
157 
158  if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE)
159  return;
160 
161  if ((p->proto) == IPPROTO_TCP && !(PKT_IS_PSEUDOPKT(p)) &&
162  (p->tcph != NULL) && (TCP_GET_SEQ(p) == ctx->v1.u32[0]))
163  {
164  SCLogDebug("packet matches TCP seq %u", ctx->v1.u32[0]);
165  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
166  }
167 }
168 
169 static void
170 PrefilterPacketSeqSet(PrefilterPacketHeaderValue *v, void *smctx)
171 {
172  const DetectSeqData *a = smctx;
173  v->u32[0] = a->seq;
174 }
175 
176 static bool
177 PrefilterPacketSeqCompare(PrefilterPacketHeaderValue v, void *smctx)
178 {
179  const DetectSeqData *a = smctx;
180  if (v.u32[0] == a->seq)
181  return TRUE;
182  return FALSE;
183 }
184 
185 static int PrefilterSetupTcpSeq(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
186 {
188  PrefilterPacketSeqSet,
189  PrefilterPacketSeqCompare,
190  PrefilterPacketSeqMatch);
191 }
192 
193 static bool PrefilterTcpSeqIsPrefilterable(const Signature *s)
194 {
195  const SigMatch *sm;
196  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
197  switch (sm->type) {
198  case DETECT_SEQ:
199  return TRUE;
200  }
201  }
202  return FALSE;
203 }
204 
205 
206 #ifdef UNITTESTS
207 
208 /**
209  * \test DetectSeqSigTest01 tests parses
210  */
211 static int DetectSeqSigTest01(void)
212 {
213  int result = 0;
215  if (de_ctx == NULL)
216  goto end;
217 
218  /* These three are crammed in here as there is no Parse */
219  if (SigInit(de_ctx,
220  "alert tcp any any -> any any "
221  "(msg:\"Testing seq\";seq:foo;sid:1;)") != NULL)
222  {
223  printf("invalid seq accepted: ");
224  goto cleanup;
225  }
226  if (SigInit(de_ctx,
227  "alert tcp any any -> any any "
228  "(msg:\"Testing seq\";seq:9999999999;sid:1;)") != NULL)
229  {
230  printf("overflowing seq accepted: ");
231  goto cleanup;
232  }
233  if (SigInit(de_ctx,
234  "alert tcp any any -> any any "
235  "(msg:\"Testing seq\";seq:-100;sid:1;)") != NULL)
236  {
237  printf("negative seq accepted: ");
238  goto cleanup;
239  }
240  result = 1;
241 
242 cleanup:
243  if (de_ctx) {
247  }
248 end:
249  return result;
250 }
251 
252 /**
253  * \test DetectSeqSigTest02 tests seq keyword
254  */
255 static int DetectSeqSigTest02(void)
256 {
257  int result = 0;
258  uint8_t *buf = (uint8_t *)"Hi all!";
259  uint16_t buflen = strlen((char *)buf);
260  Packet *p[3];
261  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
262  p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
263  p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
264  if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
265  goto end;
266 
267  /* TCP w/seq=42 */
268  p[0]->tcph->th_seq = htonl(42);
269 
270  /* TCP w/seq=100 */
271  p[1]->tcph->th_seq = htonl(100);
272 
273  const char *sigs[2];
274  sigs[0]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:41; sid:1;)";
275  sigs[1]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:42; sid:2;)";
276 
277  uint32_t sid[2] = {1, 2};
278 
279  uint32_t results[3][2] = {
280  /* packet 0 match sid 1 but should not match sid 2 */
281  {0, 1},
282  /* packet 1 should not match */
283  {0, 0},
284  /* packet 2 should not match */
285  {0, 0} };
286 
287  result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 2);
288  UTHFreePackets(p, 3);
289 end:
290  return result;
291 }
292 
293 /**
294  * \internal
295  * \brief This function registers unit tests for DetectSeq
296  */
297 static void DetectSeqRegisterTests(void)
298 {
299  UtRegisterTest("DetectSeqSigTest01", DetectSeqSigTest01);
300  UtRegisterTest("DetectSeqSigTest02", DetectSeqSigTest02);
301 }
302 #endif /* UNITTESTS */
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1214
Packet_::proto
uint8_t proto
Definition: decode.h:436
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1213
DetectSeqData_::seq
uint32_t seq
Definition: detect-tcp-seq.h:31
SigMatchFree
void SigMatchFree(DetectEngineCtx *de_ctx, SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:250
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1201
SigTableElmt_::name
const char * name
Definition: detect.h:1211
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1147
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1347
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2056
results
struct DetectRfbSecresult_ results[]
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1111
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
PrefilterPacketHeaderCtx_::sigs_array
SigIntId * sigs_array
Definition: detect-engine-prefilter-common.h:41
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2093
detect-tcp-seq.h
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:337
PrefilterPacketHeaderCtx_::sigs_cnt
uint32_t sigs_cnt
Definition: detect-engine-prefilter-common.h:40
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1196
detect-engine-prefilter.h
util-unittest.h
util-unittest-helper.h
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1199
DetectSeqRegister
void DetectSeqRegister(void)
Registration function for ack: keyword.
Definition: detect-tcp-seq.c:53
PKT_IS_TCP
#define PKT_IS_TCP(p)
Definition: decode.h:259
DetectSeqData_
seq data
Definition: detect-tcp-seq.h:30
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:33
decode.h
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1010
PrefilterPacketHeaderValue::u32
uint32_t u32[4]
Definition: detect-engine-prefilter-common.h:24
detect.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:324
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
TRUE
#define TRUE
Definition: suricata-common.h:33
DETECT_SEQ
@ DETECT_SEQ
Definition: detect-engine-register.h:37
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:323
TCP_GET_SEQ
#define TCP_GET_SEQ(p)
Definition: decode-tcp.h:112
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1953
FALSE
#define FALSE
Definition: suricata-common.h:34
Signature_::flags
uint32_t flags
Definition: detect.h:529
Packet_
Definition: decode.h:414
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:597
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1179
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:522
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
SigMatch_::type
uint8_t type
Definition: detect.h:321
PrefilterPacketHeaderCtx_::v1
PrefilterPacketHeaderValue v1
Definition: detect-engine-prefilter-common.h:34
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:315
StringParseUint32
int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:313
SigTableElmt_::alias
const char * alias
Definition: detect.h:1212
suricata-common.h
Packet_::tcph
TCPHdr * tcph
Definition: decode.h:531
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perfom a generic check taking care of as maximum common unittest elemen...
Definition: util-unittest-helper.c:604
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, void(*Set)(PrefilterPacketHeaderValue *v, void *), bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
Definition: detect-engine-prefilter-common.c:407
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1198
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
SigMatch_
a single match condition for a signature
Definition: detect.h:320
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2048
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:21
detect-engine-prefilter-common.h
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
debug.h
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1203
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:468