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 "decode.h"
28 #include "detect.h"
29 
30 #include "detect-parse.h"
31 #include "detect-engine.h"
34 #include "detect-engine-build.h"
35 #include "detect-engine-uint.h"
36 
37 #include "detect-tcp-seq.h"
38 
39 #include "util-byte.h"
40 #include "util-unittest.h"
41 #include "util-unittest-helper.h"
42 #include "util-debug.h"
43 
44 static int DetectSeqSetup(DetectEngineCtx *, Signature *, const char *);
45 static int DetectSeqMatch(DetectEngineThreadCtx *,
46  Packet *, const Signature *, const SigMatchCtx *);
47 #ifdef UNITTESTS
48 static void DetectSeqRegisterTests(void);
49 #endif
50 static void DetectSeqFree(DetectEngineCtx *, void *);
51 static int PrefilterSetupTcpSeq(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
52 static bool PrefilterTcpSeqIsPrefilterable(const Signature *s);
53 
55 {
56  sigmatch_table[DETECT_SEQ].name = "tcp.seq";
58  sigmatch_table[DETECT_SEQ].desc = "check for a specific TCP sequence number";
59  sigmatch_table[DETECT_SEQ].url = "/rules/header-keywords.html#seq";
60  sigmatch_table[DETECT_SEQ].Match = DetectSeqMatch;
61  sigmatch_table[DETECT_SEQ].Setup = DetectSeqSetup;
62  sigmatch_table[DETECT_SEQ].Free = DetectSeqFree;
64 #ifdef UNITTESTS
65  sigmatch_table[DETECT_SEQ].RegisterTests = DetectSeqRegisterTests;
66 #endif
67  sigmatch_table[DETECT_SEQ].SupportsPrefilter = PrefilterTcpSeqIsPrefilterable;
68  sigmatch_table[DETECT_SEQ].SetupPrefilter = PrefilterSetupTcpSeq;
69 }
70 
71 /**
72  * \internal
73  * \brief This function is used to match packets with a given Seq number
74  *
75  * \param t pointer to thread vars
76  * \param det_ctx pointer to the pattern matcher thread
77  * \param p pointer to the current packet
78  * \param m pointer to the sigmatch that we will cast into DetectSeqData
79  *
80  * \retval 0 no match
81  * \retval 1 match
82  */
83 static int DetectSeqMatch(DetectEngineThreadCtx *det_ctx,
84  Packet *p, const Signature *s, const SigMatchCtx *ctx)
85 {
86  const DetectU32Data *data = (const DetectU32Data *)ctx;
87 
89  /* This is only needed on TCP packets */
90  if (!(PacketIsTCP(p))) {
91  return 0;
92  }
93 
94  return DetectU32Match(TCP_GET_RAW_SEQ(PacketGetTCP(p)), data);
95 }
96 
97 /**
98  * \internal
99  * \brief this function is used to add the seq option into the signature
100  *
101  * \param de_ctx pointer to the Detection Engine Context
102  * \param s pointer to the Current Signature
103  * \param optstr pointer to the user provided options
104  *
105  * \retval 0 on Success
106  * \retval -1 on Failure
107  */
108 static int DetectSeqSetup (DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
109 {
110  DetectU32Data *data = SCDetectU32Parse(optstr);
111  if (data == NULL)
112  return -1;
113 
115  de_ctx, s, DETECT_SEQ, (SigMatchCtx *)data, DETECT_SM_LIST_MATCH) == NULL) {
116  DetectSeqFree(de_ctx, data);
117  return -1;
118  }
120  return 0;
121 }
122 
123 /**
124  * \internal
125  * \brief this function will free memory associated with seq option
126  *
127  * \param data pointer to seq configuration data
128  */
129 static void DetectSeqFree(DetectEngineCtx *de_ctx, void *ptr)
130 {
131  SCDetectU32Free(ptr);
132 }
133 
134 /* prefilter code */
135 
136 static void
137 PrefilterPacketSeqMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
138 {
139  const PrefilterPacketHeaderCtx *ctx = pectx;
140 
142  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
143  return;
144 
145  if (p->proto == IPPROTO_TCP && PacketIsTCP(p)) {
146  DetectU32Data du32;
147  du32.mode = ctx->v1.u8[0];
148  du32.arg1 = ctx->v1.u32[1];
149  du32.arg2 = ctx->v1.u32[2];
150  if (DetectU32Match(TCP_GET_RAW_SEQ(PacketGetTCP(p)), &du32)) {
151  SCLogDebug("packet matches TCP seq %u", ctx->v1.u32[0]);
152  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
153  }
154  }
155 }
156 
157 static int PrefilterSetupTcpSeq(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
158 {
160  PrefilterPacketU32Set, PrefilterPacketU32Compare, PrefilterPacketSeqMatch);
161 }
162 
163 static bool PrefilterTcpSeqIsPrefilterable(const Signature *s)
164 {
165  const SigMatch *sm;
166  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
167  switch (sm->type) {
168  case DETECT_SEQ:
169  return true;
170  }
171  }
172  return false;
173 }
174 
175 
176 #ifdef UNITTESTS
177 
178 /**
179  * \test DetectSeqSigTest01 tests parses
180  */
181 static int DetectSeqSigTest01(void)
182 {
183  int result = 0;
185  if (de_ctx == NULL)
186  goto end;
187 
188  /* These three are crammed in here as there is no Parse */
189  if (SigInit(de_ctx,
190  "alert tcp any any -> any any "
191  "(msg:\"Testing seq\";seq:foo;sid:1;)") != NULL)
192  {
193  printf("invalid seq accepted: ");
194  goto cleanup;
195  }
196  if (SigInit(de_ctx,
197  "alert tcp any any -> any any "
198  "(msg:\"Testing seq\";seq:9999999999;sid:1;)") != NULL)
199  {
200  printf("overflowing seq accepted: ");
201  goto cleanup;
202  }
203  if (SigInit(de_ctx,
204  "alert tcp any any -> any any "
205  "(msg:\"Testing seq\";seq:-100;sid:1;)") != NULL)
206  {
207  printf("negative seq accepted: ");
208  goto cleanup;
209  }
210  result = 1;
211 
212 cleanup:
213  if (de_ctx) {
217  }
218 end:
219  return result;
220 }
221 
222 /**
223  * \test DetectSeqSigTest02 tests seq keyword
224  */
225 static int DetectSeqSigTest02(void)
226 {
227  int result = 0;
228  uint8_t *buf = (uint8_t *)"Hi all!";
229  uint16_t buflen = strlen((char *)buf);
230  Packet *p[3];
231  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
232  p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
233  p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
234  if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
235  goto end;
236 
237  /* TCP w/seq=42 */
238  p[0]->l4.hdrs.tcph->th_seq = htonl(42);
239 
240  /* TCP w/seq=100 */
241  p[1]->l4.hdrs.tcph->th_seq = htonl(100);
242 
243  const char *sigs[2];
244  sigs[0]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:41; sid:1;)";
245  sigs[1]= "alert tcp any any -> any any (msg:\"Testing seq\"; seq:42; sid:2;)";
246 
247  uint32_t sid[2] = {1, 2};
248 
249  uint32_t results[3][2] = {
250  /* packet 0 match sid 1 but should not match sid 2 */
251  {0, 1},
252  /* packet 1 should not match */
253  {0, 0},
254  /* packet 2 should not match */
255  {0, 0} };
256 
257  result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 2);
258  UTHFreePackets(p, 3);
259 end:
260  return result;
261 }
262 
263 /**
264  * \internal
265  * \brief This function registers unit tests for DetectSeq
266  */
267 static void DetectSeqRegisterTests(void)
268 {
269  UtRegisterTest("DetectSeqSigTest01", DetectSeqSigTest01);
270  UtRegisterTest("DetectSeqSigTest02", DetectSeqSigTest02);
271 }
272 #endif /* UNITTESTS */
TCP_GET_RAW_SEQ
#define TCP_GET_RAW_SEQ(tcph)
Definition: decode-tcp.h:80
util-byte.h
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1461
Packet_::proto
uint8_t proto
Definition: decode.h:523
detect-engine.h
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:316
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:642
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:1460
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1445
SigTableElmt_::name
const char * name
Definition: detect.h:1458
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1323
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1628
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1449
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
PrefilterPacketU32Set
void PrefilterPacketU32Set(PrefilterPacketHeaderValue *v, void *smctx)
Definition: detect-engine-uint.c:51
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1348
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:933
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2634
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:365
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:56
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1440
detect-engine-prefilter.h
util-unittest.h
util-unittest-helper.h
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1443
SIGMATCH_INFO_UINT32
#define SIGMATCH_INFO_UINT32
Definition: detect.h:1691
DetectSeqRegister
void DetectSeqRegister(void)
Registration function for ack: keyword.
Definition: detect-tcp-seq.c:54
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:35
decode.h
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1245
TCPHdr_::th_seq
uint32_t th_seq
Definition: decode-tcp.h:152
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:388
detect.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:360
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3098
DETECT_SEQ
@ DETECT_SEQ
Definition: detect-engine-register.h:37
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2265
Signature_::flags
uint32_t flags
Definition: detect.h:669
Packet_
Definition: decode.h:501
detect-engine-build.h
Packet_::l4
struct PacketL4 l4
Definition: decode.h:601
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, SignatureMask mask, 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:470
PrefilterPacketU32Compare
bool PrefilterPacketU32Compare(PrefilterPacketHeaderValue v, void *smctx)
Definition: detect-engine-uint.c:60
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1420
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:351
SigTableElmt_::alias
const char * alias
Definition: detect.h:1459
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:357
DetectU32Data
DetectUintData_u32 DetectU32Data
Definition: detect-engine-uint.h:41
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perform a generic check taking care of as maximum common unittest eleme...
Definition: util-unittest-helper.c:581
PacketL4::L4Hdrs::tcph
TCPHdr * tcph
Definition: decode.h:469
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1442
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
SigMatch_
a single match condition for a signature
Definition: detect.h:356
PacketL4::hdrs
union PacketL4::L4Hdrs hdrs
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2595
detect-engine-prefilter-common.h
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1447
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254
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:456