suricata
detect-bypass.c
Go to the documentation of this file.
1 /* Copyright (C) 2016 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 Giuseppe Longo <glongo@stamus-networks.com>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "threads.h"
27 #include "app-layer.h"
28 #include "app-layer-parser.h"
29 #include "debug.h"
30 #include "decode.h"
31 
32 #include "detect.h"
33 #include "detect-parse.h"
34 
35 #include "detect-engine.h"
36 #include "detect-engine-mpm.h"
37 #include "detect-engine-state.h"
38 #include "detect-engine-sigorder.h"
39 #include "detect-bypass.h"
40 
41 #include "flow.h"
42 #include "flow-var.h"
43 #include "flow-util.h"
44 
45 #include "stream-tcp.h"
46 
47 #include "util-debug.h"
48 #include "util-spm-bm.h"
49 #include "util-unittest.h"
50 #include "util-unittest-helper.h"
51 #include "util-device.h"
52 
53 static int DetectBypassMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *,
54  const Signature *, const SigMatchCtx *);
55 static int DetectBypassSetup(DetectEngineCtx *, Signature *, const char *);
56 static void DetectBypassRegisterTests(void);
57 
58 /**
59  * \brief Registration function for keyword: bypass
60  */
62 {
63  sigmatch_table[DETECT_BYPASS].name = "bypass";
64  sigmatch_table[DETECT_BYPASS].desc = "call the bypass callback when the match of a sig is complete";
65  sigmatch_table[DETECT_BYPASS].url = DOC_URL DOC_VERSION "/rules/bypass-keyword.html";
66  sigmatch_table[DETECT_BYPASS].Match = DetectBypassMatch;
67  sigmatch_table[DETECT_BYPASS].Setup = DetectBypassSetup;
69  sigmatch_table[DETECT_BYPASS].RegisterTests = DetectBypassRegisterTests;
71 }
72 
73 static int DetectBypassSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
74 {
75  SigMatch *sm = NULL;
76 
77  if (s->flags & SIG_FLAG_FILESTORE) {
79  "bypass can't work with filestore keyword");
80  return -1;
81  }
82  s->flags |= SIG_FLAG_BYPASS;
83 
84  sm = SigMatchAlloc();
85  if (sm == NULL)
86  return -1;
87 
88  sm->type = DETECT_BYPASS;
89  sm->ctx = NULL;
91 
92  return 0;
93 }
94 
95 static int DetectBypassMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p,
96  const Signature *s, const SigMatchCtx *ctx)
97 {
99 
100  return 1;
101 }
102 
103 #ifdef UNITTESTS
104 #include "app-layer-htp.h"
105 
106 static int callback_var = 0;
107 
108 static int BypassCallback(Packet *p)
109 {
110  callback_var = 1;
111  return 1;
112 }
113 
114 static void ResetCallbackVar(void)
115 {
116  callback_var = 0;
117 }
118 
119 static int DetectBypassTestSig01(void)
120 {
121  TcpSession ssn;
122  Packet *p1 = NULL;
123  Packet *p2 = NULL;
124  ThreadVars th_v;
125  DetectEngineCtx *de_ctx = NULL;
126  DetectEngineThreadCtx *det_ctx = NULL;
127  HtpState *http_state = NULL;
128  Flow f;
129  uint8_t http_buf1[] =
130  "GET /index.html HTTP/1.0\r\n"
131  "Host: This is dummy message body\r\n"
132  "User-Agent: www.openinfosecfoundation.org\r\n"
133  "Content-Type: text/html\r\n"
134  "\r\n";
135  uint32_t http_len1 = sizeof(http_buf1) - 1;
136  uint8_t http_buf2[] =
137  "HTTP/1.0 200 ok\r\n"
138  "Content-Type: text/html\r\n"
139  "Content-Length: 7\r\n"
140  "\r\n"
141  "message";
142  uint32_t http_len2 = sizeof(http_buf2) - 1;
144  LiveDevice *livedev = SCMalloc(sizeof(LiveDevice));
145  FAIL_IF(livedev == NULL);
146 
147  memset(&th_v, 0, sizeof(th_v));
148  memset(&f, 0, sizeof(f));
149  memset(&ssn, 0, sizeof(ssn));
150 
151  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
152  FAIL_IF(p1 == NULL);
153  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
154  FAIL_IF(p2 == NULL);
155 
156  p1->BypassPacketsFlow = BypassCallback;
157  p2->BypassPacketsFlow = BypassCallback;
158 
159  FLOW_INITIALIZE(&f);
160  f.protoctx = (void *)&ssn;
161  f.proto = IPPROTO_TCP;
162  f.flags |= FLOW_IPV4;
163 
164  p1->flow = &f;
168  p1->livedev = livedev;
169  p2->flow = &f;
173  p2->livedev = livedev;
174  f.alproto = ALPROTO_HTTP;
175 
177 
178  de_ctx = DetectEngineCtxInit();
179  FAIL_IF(de_ctx == NULL);
180 
181  de_ctx->flags |= DE_QUIET;
182 
183  const char *sigs[3];
184  sigs[0] = "alert tcp any any -> any any (bypass; content:\"GET \"; sid:1;)";
185  sigs[1] = "alert http any any -> any any "
186  "(bypass; content:\"message\"; http_server_body; "
187  "sid:2;)";
188  sigs[2] = "alert http any any -> any any "
189  "(bypass; content:\"message\"; http_host; "
190  "sid:3;)";
191  FAIL_IF(UTHAppendSigs(de_ctx, sigs, 3) == 0);
192 
194  SCSigOrderSignatures(de_ctx);
196 
197  SigGroupBuild(de_ctx);
198  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
199 
200  FLOWLOCK_WRLOCK(&f);
201  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
202  STREAM_TOSERVER, http_buf1, http_len1);
203  FAIL_IF(r != 0);
204  FLOWLOCK_UNLOCK(&f);
205 
206  http_state = f.alstate;
207  FAIL_IF(http_state == NULL);
208 
209  /* do detect */
210  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
211 
212  FAIL_IF(PacketAlertCheck(p1, 1));
213 
214  FLOWLOCK_WRLOCK(&f);
215  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT,
216  http_buf2, http_len2);
217  FAIL_IF(r != 0);
218  FLOWLOCK_UNLOCK(&f);
219  /* do detect */
220  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
221 
222  FAIL_IF(!(PacketAlertCheck(p2, 2)));
223  FAIL_IF(!(PacketAlertCheck(p1, 3)));
224 
225  FAIL_IF(callback_var == 0);
226 
228  FLOW_DESTROY(&f);
229  UTHFreePacket(p1);
230  UTHFreePacket(p2);
231  ResetCallbackVar();
232  SCFree(livedev);
233  PASS;
234 }
235 #endif /* UNITTESTS */
236 
237 static void DetectBypassRegisterTests(void)
238 {
239 #ifdef UNITTESTS
240  UtRegisterTest("DetectBypassTestSig01", DetectBypassTestSig01);
241 #endif /* UNITTESTS */
242 }
#define SIG_FLAG_FILESTORE
Definition: detect.h:241
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
int(* BypassPacketsFlow)(struct Packet_ *)
Definition: decode.h:490
struct Flow_ * flow
Definition: decode.h:444
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int UTHAppendSigs(DetectEngineCtx *de_ctx, const char *sigs[], int numsigs)
UTHAppendSigs: Add sigs to the detection_engine checking for errors.
uint32_t flags
Definition: detect.h:493
uint8_t proto
Definition: flow.h:346
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1160
Signature container.
Definition: detect.h:492
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:319
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
void * protoctx
Definition: flow.h:398
main detection engine ctx
Definition: detect.h:720
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered...
void * alstate
Definition: flow.h:436
#define DE_QUIET
Definition: detect.h:298
#define str(s)
uint8_t flags
Definition: detect.h:721
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1151
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
uint8_t flowflags
Definition: decode.h:438
void PacketBypassCallback(Packet *p)
Definition: decode.c:400
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.
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
uint8_t type
Definition: detect.h:325
const char * desc
Definition: detect.h:1162
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:282
SigMatchCtx * ctx
Definition: detect.h:327
#define SCMalloc(a)
Definition: util-mem.h:174
#define SCFree(a)
Definition: util-mem.h:236
#define SIGMATCH_NOOPT
Definition: detect.h:1328
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1129
const char * url
Definition: detect.h:1163
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
void DetectBypassRegister(void)
Registration function for keyword: bypass.
Definition: detect-bypass.c:61
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define SIG_FLAG_BYPASS
Definition: detect.h:248
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:226
struct LiveDevice_ * livedev
Definition: decode.h:558
Per thread variable structure.
Definition: threadvars.h:57
#define FLOW_PKT_TOCLIENT
Definition: flow.h:194
AppProto alproto
application level protocol
Definition: flow.h:407
uint32_t flags
Definition: decode.h:442
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1154
Flow data structure.
Definition: flow.h:327
#define FLOW_IPV4
Definition: flow.h:93
uint32_t flags
Definition: flow.h:377
#define PKT_STREAM_EST
Definition: decode.h:1099
void(* RegisterTests)(void)
Definition: detect.h:1152
a single match condition for a signature
Definition: detect.h:324
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
DetectEngineCtx * DetectEngineCtxInit(void)