1 /* Copyright (C) 2007-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  * \ingroup httplayer
20  *
21  * @{
22  */
23 
24 
25 /** \file
26  *
27  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
28  * \author Victor Julien <victor@inliniac.net>
29  *
30  * \brief Handle HTTP request body match corresponding to http_client_body
31  * keyword.
32  *
33  */
34 
35 #include "../suricata-common.h"
36 #include "../suricata.h"
37 #include "../decode.h"
38 
39 #include "detect.h"
40 #include "detect-engine.h"
41 #include "detect-engine-mpm.h"
42 #include "detect-parse.h"
43 #include "detect-engine-state.h"
44 #include "detect-engine-content-inspection.h"
45 #include "detect-engine-prefilter.h"
46 #include "detect-isdataat.h"
47 #include "stream-tcp-reassemble.h"
48 
49 
50 #include "flow-util.h"
51 #include "util-debug.h"
52 #include "util-print.h"
53 #include "flow.h"
54 
55 #include "app-layer-parser.h"
56 
57 #include "stream-tcp.h"
58 
59 #include "util-unittest.h"
60 #include "util-unittest-helper.h"
61 #include "app-layer.h"
62 #include "app-layer-htp.h"
63 #include "app-layer-protos.h"
64 
65 #include "conf.h"
66 #include "conf-yaml-loader.h"
67 
68 #include "util-validate.h"
69 
70 #ifdef UNITTESTS
71 
72 /**
73  * \test Test parser accepting valid rules and rejecting invalid rules
74  */
DetectHttpClientBodyParserTest01(void)75 static int DetectHttpClientBodyParserTest01(void)
76 {
77     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; http_client_body; sid:1;)", true));
78     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; nocase; http_client_body; sid:1;)", true));
79     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; endswith; http_client_body; sid:1;)", true));
80     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; http_client_body; sid:1;)", true));
81     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; endswith; http_client_body; sid:1;)", true));
82 
83     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; rawbytes; http_client_body; sid:1;)", false));
84     FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http_client_body; sid:1;)", false));
85     FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; content:\"abc\"; http_client_body; sid:1;)", false));
86     PASS;
87 }
88 
89 /**
90  * \test Test parser accepting valid rules and rejecting invalid rules
91  */
DetectHttpClientBodyParserTest02(void)92 static int DetectHttpClientBodyParserTest02(void)
93 {
94     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; sid:1;)", true));
95     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; nocase; sid:1;)", true));
96     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; endswith; sid:1;)", true));
97     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; startswith; sid:1;)", true));
98     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; startswith; endswith; sid:1;)", true));
99     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; bsize:10; sid:1;)", true));
100 
101     FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; rawbytes; sid:1;)", false));
102     FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http.request_body; sid:1;)", false));
103     FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; http.request_body; content:\"abc\"; sid:1;)", false));
104     PASS;
105 }
106 
107 struct TestSteps {
108     const uint8_t *input;
109     size_t input_size;      /**< if 0 strlen will be used */
110     int direction;          /**< STREAM_TOSERVER, STREAM_TOCLIENT */
111     int expect;
112 };
113 
RunTest(struct TestSteps * steps,const char * sig,const char * yaml)114 static int RunTest (struct TestSteps *steps, const char *sig, const char *yaml)
115 {
116     TcpSession ssn;
117     Flow f;
118     ThreadVars th_v;
119     DetectEngineThreadCtx *det_ctx = NULL;
120     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
121     FAIL_IF_NULL(alp_tctx);
122 
123     memset(&th_v, 0, sizeof(th_v));
124     memset(&f, 0, sizeof(f));
125     memset(&ssn, 0, sizeof(ssn));
126 
127     if (yaml) {
128         ConfCreateContextBackup();
129         ConfInit();
130         HtpConfigCreateBackup();
131 
132         ConfYamlLoadString(yaml, strlen(yaml));
133         HTPConfigure();
134     }
135 
136     StreamTcpInitConfig(TRUE);
137 
138     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
139     FAIL_IF_NULL(de_ctx);
140     de_ctx->flags |= DE_QUIET;
141 
142     FLOW_INITIALIZE(&f);
143     f.protoctx = (void *)&ssn;
144     f.proto = IPPROTO_TCP;
145     f.flags |= FLOW_IPV4;
146     f.alproto = ALPROTO_HTTP;
147 
148     SCLogDebug("sig %s", sig);
149     Signature *s = DetectEngineAppendSig(de_ctx, (char *)sig);
150     FAIL_IF_NULL(s);
151 
152     SigGroupBuild(de_ctx);
153     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
154     FAIL_IF_NULL(det_ctx);
155 
156     struct TestSteps *b = steps;
157     int i = 0;
158     while (b->input != NULL) {
159         SCLogDebug("chunk %p %d", b, i);
160         Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
161         FAIL_IF_NULL(p);
162         p->flow = &f;
163         p->flowflags = (b->direction == STREAM_TOSERVER) ? FLOW_PKT_TOSERVER : FLOW_PKT_TOCLIENT;
164         p->flowflags |= FLOW_PKT_ESTABLISHED;
165         p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
166 
167         int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
168                                     b->direction, (uint8_t *)b->input,
169                                     b->input_size ? b->input_size : strlen((const char *)b->input));
170         FAIL_IF_NOT(r == 0);
171 
172         /* do detect */
173         SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
174 
175         int match = PacketAlertCheck(p, 1);
176         FAIL_IF_NOT (b->expect == match);
177 
178         UTHFreePackets(&p, 1);
179         b++;
180         i++;
181     }
182 
183     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
184     AppLayerParserThreadCtxFree(alp_tctx);
185     DetectEngineCtxFree(de_ctx);
186 
187     StreamTcpFreeConfig(TRUE);
188     FLOW_DESTROY(&f);
189 
190     if (yaml) {
191         HtpConfigRestoreBackup();
192         ConfRestoreContextBackup();
193     }
194     PASS;
195 }
196 
DetectEngineHttpClientBodyTest01(void)197 static int DetectEngineHttpClientBodyTest01(void)
198 {
199     struct TestSteps steps[] = {
200         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
201             "Host: www.openinfosecfoundation.org\r\n"
202             "Content-Type: text/html\r\n"
203             "Content-Length: 46\r\n"
204             "\r\n"
205             "This is dummy body1",
206             0, STREAM_TOSERVER, 0 },
207         {   (const uint8_t *)"This is dummy message body2",
208             0, STREAM_TOSERVER, 1 },
209         {   NULL, 0, 0, 0 },
210     };
211 
212     const char *sig = "alert http any any -> any any (content:\"body1This\"; http_client_body; sid:1;)";
213     return RunTest(steps, sig, NULL);
214 }
215 
DetectEngineHttpClientBodyTest02(void)216 static int DetectEngineHttpClientBodyTest02(void)
217 {
218     struct TestSteps steps[] = {
219         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
220             "Host: www.openinfosecfoundation.org\r\n"
221             "Content-Type: text/html\r\n"
222             "Content-Length: 19\r\n"
223             "\r\n"
224             "This is dummy body1",
225             0, STREAM_TOSERVER, 1 },
226         {   NULL, 0, 0, 0 },
227     };
228 
229     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; offset:5; sid:1;)";
230     return RunTest(steps, sig, NULL);
231 }
232 
DetectEngineHttpClientBodyTest03(void)233 static int DetectEngineHttpClientBodyTest03(void)
234 {
235     struct TestSteps steps[] = {
236         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
237             "Host: www.openinfosecfoundation.org\r\n"
238             "Content-Type: text/html\r\n"
239             "Content-Length: 46\r\n"
240             "\r\n"
241             "This is dummy body1",
242             0, STREAM_TOSERVER, 0 },
243         {   (const uint8_t *)"This is dummy message body2",
244             0, STREAM_TOSERVER, 0 },
245         {   NULL, 0, 0, 0 },
246     };
247 
248     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; offset:16; sid:1;)";
249     return RunTest(steps, sig, NULL);
250 }
251 
DetectEngineHttpClientBodyTest04(void)252 static int DetectEngineHttpClientBodyTest04(void)
253 {
254     struct TestSteps steps[] = {
255         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
256             "Host: www.openinfosecfoundation.org\r\n"
257             "Content-Type: text/html\r\n"
258             "Content-Length: 46\r\n"
259             "\r\n"
260             "This is dummy body1",
261             0, STREAM_TOSERVER, 0 },
262         {   (const uint8_t *)"This is dummy message body2",
263             0, STREAM_TOSERVER, 1 },
264         {   NULL, 0, 0, 0 },
265     };
266 
267     const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; offset:16; sid:1;)";
268     return RunTest(steps, sig, NULL);
269 }
270 
DetectEngineHttpClientBodyTest05(void)271 static int DetectEngineHttpClientBodyTest05(void)
272 {
273     struct TestSteps steps[] = {
274         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
275             "Host: www.openinfosecfoundation.org\r\n"
276             "Content-Type: text/html\r\n"
277             "Content-Length: 46\r\n"
278             "\r\n"
279             "This is dummy body1",
280             0, STREAM_TOSERVER, 0 },
281         {   (const uint8_t *)"This is dummy message body2",
282             0, STREAM_TOSERVER, 1 },
283         {   NULL, 0, 0, 0 },
284     };
285 
286     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; depth:25; sid:1;)";
287     return RunTest(steps, sig, NULL);
288 }
289 
DetectEngineHttpClientBodyTest06(void)290 static int DetectEngineHttpClientBodyTest06(void)
291 {
292     struct TestSteps steps[] = {
293         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
294             "Host: www.openinfosecfoundation.org\r\n"
295             "Content-Type: text/html\r\n"
296             "Content-Length: 46\r\n"
297             "\r\n"
298             "This is dummy body1",
299             0, STREAM_TOSERVER, 0 },
300         {   (const uint8_t *)"This is dummy message body2",
301             0, STREAM_TOSERVER, 0 },
302         {   NULL, 0, 0, 0 },
303     };
304 
305     const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; depth:25; sid:1;)";
306     return RunTest(steps, sig, NULL);
307 }
308 
DetectEngineHttpClientBodyTest07(void)309 static int DetectEngineHttpClientBodyTest07(void)
310 {
311     struct TestSteps steps[] = {
312         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
313             "Host: www.openinfosecfoundation.org\r\n"
314             "Content-Type: text/html\r\n"
315             "Content-Length: 46\r\n"
316             "\r\n"
317             "This is dummy body1",
318             0, STREAM_TOSERVER, 0 },
319         {   (const uint8_t *)"This is dummy message body2",
320             0, STREAM_TOSERVER, 1 },
321         {   NULL, 0, 0, 0 },
322     };
323 
324     const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; depth:15; sid:1;)";
325     return RunTest(steps, sig, NULL);
326 }
327 
DetectEngineHttpClientBodyTest08(void)328 static int DetectEngineHttpClientBodyTest08(void)
329 {
330     struct TestSteps steps[] = {
331         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
332             "Host: www.openinfosecfoundation.org\r\n"
333             "Content-Type: text/html\r\n"
334             "Content-Length: 46\r\n"
335             "\r\n"
336             "This is dummy body1",
337             0, STREAM_TOSERVER, 0 },
338         {   (const uint8_t *)"This is dummy message body2",
339             0, STREAM_TOSERVER, 1 },
340         {   NULL, 0, 0, 0 },
341     };
342 
343     const char *sig = "alert http any any -> any any (content:\"This is dummy body1This is dummy message body2\"; http_client_body; sid:1;)";
344     return RunTest(steps, sig, NULL);
345 }
346 
DetectEngineHttpClientBodyTest09(void)347 static int DetectEngineHttpClientBodyTest09(void)
348 {
349     struct TestSteps steps[] = {
350         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
351             "Host: www.openinfosecfoundation.org\r\n"
352             "Content-Type: text/html\r\n"
353             "Content-Length: 46\r\n"
354             "\r\n"
355             "This is dummy body1",
356             0, STREAM_TOSERVER, 0 },
357         {   (const uint8_t *)"This is dummy message body2",
358             0, STREAM_TOSERVER, 1 },
359         {   NULL, 0, 0, 0 },
360     };
361 
362     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"This\"; http_client_body; within:5; sid:1;)";
363     return RunTest(steps, sig, NULL);
364 }
365 
DetectEngineHttpClientBodyTest10(void)366 static int DetectEngineHttpClientBodyTest10(void)
367 {
368     struct TestSteps steps[] = {
369         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
370             "Host: www.openinfosecfoundation.org\r\n"
371             "Content-Type: text/html\r\n"
372             "Content-Length: 46\r\n"
373             "\r\n"
374             "This is dummy body1",
375             0, STREAM_TOSERVER, 0 },
376         {   (const uint8_t *)"This is dummy message body2",
377             0, STREAM_TOSERVER, 1 },
378         {   NULL, 0, 0, 0 },
379     };
380 
381     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"boom\"; http_client_body; within:5; sid:1;)";
382     return RunTest(steps, sig, NULL);
383 }
384 
DetectEngineHttpClientBodyTest11(void)385 static int DetectEngineHttpClientBodyTest11(void)
386 {
387     struct TestSteps steps[] = {
388         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
389             "Host: www.openinfosecfoundation.org\r\n"
390             "Content-Type: text/html\r\n"
391             "Content-Length: 46\r\n"
392             "\r\n"
393             "This is dummy body1",
394             0, STREAM_TOSERVER, 0 },
395         {   (const uint8_t *)"This is dummy message body2",
396             0, STREAM_TOSERVER, 0 },
397         {   NULL, 0, 0, 0 },
398     };
399 
400     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"boom\"; http_client_body; within:5; sid:1;)";
401     return RunTest(steps, sig, NULL);
402 }
403 
DetectEngineHttpClientBodyTest12(void)404 static int DetectEngineHttpClientBodyTest12(void)
405 {
406     struct TestSteps steps[] = {
407         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
408             "Host: www.openinfosecfoundation.org\r\n"
409             "Content-Type: text/html\r\n"
410             "Content-Length: 46\r\n"
411             "\r\n"
412             "This is dummy body1",
413             0, STREAM_TOSERVER, 0 },
414         {   (const uint8_t *)"This is dummy message body2",
415             0, STREAM_TOSERVER, 0 },
416         {   NULL, 0, 0, 0 },
417     };
418 
419     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"This\"; http_client_body; within:5; sid:1;)";
420     return RunTest(steps, sig, NULL);
421 }
422 
DetectEngineHttpClientBodyTest13(void)423 static int DetectEngineHttpClientBodyTest13(void)
424 {
425     struct TestSteps steps[] = {
426         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
427             "Host: www.openinfosecfoundation.org\r\n"
428             "Content-Type: text/html\r\n"
429             "Content-Length: 46\r\n"
430             "\r\n"
431             "This is dummy body1",
432             0, STREAM_TOSERVER, 0 },
433         {   (const uint8_t *)"This is dummy message body2",
434             0, STREAM_TOSERVER, 1 },
435         {   NULL, 0, 0, 0 },
436     };
437 
438     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"dummy\"; http_client_body; distance:5; sid:1;)";
439     return RunTest(steps, sig, NULL);
440 }
441 
DetectEngineHttpClientBodyTest14(void)442 static int DetectEngineHttpClientBodyTest14(void)
443 {
444     struct TestSteps steps[] = {
445         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
446             "Host: www.openinfosecfoundation.org\r\n"
447             "Content-Type: text/html\r\n"
448             "Content-Length: 46\r\n"
449             "\r\n"
450             "This is dummy body1",
451             0, STREAM_TOSERVER, 0 },
452         {   (const uint8_t *)"This is dummy message body2",
453             0, STREAM_TOSERVER, 1 },
454         {   NULL, 0, 0, 0 },
455     };
456 
457     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"dummy\"; http_client_body; distance:10; sid:1;)";
458     return RunTest(steps, sig, NULL);
459 }
460 
DetectEngineHttpClientBodyTest15(void)461 static int DetectEngineHttpClientBodyTest15(void)
462 {
463     struct TestSteps steps[] = {
464         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
465             "Host: www.openinfosecfoundation.org\r\n"
466             "Content-Type: text/html\r\n"
467             "Content-Length: 46\r\n"
468             "\r\n"
469             "This is dummy body1",
470             0, STREAM_TOSERVER, 0 },
471         {   (const uint8_t *)"This is dummy message body2",
472             0, STREAM_TOSERVER, 0 },
473         {   NULL, 0, 0, 0 },
474     };
475 
476     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"dummy\"; http_client_body; distance:10; sid:1;)";
477     return RunTest(steps, sig, NULL);
478 }
479 
DetectEngineHttpClientBodyTest16(void)480 static int DetectEngineHttpClientBodyTest16(void)
481 {
482     struct TestSteps steps[] = {
483         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
484             "Host: www.openinfosecfoundation.org\r\n"
485             "Content-Type: text/html\r\n"
486             "Content-Length: 46\r\n"
487             "\r\n"
488             "This is dummy body1",
489             0, STREAM_TOSERVER, 0 },
490         {   (const uint8_t *)"This is dummy message body2",
491             0, STREAM_TOSERVER, 0 },
492         {   NULL, 0, 0, 0 },
493     };
494 
495     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"dummy\"; http_client_body; distance:5; sid:1;)";
496     return RunTest(steps, sig, NULL);
497 }
498 
DetectEngineHttpClientBodyTest17(void)499 static int DetectEngineHttpClientBodyTest17(void)
500 {
501     struct TestSteps steps[] = {
502         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
503             "Host: www.openinfosecfoundation.org\r\n"
504             "Content-Type: text/html\r\n"
505             "Content-Length: 19\r\n"
506             "\r\n"
507             "This is dummy body1",
508             0, STREAM_TOSERVER, 0 },
509         {   NULL, 0, 0, 0 },
510     };
511 
512     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"bambu\"; http_client_body; sid:1;)";
513     return RunTest(steps, sig, NULL);
514 }
515 
DetectEngineHttpClientBodyTest18(void)516 static int DetectEngineHttpClientBodyTest18(void)
517 {
518     struct TestSteps steps[] = {
519         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
520             "Host: www.openinfosecfoundation.org\r\n"
521             "Content-Type: text/html\r\n"
522             "Content-Length: 19\r\n"
523             "\r\n"
524             "This is dummy body1",
525             0, STREAM_TOSERVER, 0 },
526         {   NULL, 0, 0, 0 },
527     };
528 
529     const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"bambu\"; http_client_body; fast_pattern; sid:1;)";
530     return RunTest(steps, sig, NULL);
531 }
532 
DetectEngineHttpClientBodyTest19(void)533 static int DetectEngineHttpClientBodyTest19(void)
534 {
535     struct TestSteps steps[] = {
536         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
537             "Host: www.openinfosecfoundation.org\r\n"
538             "Content-Type: text/html\r\n"
539             "Content-Length: 19\r\n"
540             "\r\n"
541             "This is dummy body1",
542             0, STREAM_TOSERVER, 0 },
543         {   NULL, 0, 0, 0 },
544     };
545 
546     const char *sig = "alert http any any -> any any (content:\"bambu\"; http_client_body; content:\"is\"; http_client_body; sid:1;)";
547     return RunTest(steps, sig, NULL);
548 }
549 
DetectEngineHttpClientBodyTest20(void)550 static int DetectEngineHttpClientBodyTest20(void)
551 {
552     struct TestSteps steps[] = {
553         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
554             "Host: www.openinfosecfoundation.org\r\n"
555             "Content-Type: text/html\r\n"
556             "Content-Length: 19\r\n"
557             "\r\n"
558             "This is dummy body1",
559             0, STREAM_TOSERVER, 1 },
560         {   NULL, 0, 0, 0 },
561     };
562 
563     const char *sig = "alert http any any -> any any (content:\"is\"; http_client_body; fast_pattern; sid:1;)";
564     return RunTest(steps, sig, NULL);
565 }
566 
DetectEngineHttpClientBodyTest21(void)567 static int DetectEngineHttpClientBodyTest21(void)
568 {
569     struct TestSteps steps[] = {
570         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
571             "Host: www.openinfosecfoundation.org\r\n"
572             "Content-Type: text/html\r\n"
573             "Content-Length: 46\r\n"
574             "\r\n"
575             "This is dummy body1",
576             0, STREAM_TOSERVER, 0 },
577         {   (const uint8_t *)"This is dummy message body2",
578             0, STREAM_TOSERVER, 1 },
579         {   NULL, 0, 0, 0 },
580     };
581 
582     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; http_client_body; within:7; sid:1;)";
583     return RunTest(steps, sig, NULL);
584 }
585 
DetectEngineHttpClientBodyTest22(void)586 static int DetectEngineHttpClientBodyTest22(void)
587 {
588     struct TestSteps steps[] = {
589         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
590             "Host: www.openinfosecfoundation.org\r\n"
591             "Content-Type: text/html\r\n"
592             "Content-Length: 46\r\n"
593             "\r\n"
594             "This is dummy body1",
595             0, STREAM_TOSERVER, 0 },
596         {   (const uint8_t *)"This is dummy message body2",
597             0, STREAM_TOSERVER, 1 },
598         {   NULL, 0, 0, 0 },
599     };
600 
601     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; within:7; http_client_body; sid:1;)";
602     return RunTest(steps, sig, NULL);
603 }
604 
DetectEngineHttpClientBodyTest23(void)605 static int DetectEngineHttpClientBodyTest23(void)
606 {
607     struct TestSteps steps[] = {
608         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
609             "Host: www.openinfosecfoundation.org\r\n"
610             "Content-Type: text/html\r\n"
611             "Content-Length: 46\r\n"
612             "\r\n"
613             "This is dummy body1",
614             0, STREAM_TOSERVER, 0 },
615         {   (const uint8_t *)"This is dummy message body2",
616             0, STREAM_TOSERVER, 0 },
617         {   NULL, 0, 0, 0 },
618     };
619 
620     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; distance:3; http_client_body; sid:1;)";
621     return RunTest(steps, sig, NULL);
622 }
623 
DetectEngineHttpClientBodyTest24(void)624 static int DetectEngineHttpClientBodyTest24(void)
625 {
626     struct TestSteps steps[] = {
627         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
628             "Host: www.openinfosecfoundation.org\r\n"
629             "Content-Type: text/html\r\n"
630             "Content-Length: 46\r\n"
631             "\r\n"
632             "This is dummy body1",
633             0, STREAM_TOSERVER, 0 },
634         {   (const uint8_t *)"This is dummy message body2",
635             0, STREAM_TOSERVER, 1 },
636         {   NULL, 0, 0, 0 },
637     };
638 
639     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; distance:13; http_client_body; sid:1;)";
640     return RunTest(steps, sig, NULL);
641 }
642 
DetectEngineHttpClientBodyTest25(void)643 static int DetectEngineHttpClientBodyTest25(void)
644 {
645     struct TestSteps steps[] = {
646         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
647             "Host: www.openinfosecfoundation.org\r\n"
648             "Content-Type: text/html\r\n"
649             "Content-Length: 46\r\n"
650             "\r\n"
651             "This is dummy body1",
652             0, STREAM_TOSERVER, 0 },
653         {   (const uint8_t *)"This is dummy message body2",
654             0, STREAM_TOSERVER, 1 },
655         {   NULL, 0, 0, 0 },
656     };
657 
658     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; within:15; http_client_body; sid:1;)";
659     return RunTest(steps, sig, NULL);
660 }
661 
DetectEngineHttpClientBodyTest26(void)662 static int DetectEngineHttpClientBodyTest26(void)
663 {
664     struct TestSteps steps[] = {
665         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
666             "Host: www.openinfosecfoundation.org\r\n"
667             "Content-Type: text/html\r\n"
668             "Content-Length: 46\r\n"
669             "\r\n"
670             "This is dummy body1",
671             0, STREAM_TOSERVER, 0 },
672         {   (const uint8_t *)"This is dummy message body2",
673             0, STREAM_TOSERVER, 0 },
674         {   NULL, 0, 0, 0 },
675     };
676 
677     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; within:10; http_client_body; sid:1;)";
678     return RunTest(steps, sig, NULL);
679 }
680 
DetectEngineHttpClientBodyTest27(void)681 static int DetectEngineHttpClientBodyTest27(void)
682 {
683     struct TestSteps steps[] = {
684         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
685             "Host: www.openinfosecfoundation.org\r\n"
686             "Content-Type: text/html\r\n"
687             "Content-Length: 46\r\n"
688             "\r\n"
689             "This is dummy body1",
690             0, STREAM_TOSERVER, 0 },
691         {   (const uint8_t *)"This is dummy message body2",
692             0, STREAM_TOSERVER, 1 },
693         {   NULL, 0, 0, 0 },
694     };
695 
696     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; distance:8; http_client_body; sid:1;)";
697     return RunTest(steps, sig, NULL);
698 }
699 
DetectEngineHttpClientBodyTest28(void)700 static int DetectEngineHttpClientBodyTest28(void)
701 {
702     struct TestSteps steps[] = {
703         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
704             "Host: www.openinfosecfoundation.org\r\n"
705             "Content-Type: text/html\r\n"
706             "Content-Length: 46\r\n"
707             "\r\n"
708             "This is dummy body1",
709             0, STREAM_TOSERVER, 0 },
710         {   (const uint8_t *)"This is dummy message body2",
711             0, STREAM_TOSERVER, 0 },
712         {   NULL, 0, 0, 0 },
713     };
714 
715     const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; distance:14; http_client_body; sid:1;)";
716     return RunTest(steps, sig, NULL);
717 }
718 
DetectEngineHttpClientBodyTest29(void)719 static int DetectEngineHttpClientBodyTest29(void)
720 {
721     const char *request_buffer = "GET /one HTTP/1.0\r\n"
722                                  "Host: localhost\r\n\r\n";
723 #define TOTAL_REQUESTS 45
724     uint8_t *http_buf = SCMalloc(TOTAL_REQUESTS * strlen(request_buffer));
725     if (unlikely(http_buf == NULL))
726         return 0;
727     for (int i = 0; i < TOTAL_REQUESTS; i++) {
728         memcpy(http_buf + i * strlen(request_buffer), request_buffer,
729                strlen(request_buffer));
730     }
731     uint32_t http_buf_len = TOTAL_REQUESTS * strlen(request_buffer);
732 #undef TOTAL_REQUESTS
733 
734     struct TestSteps steps[] = {
735         {   (const uint8_t *)http_buf,
736             (size_t)http_buf_len, STREAM_TOSERVER, 0 },
737 
738         {   (const uint8_t *)"HTTP/1.0 200 ok\r\n"
739             "Content-Type: text/html\r\n"
740             "Content-Length: 5\r\n"
741             "\r\n"
742             "dummy",
743             0, STREAM_TOCLIENT, 0 },
744 
745         {   NULL, 0, 0, 0 },
746     };
747 
748     const char *sig = "alert http any any -> any any (content:\"dummyone\"; fast_pattern:0,3; http_server_body; sid:1;)";
749     int result = RunTest(steps, sig, NULL);
750     SCFree(http_buf);
751     return result;
752 }
753 
DetectEngineHttpClientBodyTest30(void)754 static int DetectEngineHttpClientBodyTest30(void)
755 {
756     const char yaml[] = "\
757 %YAML 1.1\n\
758 ---\n\
759 libhtp:\n\
760 \n\
761   default-config:\n\
762     personality: IDS\n\
763     request-body-limit: 0\n\
764     response-body-limit: 0\n\
765 \n\
766     request-body-inspect-window: 0\n\
767     response-body-inspect-window: 0\n\
768     request-body-minimal-inspect-size: 0\n\
769     response-body-minimal-inspect-size: 0\n\
770 ";
771     struct TestSteps steps[] = {
772         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
773             "Host: www.openinfosecfoundation.org\r\n"
774             "Content-Type: text/html\r\n"
775             "Content-Length: 46\r\n"
776             "\r\n"
777             "This is dummy body1",
778             0, STREAM_TOSERVER, 0 },
779         {   (const uint8_t *)"This is dummy message body2",
780             0, STREAM_TOSERVER, 0 },
781         {   NULL, 0, 0, 0 },
782     };
783 
784     const char *sig = "alert http any any -> any any (content:\"bags\"; within:4; http_client_body; sid:1;)";
785     return RunTest(steps, sig, yaml);
786 }
787 
DetectEngineHttpClientBodyTest31(void)788 static int DetectEngineHttpClientBodyTest31(void)
789 {
790     const char yaml[] = "\
791 %YAML 1.1\n\
792 ---\n\
793 libhtp:\n\
794 \n\
795   default-config:\n\
796     personality: IDS\n\
797     request-body-limit: 0\n\
798     response-body-limit: 0\n\
799 \n\
800     request-body-inspect-window: 0\n\
801     response-body-inspect-window: 0\n\
802     request-body-minimal-inspect-size: 0\n\
803     response-body-minimal-inspect-size: 0\n\
804 ";
805 
806     struct TestSteps steps[] = {
807         {   (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
808             "Host: www.openinfosecfoundation.org\r\n"
809             "Content-Type: text/html\r\n"
810             "Content-Length: 46\r\n"
811             "\r\n"
812             "This is dummy body1",
813             0, STREAM_TOSERVER, 0 },
814         {   (const uint8_t *)"This is dummy message body2",
815             0, STREAM_TOSERVER, 0 },
816         {   NULL, 0, 0, 0 },
817     };
818 
819     const char *sig = "alert http any any -> any any (content:\"bags\"; depth:4; http_client_body; sid:1;)";
820     return RunTest(steps, sig, yaml);
821 }
822 
823 /**
824  * \test Test that a signature containting a http_client_body is correctly parsed
825  *       and the keyword is registered.
826  */
DetectHttpClientBodyTest01(void)827 static int DetectHttpClientBodyTest01(void)
828 {
829     DetectEngineCtx *de_ctx = NULL;
830     int result = 0;
831     SigMatch *sm = NULL;
832 
833     de_ctx = DetectEngineCtxInit();
834     if (de_ctx == NULL)
835         goto end;
836 
837     de_ctx->flags |= DE_QUIET;
838     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
839                                "(msg:\"Testing http_client_body\"; "
840                                "content:\"one\"; http_client_body; sid:1;)");
841     if (de_ctx->sig_list != NULL) {
842         result = 1;
843     } else {
844         goto end;
845     }
846 
847     sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_MATCH];
848     if (sm != NULL) {
849         result &= (sm->type == DETECT_CONTENT);
850         result &= (sm->next == NULL);
851     }
852 
853  end:
854     DetectEngineCtxFree(de_ctx);
855 
856     return result;
857 }
858 
859 /**
860  * \test Test that a signature containing an valid http_client_body entry is
861  *       parsed.
862  */
DetectHttpClientBodyTest02(void)863 static int DetectHttpClientBodyTest02(void)
864 {
865     DetectEngineCtx *de_ctx = NULL;
866     int result = 0;
867 
868     de_ctx = DetectEngineCtxInit();
869     if (de_ctx == NULL)
870         goto end;
871 
872     de_ctx->flags |= DE_QUIET;
873     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
874                                "(msg:\"Testing http_client_body\"; "
875                                "content:\"one\"; http_client_body:; sid:1;)");
876     if (de_ctx->sig_list != NULL)
877         result = 1;
878 
879  end:
880     DetectEngineCtxFree(de_ctx);
881 
882     return result;
883 }
884 
885 /**
886  * \test Test that an invalid signature containing no content but a http_client_body
887  *       is invalidated.
888  */
DetectHttpClientBodyTest03(void)889 static int DetectHttpClientBodyTest03(void)
890 {
891     DetectEngineCtx *de_ctx = NULL;
892     int result = 0;
893 
894     de_ctx = DetectEngineCtxInit();
895     if (de_ctx == NULL)
896         goto end;
897 
898     de_ctx->flags |= DE_QUIET;
899     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
900                                "(msg:\"Testing http_client_body\"; "
901                                "http_client_body; sid:1;)");
902     if (de_ctx->sig_list == NULL)
903         result = 1;
904 
905  end:
906     DetectEngineCtxFree(de_ctx);
907 
908     return result;
909 }
910 
911 /**
912  * \test Test that an invalid signature containing a rawbytes along with a
913  *       http_client_body is invalidated.
914  */
DetectHttpClientBodyTest04(void)915 static int DetectHttpClientBodyTest04(void)
916 {
917     DetectEngineCtx *de_ctx = NULL;
918     int result = 0;
919 
920     de_ctx = DetectEngineCtxInit();
921     if (de_ctx == NULL)
922         goto end;
923 
924     de_ctx->flags |= DE_QUIET;
925     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
926                                "(msg:\"Testing http_client_body\"; "
927                                "content:\"one\"; rawbytes; http_client_body; sid:1;)");
928     if (de_ctx->sig_list == NULL)
929         result = 1;
930 
931  end:
932     DetectEngineCtxFree(de_ctx);
933 
934     return result;
935 }
936 
937 /**
938  * \test Test that an invalid signature containing a rawbytes along with a
939  *       http_client_body is invalidated.
940  */
DetectHttpClientBodyTest05(void)941 static int DetectHttpClientBodyTest05(void)
942 {
943     DetectEngineCtx *de_ctx = NULL;
944     int result = 0;
945 
946     de_ctx = DetectEngineCtxInit();
947     if (de_ctx == NULL)
948         goto end;
949 
950     de_ctx->flags |= DE_QUIET;
951     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
952                                "(msg:\"Testing http_client_body\"; "
953                                "content:\"one\"; http_client_body; nocase; sid:1;)");
954     if (de_ctx->sig_list != NULL)
955         result = 1;
956 
957  end:
958     DetectEngineCtxFree(de_ctx);
959 
960     return result;
961 }
962 
963 /**
964  *\test Test that the http_client_body content matches against a http request
965  *      which holds the content.
966  */
DetectHttpClientBodyTest06(void)967 static int DetectHttpClientBodyTest06(void)
968 {
969     TcpSession ssn;
970     Packet *p = NULL;
971     ThreadVars th_v;
972     DetectEngineCtx *de_ctx = NULL;
973     DetectEngineThreadCtx *det_ctx = NULL;
974     HtpState *http_state = NULL;
975     Flow f;
976     uint8_t http_buf[] =
977         "GET /index.html HTTP/1.0\r\n"
978         "Host: www.openinfosecfoundation.org\r\n"
979         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
980         "Content-Type: text/html\r\n"
981         "Content-Length: 26\r\n"
982         "\r\n"
983         "This is dummy message body";
984     uint32_t http_len = sizeof(http_buf) - 1;
985     int result = 0;
986     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
987 
988     memset(&th_v, 0, sizeof(th_v));
989     memset(&f, 0, sizeof(f));
990     memset(&ssn, 0, sizeof(ssn));
991 
992     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
993 
994     FLOW_INITIALIZE(&f);
995     f.protoctx = (void *)&ssn;
996     f.proto = IPPROTO_TCP;
997     f.flags |= FLOW_IPV4;
998 
999     p->flow = &f;
1000     p->flowflags |= FLOW_PKT_TOSERVER;
1001     p->flowflags |= FLOW_PKT_ESTABLISHED;
1002     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1003     f.alproto = ALPROTO_HTTP;
1004 
1005     StreamTcpInitConfig(TRUE);
1006 
1007     de_ctx = DetectEngineCtxInit();
1008     if (de_ctx == NULL)
1009         goto end;
1010 
1011     de_ctx->flags |= DE_QUIET;
1012 
1013     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1014                                "(msg:\"http client body test\"; "
1015                                "content:\"message\"; http_client_body; "
1016                                "sid:1;)");
1017     if (de_ctx->sig_list == NULL)
1018         goto end;
1019 
1020     SigGroupBuild(de_ctx);
1021     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1022 
1023     FLOWLOCK_WRLOCK(&f);
1024     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1025                                 STREAM_TOSERVER, http_buf, http_len);
1026     if (r != 0) {
1027         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1028         result = 0;
1029         FLOWLOCK_UNLOCK(&f);
1030         goto end;
1031     }
1032     FLOWLOCK_UNLOCK(&f);
1033 
1034     http_state = f.alstate;
1035     if (http_state == NULL) {
1036         printf("no http state: \n");
1037         result = 0;
1038         goto end;
1039     }
1040 
1041     /* do detect */
1042     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1043 
1044     if (!(PacketAlertCheck(p, 1))) {
1045         printf("sid 1 didn't match but should have\n");
1046         goto end;
1047     }
1048 
1049     result = 1;
1050 end:
1051     if (alp_tctx != NULL)
1052         AppLayerParserThreadCtxFree(alp_tctx);
1053     if (de_ctx != NULL)
1054         DetectEngineCtxFree(de_ctx);
1055 
1056     StreamTcpFreeConfig(TRUE);
1057     FLOW_DESTROY(&f);
1058     UTHFreePackets(&p, 1);
1059     return result;
1060 }
1061 
1062 /**
1063  *\test Test that the http_client_body content matches against a http request
1064  *      which holds the content.
1065  */
DetectHttpClientBodyTest07(void)1066 static int DetectHttpClientBodyTest07(void)
1067 {
1068     TcpSession ssn;
1069     Packet *p1 = NULL;
1070     Packet *p2 = NULL;
1071     ThreadVars th_v;
1072     DetectEngineCtx *de_ctx = NULL;
1073     DetectEngineThreadCtx *det_ctx = NULL;
1074     HtpState *http_state = NULL;
1075     Flow f;
1076     uint8_t http1_buf[] =
1077         "GET /index.html HTTP/1.0\r\n"
1078         "Host: www.openinfosecfoundation.org\r\n"
1079         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1080         "Content-Type: text/html\r\n"
1081         "Content-Length: 54\r\n"
1082         "\r\n"
1083         "This is dummy message body1";
1084     uint8_t http2_buf[] =
1085         "This is dummy message body2";
1086     uint32_t http1_len = sizeof(http1_buf) - 1;
1087     uint32_t http2_len = sizeof(http2_buf) - 1;
1088     int result = 0;
1089     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1090 
1091     memset(&th_v, 0, sizeof(th_v));
1092     memset(&f, 0, sizeof(f));
1093     memset(&ssn, 0, sizeof(ssn));
1094 
1095     p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1096     p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1097 
1098     FLOW_INITIALIZE(&f);
1099     f.protoctx = (void *)&ssn;
1100     f.proto = IPPROTO_TCP;
1101     f.flags |= FLOW_IPV4;
1102 
1103     p1->flow = &f;
1104     p1->flowflags |= FLOW_PKT_TOSERVER;
1105     p1->flowflags |= FLOW_PKT_ESTABLISHED;
1106     p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1107     p2->flow = &f;
1108     p2->flowflags |= FLOW_PKT_TOSERVER;
1109     p2->flowflags |= FLOW_PKT_ESTABLISHED;
1110     p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1111     f.alproto = ALPROTO_HTTP;
1112 
1113     StreamTcpInitConfig(TRUE);
1114 
1115     de_ctx = DetectEngineCtxInit();
1116     if (de_ctx == NULL)
1117         goto end;
1118 
1119     de_ctx->flags |= DE_QUIET;
1120 
1121     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1122                                "(msg:\"http client body test\"; "
1123                                "content:\"message\"; http_client_body; "
1124                                "sid:1;)");
1125     if (de_ctx->sig_list == NULL)
1126         goto end;
1127 
1128     SigGroupBuild(de_ctx);
1129     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1130 
1131     FLOWLOCK_WRLOCK(&f);
1132     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1133                                 STREAM_TOSERVER, http1_buf, http1_len);
1134     if (r != 0) {
1135         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1136         result = 0;
1137         FLOWLOCK_UNLOCK(&f);
1138         goto end;
1139     }
1140     FLOWLOCK_UNLOCK(&f);
1141 
1142     http_state = f.alstate;
1143     if (http_state == NULL) {
1144         printf("no http state: ");
1145         goto end;
1146     }
1147 
1148     /* do detect */
1149     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1150 
1151     if (PacketAlertCheck(p1, 1)) {
1152         printf("sid 1 matched on p1 but shouldn't have: ");
1153         goto end;
1154     }
1155 
1156     FLOWLOCK_WRLOCK(&f);
1157     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1158                             STREAM_TOSERVER, http2_buf, http2_len);
1159     if (r != 0) {
1160         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1161         FLOWLOCK_UNLOCK(&f);
1162         goto end;
1163     }
1164     FLOWLOCK_UNLOCK(&f);
1165 
1166     /* do detect */
1167     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1168     if (!(PacketAlertCheck(p2, 1))) {
1169         printf("sid 1 didn't match on p2 but should have: ");
1170         goto end;
1171     }
1172 
1173     result = 1;
1174 end:
1175     if (alp_tctx != NULL)
1176         AppLayerParserThreadCtxFree(alp_tctx);
1177     if (de_ctx != NULL)
1178         DetectEngineCtxFree(de_ctx);
1179 
1180     StreamTcpFreeConfig(TRUE);
1181     FLOW_DESTROY(&f);
1182     UTHFreePackets(&p1, 1);
1183     UTHFreePackets(&p2, 1);
1184     return result;
1185 }
1186 
1187 /**
1188  *\test Test that the http_client_body content matches against a http request
1189  *      which holds the content.
1190  */
DetectHttpClientBodyTest08(void)1191 static int DetectHttpClientBodyTest08(void)
1192 {
1193     TcpSession ssn;
1194     Packet *p1 = NULL;
1195     Packet *p2 = NULL;
1196     ThreadVars th_v;
1197     DetectEngineCtx *de_ctx = NULL;
1198     DetectEngineThreadCtx *det_ctx = NULL;
1199     HtpState *http_state = NULL;
1200     Flow f;
1201     uint8_t http1_buf[] =
1202         "GET /index.html HTTP/1.0\r\n"
1203         "Host: www.openinfosecfoundation.org\r\n"
1204         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1205         "Content-Type: text/html\r\n"
1206         "Content-Length: 46\r\n"
1207         "\r\n"
1208         "This is dummy body1";
1209     uint8_t http2_buf[] =
1210         "This is dummy message body2";
1211     uint32_t http1_len = sizeof(http1_buf) - 1;
1212     uint32_t http2_len = sizeof(http2_buf) - 1;
1213     int result = 0;
1214     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1215 
1216     memset(&th_v, 0, sizeof(th_v));
1217     memset(&f, 0, sizeof(f));
1218     memset(&ssn, 0, sizeof(ssn));
1219 
1220     p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1221     p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1222 
1223     FLOW_INITIALIZE(&f);
1224     f.protoctx = (void *)&ssn;
1225     f.proto = IPPROTO_TCP;
1226     f.flags |= FLOW_IPV4;
1227 
1228     p1->flow = &f;
1229     p1->flowflags |= FLOW_PKT_TOSERVER;
1230     p1->flowflags |= FLOW_PKT_ESTABLISHED;
1231     p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1232     p2->flow = &f;
1233     p2->flowflags |= FLOW_PKT_TOSERVER;
1234     p2->flowflags |= FLOW_PKT_ESTABLISHED;
1235     p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1236     f.alproto = ALPROTO_HTTP;
1237 
1238     StreamTcpInitConfig(TRUE);
1239 
1240     de_ctx = DetectEngineCtxInit();
1241     if (de_ctx == NULL)
1242         goto end;
1243 
1244     de_ctx->flags |= DE_QUIET;
1245 
1246     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1247                                "(msg:\"http client body test\"; "
1248                                "content:\"message\"; http_client_body; "
1249                                "sid:1;)");
1250     if (de_ctx->sig_list == NULL)
1251         goto end;
1252 
1253     SigGroupBuild(de_ctx);
1254     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1255 
1256     FLOWLOCK_WRLOCK(&f);
1257     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1258                                 STREAM_TOSERVER, http1_buf, http1_len);
1259     if (r != 0) {
1260         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1261         result = 0;
1262         FLOWLOCK_UNLOCK(&f);
1263         goto end;
1264     }
1265     FLOWLOCK_UNLOCK(&f);
1266 
1267     http_state = f.alstate;
1268     if (http_state == NULL) {
1269         printf("no http state: ");
1270         result = 0;
1271         goto end;
1272     }
1273 
1274     /* do detect */
1275     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1276 
1277     if ((PacketAlertCheck(p1, 1))) {
1278         printf("sid 1 didn't match but should have");
1279         goto end;
1280     }
1281 
1282     FLOWLOCK_WRLOCK(&f);
1283     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1284                             STREAM_TOSERVER, http2_buf, http2_len);
1285     if (r != 0) {
1286         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1287         result = 0;
1288         FLOWLOCK_UNLOCK(&f);
1289         goto end;
1290     }
1291     FLOWLOCK_UNLOCK(&f);
1292 
1293     /* do detect */
1294     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1295 
1296     if (!(PacketAlertCheck(p2, 1))) {
1297         printf("sid 1 didn't match but should have");
1298         goto end;
1299     }
1300 
1301     result = 1;
1302 end:
1303     if (alp_tctx != NULL)
1304         AppLayerParserThreadCtxFree(alp_tctx);
1305     if (de_ctx != NULL)
1306         DetectEngineCtxFree(de_ctx);
1307 
1308     StreamTcpFreeConfig(TRUE);
1309     FLOW_DESTROY(&f);
1310     UTHFreePackets(&p1, 1);
1311     UTHFreePackets(&p2, 1);
1312     return result;
1313 }
1314 
1315 /**
1316  *\test Test that the http_client_body content matches against a http request
1317  *      which holds the content, against a cross boundary present pattern.
1318  */
DetectHttpClientBodyTest09(void)1319 static int DetectHttpClientBodyTest09(void)
1320 {
1321     TcpSession ssn;
1322     Packet *p1 = NULL;
1323     Packet *p2 = NULL;
1324     ThreadVars th_v;
1325     DetectEngineCtx *de_ctx = NULL;
1326     DetectEngineThreadCtx *det_ctx = NULL;
1327     HtpState *http_state = NULL;
1328     Flow f;
1329     uint8_t http1_buf[] =
1330         "GET /index.html HTTP/1.0\r\n"
1331         "Host: www.openinfosecfoundation.org\r\n"
1332         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1333         "Content-Type: text/html\r\n"
1334         "Content-Length: 46\r\n"
1335         "\r\n"
1336         "This is dummy body1";
1337     uint8_t http2_buf[] =
1338         "This is dummy message body2";
1339     uint32_t http1_len = sizeof(http1_buf) - 1;
1340     uint32_t http2_len = sizeof(http2_buf) - 1;
1341     int result = 0;
1342     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1343 
1344     memset(&th_v, 0, sizeof(th_v));
1345     memset(&f, 0, sizeof(f));
1346     memset(&ssn, 0, sizeof(ssn));
1347 
1348     p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1349     p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1350 
1351     FLOW_INITIALIZE(&f);
1352     f.protoctx = (void *)&ssn;
1353     f.proto = IPPROTO_TCP;
1354     f.flags |= FLOW_IPV4;
1355 
1356     p1->flow = &f;
1357     p1->flowflags |= FLOW_PKT_TOSERVER;
1358     p1->flowflags |= FLOW_PKT_ESTABLISHED;
1359     p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1360     p2->flow = &f;
1361     p2->flowflags |= FLOW_PKT_TOSERVER;
1362     p2->flowflags |= FLOW_PKT_ESTABLISHED;
1363     p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1364     f.alproto = ALPROTO_HTTP;
1365 
1366     StreamTcpInitConfig(TRUE);
1367 
1368     de_ctx = DetectEngineCtxInit();
1369     if (de_ctx == NULL)
1370         goto end;
1371 
1372     de_ctx->flags |= DE_QUIET;
1373 
1374     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1375                                "(msg:\"http client body test\"; "
1376                                "content:\"body1This\"; http_client_body; "
1377                                "sid:1;)");
1378     if (de_ctx->sig_list == NULL)
1379         goto end;
1380 
1381     SigGroupBuild(de_ctx);
1382     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1383 
1384     FLOWLOCK_WRLOCK(&f);
1385     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1386                                 STREAM_TOSERVER, http1_buf, http1_len);
1387     if (r != 0) {
1388         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1389         result = 0;
1390         FLOWLOCK_UNLOCK(&f);
1391         goto end;
1392     }
1393     FLOWLOCK_UNLOCK(&f);
1394 
1395     http_state = f.alstate;
1396     if (http_state == NULL) {
1397         printf("no http state: ");
1398         result = 0;
1399         goto end;
1400     }
1401 
1402     /* do detect */
1403     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1404 
1405     if ((PacketAlertCheck(p1, 1))) {
1406         printf("sid 1 didn't match but should have");
1407         goto end;
1408     }
1409 
1410     FLOWLOCK_WRLOCK(&f);
1411     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1412                             STREAM_TOSERVER, http2_buf, http2_len);
1413     if (r != 0) {
1414         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1415         result = 0;
1416         FLOWLOCK_UNLOCK(&f);
1417         goto end;
1418     }
1419     FLOWLOCK_UNLOCK(&f);
1420 
1421     /* do detect */
1422     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1423 
1424     if (!(PacketAlertCheck(p2, 1))) {
1425         printf("sid 1 didn't match but should have");
1426         goto end;
1427     }
1428 
1429     result = 1;
1430 end:
1431     if (alp_tctx != NULL)
1432         AppLayerParserThreadCtxFree(alp_tctx);
1433     if (de_ctx != NULL)
1434         DetectEngineCtxFree(de_ctx);
1435 
1436     StreamTcpFreeConfig(TRUE);
1437     FLOW_DESTROY(&f);
1438     UTHFreePackets(&p1, 1);
1439     UTHFreePackets(&p2, 1);
1440     return result;
1441 }
1442 
1443 /**
1444  *\test Test that the http_client_body content matches against a http request
1445  *      against a case insensitive pattern.
1446  */
DetectHttpClientBodyTest10(void)1447 static int DetectHttpClientBodyTest10(void)
1448 {
1449     TcpSession ssn;
1450     Packet *p1 = NULL;
1451     Packet *p2 = NULL;
1452     ThreadVars th_v;
1453     DetectEngineCtx *de_ctx = NULL;
1454     DetectEngineThreadCtx *det_ctx = NULL;
1455     HtpState *http_state = NULL;
1456     Flow f;
1457     uint8_t http1_buf[] =
1458         "GET /index.html HTTP/1.0\r\n"
1459         "Host: www.openinfosecfoundation.org\r\n"
1460         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1461         "Content-Type: text/html\r\n"
1462         "Content-Length: 46\r\n"
1463         "\r\n"
1464         "This is dummy bodY1";
1465     uint8_t http2_buf[] =
1466         "This is dummy message body2";
1467     uint32_t http1_len = sizeof(http1_buf) - 1;
1468     uint32_t http2_len = sizeof(http2_buf) - 1;
1469     int result = 0;
1470     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1471 
1472     memset(&th_v, 0, sizeof(th_v));
1473     memset(&f, 0, sizeof(f));
1474     memset(&ssn, 0, sizeof(ssn));
1475 
1476     p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1477     p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1478 
1479     FLOW_INITIALIZE(&f);
1480     f.protoctx = (void *)&ssn;
1481     f.proto = IPPROTO_TCP;
1482     f.flags |= FLOW_IPV4;
1483 
1484     p1->flow = &f;
1485     p1->flowflags |= FLOW_PKT_TOSERVER;
1486     p1->flowflags |= FLOW_PKT_ESTABLISHED;
1487     p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1488     p2->flow = &f;
1489     p2->flowflags |= FLOW_PKT_TOSERVER;
1490     p2->flowflags |= FLOW_PKT_ESTABLISHED;
1491     p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1492     f.alproto = ALPROTO_HTTP;
1493 
1494     StreamTcpInitConfig(TRUE);
1495 
1496     de_ctx = DetectEngineCtxInit();
1497     if (de_ctx == NULL)
1498         goto end;
1499 
1500     de_ctx->flags |= DE_QUIET;
1501 
1502     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1503                                "(msg:\"http client body test\"; "
1504                                "content:\"body1This\"; http_client_body; nocase;"
1505                                "sid:1;)");
1506     if (de_ctx->sig_list == NULL)
1507         goto end;
1508 
1509     SigGroupBuild(de_ctx);
1510     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1511 
1512     FLOWLOCK_WRLOCK(&f);
1513     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1514                                 STREAM_TOSERVER, http1_buf, http1_len);
1515     if (r != 0) {
1516         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1517         result = 0;
1518         FLOWLOCK_UNLOCK(&f);
1519         goto end;
1520     }
1521     FLOWLOCK_UNLOCK(&f);
1522 
1523     http_state = f.alstate;
1524     if (http_state == NULL) {
1525         printf("no http state: \n");
1526         result = 0;
1527         goto end;
1528     }
1529 
1530     /* do detect */
1531     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1532 
1533     if ((PacketAlertCheck(p1, 1))) {
1534         printf("sid 1 didn't match but should have\n");
1535         goto end;
1536     }
1537 
1538     FLOWLOCK_WRLOCK(&f);
1539     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1540                             STREAM_TOSERVER, http2_buf, http2_len);
1541     if (r != 0) {
1542         printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
1543         result = 0;
1544         FLOWLOCK_UNLOCK(&f);
1545         goto end;
1546     }
1547     FLOWLOCK_UNLOCK(&f);
1548 
1549     /* do detect */
1550     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1551 
1552     if (!(PacketAlertCheck(p2, 1))) {
1553         printf("sid 1 didn't match but should have");
1554         goto end;
1555     }
1556 
1557     result = 1;
1558 end:
1559     if (alp_tctx != NULL)
1560         AppLayerParserThreadCtxFree(alp_tctx);
1561     if (de_ctx != NULL)
1562         DetectEngineCtxFree(de_ctx);
1563 
1564     StreamTcpFreeConfig(TRUE);
1565     FLOW_DESTROY(&f);
1566     UTHFreePackets(&p1, 1);
1567     UTHFreePackets(&p2, 1);
1568     return result;
1569 }
1570 
1571 /**
1572  *\test Test that the negated http_client_body content matches against a
1573  *      http request which doesn't hold the content.
1574  */
DetectHttpClientBodyTest11(void)1575 static int DetectHttpClientBodyTest11(void)
1576 {
1577     TcpSession ssn;
1578     Packet *p = NULL;
1579     ThreadVars th_v;
1580     DetectEngineCtx *de_ctx = NULL;
1581     DetectEngineThreadCtx *det_ctx = NULL;
1582     HtpState *http_state = NULL;
1583     Flow f;
1584     uint8_t http_buf[] =
1585         "GET /index.html HTTP/1.0\r\n"
1586         "Host: www.openinfosecfoundation.org\r\n"
1587         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1588         "Content-Type: text/html\r\n"
1589         "Content-Length: 26\r\n"
1590         "\r\n"
1591         "This is dummy message body";
1592     uint32_t http_len = sizeof(http_buf) - 1;
1593     int result = 0;
1594     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1595 
1596     memset(&th_v, 0, sizeof(th_v));
1597     memset(&f, 0, sizeof(f));
1598     memset(&ssn, 0, sizeof(ssn));
1599 
1600     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1601 
1602     FLOW_INITIALIZE(&f);
1603     f.protoctx = (void *)&ssn;
1604     f.proto = IPPROTO_TCP;
1605     f.flags |= FLOW_IPV4;
1606 
1607     p->flow = &f;
1608     p->flowflags |= FLOW_PKT_TOSERVER;
1609     p->flowflags |= FLOW_PKT_ESTABLISHED;
1610     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1611     f.alproto = ALPROTO_HTTP;
1612 
1613     StreamTcpInitConfig(TRUE);
1614 
1615     de_ctx = DetectEngineCtxInit();
1616     if (de_ctx == NULL)
1617         goto end;
1618 
1619     de_ctx->flags |= DE_QUIET;
1620 
1621     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1622                                "(msg:\"http client body test\"; "
1623                                "content:!\"message1\"; http_client_body; "
1624                                "sid:1;)");
1625     if (de_ctx->sig_list == NULL)
1626         goto end;
1627 
1628     SigGroupBuild(de_ctx);
1629     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1630 
1631     FLOWLOCK_WRLOCK(&f);
1632     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1633                                 STREAM_TOSERVER, http_buf, http_len);
1634     if (r != 0) {
1635         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1636         result = 0;
1637         FLOWLOCK_UNLOCK(&f);
1638         goto end;
1639     }
1640     FLOWLOCK_UNLOCK(&f);
1641 
1642     http_state = f.alstate;
1643     if (http_state == NULL) {
1644         printf("no http state: ");
1645         result = 0;
1646         goto end;
1647     }
1648 
1649     /* do detect */
1650     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1651 
1652     if (!(PacketAlertCheck(p, 1))) {
1653         printf("sid 1 didn't match but should have");
1654         goto end;
1655     }
1656 
1657     result = 1;
1658 end:
1659     if (alp_tctx != NULL)
1660         AppLayerParserThreadCtxFree(alp_tctx);
1661     if (de_ctx != NULL)
1662         DetectEngineCtxFree(de_ctx);
1663 
1664     StreamTcpFreeConfig(TRUE);
1665     FLOW_DESTROY(&f);
1666     UTHFreePackets(&p, 1);
1667     return result;
1668 }
1669 
1670 /**
1671  *\test Negative test that the negated http_client_body content matches against a
1672  *      http request which holds hold the content.
1673  */
DetectHttpClientBodyTest12(void)1674 static int DetectHttpClientBodyTest12(void)
1675 {
1676     TcpSession ssn;
1677     Packet *p = NULL;
1678     ThreadVars th_v;
1679     DetectEngineCtx *de_ctx = NULL;
1680     DetectEngineThreadCtx *det_ctx = NULL;
1681     HtpState *http_state = NULL;
1682     Flow f;
1683     uint8_t http_buf[] =
1684         "GET /index.html HTTP/1.0\r\n"
1685         "Host: www.openinfosecfoundation.org\r\n"
1686         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1687         "Content-Type: text/html\r\n"
1688         "Content-Length: 26\r\n"
1689         "\r\n"
1690         "This is dummy message body";
1691     uint32_t http_len = sizeof(http_buf) - 1;
1692     int result = 0;
1693     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1694 
1695     memset(&th_v, 0, sizeof(th_v));
1696     memset(&f, 0, sizeof(f));
1697     memset(&ssn, 0, sizeof(ssn));
1698 
1699     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1700 
1701     FLOW_INITIALIZE(&f);
1702     f.protoctx = (void *)&ssn;
1703     f.proto = IPPROTO_TCP;
1704     f.flags |= FLOW_IPV4;
1705 
1706     p->flow = &f;
1707     p->flowflags |= FLOW_PKT_TOSERVER;
1708     p->flowflags |= FLOW_PKT_ESTABLISHED;
1709     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1710     f.alproto = ALPROTO_HTTP;
1711 
1712     StreamTcpInitConfig(TRUE);
1713 
1714     de_ctx = DetectEngineCtxInit();
1715     if (de_ctx == NULL)
1716         goto end;
1717 
1718     de_ctx->flags |= DE_QUIET;
1719 
1720     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1721                                "(msg:\"http client body test\"; "
1722                                "content:!\"message\"; http_client_body; "
1723                                "sid:1;)");
1724     if (de_ctx->sig_list == NULL)
1725         goto end;
1726 
1727     SigGroupBuild(de_ctx);
1728     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1729 
1730     FLOWLOCK_WRLOCK(&f);
1731     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1732                                 STREAM_TOSERVER, http_buf, http_len);
1733     if (r != 0) {
1734         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1735         result = 0;
1736         FLOWLOCK_UNLOCK(&f);
1737         goto end;
1738     }
1739     FLOWLOCK_UNLOCK(&f);
1740 
1741     http_state = f.alstate;
1742     if (http_state == NULL) {
1743         printf("no http state: ");
1744         result = 0;
1745         goto end;
1746     }
1747 
1748     /* do detect */
1749     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1750 
1751     if ((PacketAlertCheck(p, 1))) {
1752         printf("sid 1 didn't match but should have");
1753         goto end;
1754     }
1755 
1756     result = 1;
1757 end:
1758     if (alp_tctx != NULL)
1759         AppLayerParserThreadCtxFree(alp_tctx);
1760     if (de_ctx != NULL)
1761         DetectEngineCtxFree(de_ctx);
1762 
1763     StreamTcpFreeConfig(TRUE);
1764     FLOW_DESTROY(&f);
1765     UTHFreePackets(&p, 1);
1766     return result;
1767 }
1768 
1769 /**
1770  *\test Test that the http_client_body content matches against a http request
1771  *      which holds the content.
1772  */
DetectHttpClientBodyTest13(void)1773 static int DetectHttpClientBodyTest13(void)
1774 {
1775     TcpSession ssn;
1776     Packet *p = NULL;
1777     ThreadVars th_v;
1778     DetectEngineCtx *de_ctx = NULL;
1779     DetectEngineThreadCtx *det_ctx = NULL;
1780     HtpState *http_state = NULL;
1781     Flow f;
1782     uint8_t http_buf[] =
1783         "GET /index.html HTTP/1.0\r\n"
1784         "Host: www.openinfosecfoundation.org\r\n"
1785         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
1786         "Content-Type: text/html\r\n"
1787         "Content-Length: 55\r\n"
1788         "\r\n"
1789         "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend";
1790     uint32_t http_len = sizeof(http_buf) - 1;
1791     int result = 0;
1792     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1793 
1794     memset(&th_v, 0, sizeof(th_v));
1795     memset(&f, 0, sizeof(f));
1796     memset(&ssn, 0, sizeof(ssn));
1797 
1798     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1799 
1800     FLOW_INITIALIZE(&f);
1801     f.protoctx = (void *)&ssn;
1802     f.proto = IPPROTO_TCP;
1803     f.flags |= FLOW_IPV4;
1804 
1805     p->flow = &f;
1806     p->flowflags |= FLOW_PKT_TOSERVER;
1807     p->flowflags |= FLOW_PKT_ESTABLISHED;
1808     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1809     f.alproto = ALPROTO_HTTP;
1810 
1811     StreamTcpInitConfig(TRUE);
1812 
1813     de_ctx = DetectEngineCtxInit();
1814     if (de_ctx == NULL)
1815         goto end;
1816 
1817     de_ctx->flags |= DE_QUIET;
1818 
1819     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1820                                "(msg:\"http client body test\"; "
1821                                "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_client_body; "
1822                                "sid:1;)");
1823     if (de_ctx->sig_list == NULL)
1824         goto end;
1825 
1826     SigGroupBuild(de_ctx);
1827     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1828 
1829     FLOWLOCK_WRLOCK(&f);
1830     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1831                                 STREAM_TOSERVER, http_buf, http_len);
1832     if (r != 0) {
1833         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1834         result = 0;
1835         FLOWLOCK_UNLOCK(&f);
1836         goto end;
1837     }
1838     FLOWLOCK_UNLOCK(&f);
1839 
1840     http_state = f.alstate;
1841     if (http_state == NULL) {
1842         printf("no http state: ");
1843         result = 0;
1844         goto end;
1845     }
1846 
1847     /* do detect */
1848     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1849 
1850     if (!(PacketAlertCheck(p, 1))) {
1851         printf("sid 1 didn't match but should have");
1852         goto end;
1853     }
1854 
1855     result = 1;
1856 end:
1857     if (alp_tctx != NULL)
1858         AppLayerParserThreadCtxFree(alp_tctx);
1859     if (de_ctx != NULL)
1860         DetectEngineCtxFree(de_ctx);
1861 
1862     StreamTcpFreeConfig(TRUE);
1863     FLOW_DESTROY(&f);
1864     UTHFreePackets(&p, 1);
1865     return result;
1866 }
1867 
1868 /** \test multiple http transactions and body chunks of request handling */
DetectHttpClientBodyTest14(void)1869 static int DetectHttpClientBodyTest14(void)
1870 {
1871     int result = 0;
1872     Signature *s = NULL;
1873     DetectEngineThreadCtx *det_ctx = NULL;
1874     ThreadVars th_v;
1875     Flow f;
1876     TcpSession ssn;
1877     Packet *p = NULL;
1878     uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
1879     uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1880     uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
1881     uint8_t httpbuf4[] = "Body one!!";
1882     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1883     uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1884     uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1885     uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1886     uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
1887     uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
1888     uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1889     uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
1890     uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
1891     uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
1892     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1893 
1894     memset(&th_v, 0, sizeof(th_v));
1895     memset(&f, 0, sizeof(f));
1896     memset(&ssn, 0, sizeof(ssn));
1897 
1898     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1899 
1900     FLOW_INITIALIZE(&f);
1901     f.protoctx = (void *)&ssn;
1902     f.proto = IPPROTO_TCP;
1903     f.flags |= FLOW_IPV4;
1904 
1905     p->flow = &f;
1906     p->flowflags |= FLOW_PKT_TOSERVER;
1907     p->flowflags |= FLOW_PKT_ESTABLISHED;
1908     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1909     f.alproto = ALPROTO_HTTP;
1910 
1911     StreamTcpInitConfig(TRUE);
1912 
1913     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1914     if (de_ctx == NULL) {
1915         goto end;
1916     }
1917 
1918     de_ctx->flags |= DE_QUIET;
1919 
1920     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"one\"; http_client_body; sid:1; rev:1;)");
1921     if (s == NULL) {
1922         printf("sig parse failed: ");
1923         goto end;
1924     }
1925     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; content:\"two\"; http_client_body; sid:2; rev:1;)");
1926     if (s == NULL) {
1927         printf("sig2 parse failed: ");
1928         goto end;
1929     }
1930 
1931     SigGroupBuild(de_ctx);
1932     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1933 
1934     FLOWLOCK_WRLOCK(&f);
1935     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1936                                 STREAM_TOSERVER, httpbuf1, httplen1);
1937     if (r != 0) {
1938         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1939         FLOWLOCK_UNLOCK(&f);
1940         goto end;
1941     }
1942     FLOWLOCK_UNLOCK(&f);
1943 
1944     /* do detect */
1945     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1946     if (PacketAlertCheck(p, 1)) {
1947         printf("sig 1 alerted: ");
1948         goto end;
1949     }
1950     p->alerts.cnt = 0;
1951 
1952     FLOWLOCK_WRLOCK(&f);
1953     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1954                             STREAM_TOSERVER, httpbuf2, httplen2);
1955     if (r != 0) {
1956         printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1957         FLOWLOCK_UNLOCK(&f);
1958         goto end;
1959     }
1960     FLOWLOCK_UNLOCK(&f);
1961 
1962     /* do detect */
1963     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1964     if (PacketAlertCheck(p, 1)) {
1965         printf("sig 1 alerted (2): ");
1966         FLOWLOCK_UNLOCK(&f);
1967         goto end;
1968     }
1969     p->alerts.cnt = 0;
1970 
1971     FLOWLOCK_WRLOCK(&f);
1972     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1973                             STREAM_TOSERVER, httpbuf3, httplen3);
1974     if (r != 0) {
1975         printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1976     FLOWLOCK_UNLOCK(&f);
1977         goto end;
1978     }
1979     FLOWLOCK_UNLOCK(&f);
1980 
1981     /* do detect */
1982     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1983     if (PacketAlertCheck(p, 1)) {
1984         printf("signature matched, but shouldn't have: ");
1985         goto end;
1986     }
1987     p->alerts.cnt = 0;
1988 
1989     FLOWLOCK_WRLOCK(&f);
1990     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1991                             STREAM_TOSERVER, httpbuf4, httplen4);
1992     if (r != 0) {
1993         printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
1994         result = 0;
1995         FLOWLOCK_UNLOCK(&f);
1996         goto end;
1997     }
1998     FLOWLOCK_UNLOCK(&f);
1999 
2000     /* do detect */
2001     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2002     if (!(PacketAlertCheck(p, 1))) {
2003         printf("sig 1 didn't alert: ");
2004         goto end;
2005     }
2006     p->alerts.cnt = 0;
2007 
2008     FLOWLOCK_WRLOCK(&f);
2009     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2010                             STREAM_TOSERVER, httpbuf5, httplen5);
2011     if (r != 0) {
2012         printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
2013         FLOWLOCK_UNLOCK(&f);
2014         goto end;
2015     }
2016     FLOWLOCK_UNLOCK(&f);
2017 
2018     /* do detect */
2019     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2020     if (PacketAlertCheck(p, 1)) {
2021         printf("sig 1 alerted (5): ");
2022         goto end;
2023     }
2024     p->alerts.cnt = 0;
2025 
2026     FLOWLOCK_WRLOCK(&f);
2027     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2028                             STREAM_TOSERVER, httpbuf6, httplen6);
2029     if (r != 0) {
2030         printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
2031         FLOWLOCK_UNLOCK(&f);
2032         goto end;
2033     }
2034     FLOWLOCK_UNLOCK(&f);
2035 
2036     /* do detect */
2037     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2038     if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
2039         printf("sig 1 alerted (request 2, chunk 6): ");
2040         goto end;
2041     }
2042     p->alerts.cnt = 0;
2043 
2044     SCLogDebug("sending data chunk 7");
2045 
2046     FLOWLOCK_WRLOCK(&f);
2047     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2048                             STREAM_TOSERVER, httpbuf7, httplen7);
2049     if (r != 0) {
2050         printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
2051         FLOWLOCK_UNLOCK(&f);
2052         goto end;
2053     }
2054     FLOWLOCK_UNLOCK(&f);
2055 
2056     /* do detect */
2057     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2058     if (!(PacketAlertCheck(p, 2))) {
2059         printf("signature 2 didn't match, but should have: ");
2060         goto end;
2061     }
2062     p->alerts.cnt = 0;
2063 
2064     HtpState *htp_state = f.alstate;
2065     if (htp_state == NULL) {
2066         printf("no http state: ");
2067         result = 0;
2068         goto end;
2069     }
2070 
2071     if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
2072         printf("The http app layer doesn't have 2 transactions, but it should: ");
2073         goto end;
2074     }
2075 
2076     result = 1;
2077 end:
2078     if (alp_tctx != NULL)
2079         AppLayerParserThreadCtxFree(alp_tctx);
2080     if (det_ctx != NULL) {
2081         DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2082     }
2083     if (de_ctx != NULL) {
2084         DetectEngineCtxFree(de_ctx);
2085     }
2086 
2087     StreamTcpFreeConfig(TRUE);
2088     FLOW_DESTROY(&f);
2089     UTHFreePacket(p);
2090     return result;
2091 }
2092 
2093 /** \test multiple http transactions and body chunks of request handling */
DetectHttpClientBodyTest15(void)2094 static int DetectHttpClientBodyTest15(void)
2095 {
2096     int result = 0;
2097     Signature *s = NULL;
2098     DetectEngineThreadCtx *det_ctx = NULL;
2099     ThreadVars th_v;
2100     Flow f;
2101     TcpSession ssn;
2102     Packet *p = NULL;
2103     uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
2104     uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2105     uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2106     uint8_t httpbuf4[] = "Body one!!";
2107     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2108     uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2109     uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
2110     uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
2111     uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
2112     uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
2113     uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
2114     uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
2115     uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
2116     uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
2117     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
2118 
2119     memset(&th_v, 0, sizeof(th_v));
2120     memset(&f, 0, sizeof(f));
2121     memset(&ssn, 0, sizeof(ssn));
2122 
2123     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2124 
2125     FLOW_INITIALIZE(&f);
2126     f.protoctx = (void *)&ssn;
2127     f.proto = IPPROTO_TCP;
2128     f.flags |= FLOW_IPV4;
2129 
2130     p->flow = &f;
2131     p->flowflags |= FLOW_PKT_TOSERVER;
2132     p->flowflags |= FLOW_PKT_ESTABLISHED;
2133     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
2134     f.alproto = ALPROTO_HTTP;
2135 
2136     StreamTcpInitConfig(TRUE);
2137 
2138     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2139     if (de_ctx == NULL) {
2140         goto end;
2141     }
2142 
2143     de_ctx->flags |= DE_QUIET;
2144 
2145     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"one\"; http_client_body; sid:1; rev:1;)");
2146     if (s == NULL) {
2147         printf("sig parse failed: ");
2148         goto end;
2149     }
2150     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; content:\"two\"; http_client_body; sid:2; rev:1;)");
2151     if (s == NULL) {
2152         printf("sig2 parse failed: ");
2153         goto end;
2154     }
2155 
2156     SigGroupBuild(de_ctx);
2157     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2158 
2159     FLOWLOCK_WRLOCK(&f);
2160     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2161                                 STREAM_TOSERVER, httpbuf1, httplen1);
2162     if (r != 0) {
2163         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2164         FLOWLOCK_UNLOCK(&f);
2165         goto end;
2166     }
2167     FLOWLOCK_UNLOCK(&f);
2168 
2169     /* do detect */
2170     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2171     if (PacketAlertCheck(p, 1)) {
2172         printf("sig 1 alerted: ");
2173         goto end;
2174     }
2175     p->alerts.cnt = 0;
2176 
2177     FLOWLOCK_WRLOCK(&f);
2178     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2179                             STREAM_TOSERVER, httpbuf2, httplen2);
2180     if (r != 0) {
2181         printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2182         FLOWLOCK_UNLOCK(&f);
2183         goto end;
2184     }
2185     FLOWLOCK_UNLOCK(&f);
2186 
2187     /* do detect */
2188     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2189     if (PacketAlertCheck(p, 1)) {
2190         printf("sig 1 alerted (2): ");
2191         goto end;
2192     }
2193     p->alerts.cnt = 0;
2194 
2195     FLOWLOCK_WRLOCK(&f);
2196     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2197                             STREAM_TOSERVER, httpbuf3, httplen3);
2198     if (r != 0) {
2199         printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
2200         FLOWLOCK_UNLOCK(&f);
2201         goto end;
2202     }
2203     FLOWLOCK_UNLOCK(&f);
2204 
2205     /* do detect */
2206     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2207     if (PacketAlertCheck(p, 1)) {
2208         printf("signature matched, but shouldn't have: ");
2209         goto end;
2210     }
2211     p->alerts.cnt = 0;
2212 
2213     FLOWLOCK_WRLOCK(&f);
2214     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2215                             STREAM_TOSERVER, httpbuf4, httplen4);
2216     if (r != 0) {
2217         printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
2218         result = 0;
2219         FLOWLOCK_UNLOCK(&f);
2220         goto end;
2221     }
2222     FLOWLOCK_UNLOCK(&f);
2223 
2224     /* do detect */
2225     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2226     if (!(PacketAlertCheck(p, 1))) {
2227         printf("sig 1 didn't alert: ");
2228         goto end;
2229     }
2230     p->alerts.cnt = 0;
2231 
2232     FLOWLOCK_WRLOCK(&f);
2233     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2234                             STREAM_TOSERVER, httpbuf5, httplen5);
2235     if (r != 0) {
2236         printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
2237         FLOWLOCK_UNLOCK(&f);
2238         goto end;
2239     }
2240     FLOWLOCK_UNLOCK(&f);
2241 
2242     /* do detect */
2243     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2244     if (PacketAlertCheck(p, 1)) {
2245         printf("sig 1 alerted (5): ");
2246         goto end;
2247     }
2248     p->alerts.cnt = 0;
2249 
2250     FLOWLOCK_WRLOCK(&f);
2251     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2252                             STREAM_TOSERVER, httpbuf6, httplen6);
2253     if (r != 0) {
2254         printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
2255         FLOWLOCK_UNLOCK(&f);
2256         goto end;
2257     }
2258     FLOWLOCK_UNLOCK(&f);
2259 
2260     /* do detect */
2261     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2262     if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
2263         printf("sig 1 alerted (request 2, chunk 6): ");
2264         goto end;
2265     }
2266     p->alerts.cnt = 0;
2267 
2268     SCLogDebug("sending data chunk 7");
2269 
2270     FLOWLOCK_WRLOCK(&f);
2271     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2272                             STREAM_TOSERVER, httpbuf7, httplen7);
2273     if (r != 0) {
2274         printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
2275         FLOWLOCK_UNLOCK(&f);
2276         goto end;
2277     }
2278     FLOWLOCK_UNLOCK(&f);
2279 
2280     /* do detect */
2281     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2282     if (!(PacketAlertCheck(p, 2))) {
2283         printf("signature 2 didn't match, but should have: ");
2284         goto end;
2285     }
2286     p->alerts.cnt = 0;
2287 
2288     HtpState *htp_state = f.alstate;
2289     if (htp_state == NULL) {
2290         printf("no http state: ");
2291         result = 0;
2292         goto end;
2293     }
2294 
2295     /* hardcoded check of the transactions and it's client body chunks */
2296     if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
2297         printf("The http app layer doesn't have 2 transactions, but it should: ");
2298         goto end;
2299     }
2300 
2301     htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 0);
2302     htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 1);
2303 
2304     HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
2305 
2306     HtpBodyChunk *cur = htud->request_body.first;
2307     if (htud->request_body.first == NULL) {
2308         SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
2309         goto end;
2310     }
2311 
2312     if (StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg,
2313                 (uint8_t *)"Body one!!", 10) != 1)
2314     {
2315         SCLogDebug("Body data in t1 is not correctly set: ");
2316         goto end;
2317     }
2318 
2319     htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
2320 
2321     cur = htud->request_body.first;
2322     if (htud->request_body.first == NULL) {
2323         SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
2324         goto end;
2325     }
2326 
2327     if (StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg,
2328                 (uint8_t *)"Body two!!", 10) != 1)
2329     {
2330         SCLogDebug("Body data in t1 is not correctly set: ");
2331         goto end;
2332     }
2333 
2334     result = 1;
2335 end:
2336     if (alp_tctx != NULL)
2337         AppLayerParserThreadCtxFree(alp_tctx);
2338     if (det_ctx != NULL) {
2339         DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2340     }
2341     if (de_ctx != NULL) {
2342         DetectEngineCtxFree(de_ctx);
2343     }
2344 
2345     StreamTcpFreeConfig(TRUE);
2346     FLOW_DESTROY(&f);
2347     UTHFreePacket(p);
2348     return result;
2349 }
2350 
DetectHttpClientBodyTest22(void)2351 static int DetectHttpClientBodyTest22(void)
2352 {
2353     DetectEngineCtx *de_ctx = NULL;
2354     int result = 0;
2355 
2356     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2357         goto end;
2358 
2359     de_ctx->flags |= DE_QUIET;
2360     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2361                                "(content:\"one\"; content:\"two\"; http_client_body; "
2362                                "content:\"three\"; distance:10; http_client_body; content:\"four\"; sid:1;)");
2363     if (de_ctx->sig_list == NULL) {
2364         printf("de_ctx->sig_list == NULL\n");
2365         goto end;
2366     }
2367 
2368     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2369         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2370         goto end;
2371     }
2372 
2373     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2374         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2375         goto end;
2376     }
2377 
2378     DetectContentData *cd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2379     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2380     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2381     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2382     if (cd1->flags != 0 || memcmp(cd1->content, "one", cd1->content_len) != 0 ||
2383         cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2384         hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2385         memcmp(hcbd1->content, "two", hcbd1->content_len) != 0 ||
2386         hcbd2->flags != DETECT_CONTENT_DISTANCE ||
2387         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2388         goto end;
2389     }
2390 
2391     if (!DETECT_CONTENT_IS_SINGLE(cd1) ||
2392         !DETECT_CONTENT_IS_SINGLE(cd2) ||
2393         DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2394         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2395         goto end;
2396     }
2397 
2398     result = 1;
2399 
2400  end:
2401     DetectEngineCtxFree(de_ctx);
2402     return result;
2403 }
2404 
DetectHttpClientBodyTest23(void)2405 static int DetectHttpClientBodyTest23(void)
2406 {
2407     DetectEngineCtx *de_ctx = NULL;
2408     int result = 0;
2409 
2410     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2411         goto end;
2412 
2413     de_ctx->flags |= DE_QUIET;
2414     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2415                                "(content:\"one\"; http_client_body; pcre:/two/; "
2416                                "content:\"three\"; distance:10; http_client_body; content:\"four\"; sid:1;)");
2417     if (de_ctx->sig_list == NULL) {
2418         printf("de_ctx->sig_list == NULL\n");
2419         goto end;
2420     }
2421 
2422     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2423         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2424         goto end;
2425     }
2426 
2427     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2428         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2429         goto end;
2430     }
2431 
2432     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2433     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2434     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2435     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2436     if (pd1->flags != 0 ||
2437         cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2438         hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2439         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2440         hcbd2->flags != DETECT_CONTENT_DISTANCE ||
2441         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2442         goto end;
2443     }
2444 
2445     if (!DETECT_CONTENT_IS_SINGLE(cd2) ||
2446         DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2447         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2448         goto end;
2449     }
2450 
2451     result = 1;
2452 
2453  end:
2454     DetectEngineCtxFree(de_ctx);
2455     return result;
2456 }
2457 
DetectHttpClientBodyTest24(void)2458 static int DetectHttpClientBodyTest24(void)
2459 {
2460     DetectEngineCtx *de_ctx = NULL;
2461     int result = 0;
2462 
2463     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2464         goto end;
2465 
2466     de_ctx->flags |= DE_QUIET;
2467     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2468                                "(content:\"one\"; http_client_body; pcre:/two/; "
2469                                "content:\"three\"; distance:10; within:15; http_client_body; content:\"four\"; sid:1;)");
2470     if (de_ctx->sig_list == NULL) {
2471         printf("de_ctx->sig_list == NULL\n");
2472         goto end;
2473     }
2474 
2475     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2476         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2477         goto end;
2478     }
2479 
2480     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2481         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2482         goto end;
2483     }
2484 
2485     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2486     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2487     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2488     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2489     if (pd1->flags != 0 ||
2490         cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2491         hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2492         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2493         hcbd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
2494         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2495         goto end;
2496     }
2497 
2498     if (!DETECT_CONTENT_IS_SINGLE(cd2) ||
2499         DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2500         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2501         goto end;
2502     }
2503 
2504     result = 1;
2505 
2506  end:
2507     DetectEngineCtxFree(de_ctx);
2508     return result;
2509 }
2510 
DetectHttpClientBodyTest25(void)2511 static int DetectHttpClientBodyTest25(void)
2512 {
2513     DetectEngineCtx *de_ctx = NULL;
2514     int result = 0;
2515 
2516     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2517         goto end;
2518 
2519     de_ctx->flags |= DE_QUIET;
2520     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2521                                "(content:\"one\"; http_client_body; pcre:/two/; "
2522                                "content:\"three\"; distance:10; http_client_body; "
2523                                "content:\"four\"; distance:10; sid:1;)");
2524     if (de_ctx->sig_list == NULL) {
2525         printf("de_ctx->sig_list == NULL\n");
2526         goto end;
2527     }
2528 
2529     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2530         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2531         goto end;
2532     }
2533 
2534     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2535         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2536         goto end;
2537     }
2538 
2539     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2540     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2541     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2542     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2543     if (pd1->flags != DETECT_PCRE_RELATIVE_NEXT ||
2544         cd2->flags != DETECT_CONTENT_DISTANCE ||
2545         memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2546         hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2547         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2548         hcbd2->flags != DETECT_CONTENT_DISTANCE ||
2549         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2550         goto end;
2551     }
2552 
2553     if (DETECT_CONTENT_IS_SINGLE(cd2) ||
2554         DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2555         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2556         goto end;
2557     }
2558 
2559     result = 1;
2560 
2561  end:
2562     DetectEngineCtxFree(de_ctx);
2563     return result;
2564 }
2565 
DetectHttpClientBodyTest26(void)2566 static int DetectHttpClientBodyTest26(void)
2567 {
2568     DetectEngineCtx *de_ctx = NULL;
2569     int result = 0;
2570 
2571     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2572         goto end;
2573 
2574     de_ctx->flags |= DE_QUIET;
2575     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2576                                "(content:\"one\"; offset:10; http_client_body; pcre:/two/; "
2577                                "content:\"three\"; distance:10; http_client_body; within:10; "
2578                                "content:\"four\"; distance:10; sid:1;)");
2579     if (de_ctx->sig_list == NULL) {
2580         printf("de_ctx->sig_list == NULL\n");
2581         goto end;
2582     }
2583 
2584     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2585         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2586         goto end;
2587     }
2588 
2589     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2590         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2591         goto end;
2592     }
2593 
2594     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2595     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2596     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2597     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2598     if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
2599         cd2->flags != DETECT_CONTENT_DISTANCE ||
2600         memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2601         hcbd1->flags != (DETECT_CONTENT_RELATIVE_NEXT | DETECT_CONTENT_OFFSET) ||
2602         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2603         hcbd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
2604         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2605         printf ("failed: http_client_body incorrect flags");
2606         goto end;
2607     }
2608 
2609     if (DETECT_CONTENT_IS_SINGLE(cd2) ||
2610         DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2611         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2612         goto end;
2613     }
2614 
2615     result = 1;
2616 
2617  end:
2618     DetectEngineCtxFree(de_ctx);
2619     return result;
2620 }
2621 
DetectHttpClientBodyTest27(void)2622 static int DetectHttpClientBodyTest27(void)
2623 {
2624     DetectEngineCtx *de_ctx = NULL;
2625     int result = 0;
2626 
2627     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2628         goto end;
2629 
2630     de_ctx->flags |= DE_QUIET;
2631     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2632                                "(content:\"one\"; offset:10; http_client_body; pcre:/two/; "
2633                                "content:\"three\"; distance:10; http_client_body; within:10; "
2634                                "content:\"four\"; distance:10; sid:1;)");
2635     if (de_ctx->sig_list == NULL) {
2636         printf("de_ctx->sig_list == NULL\n");
2637         goto end;
2638     }
2639 
2640     result = 1;
2641 
2642  end:
2643     DetectEngineCtxFree(de_ctx);
2644     return result;
2645 }
2646 
DetectHttpClientBodyTest28(void)2647 static int DetectHttpClientBodyTest28(void)
2648 {
2649     DetectEngineCtx *de_ctx = NULL;
2650     int result = 0;
2651 
2652     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2653         goto end;
2654 
2655     de_ctx->flags |= DE_QUIET;
2656     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2657                                "(content:\"one\"; http_client_body; pcre:/two/; "
2658                                "content:\"three\"; http_client_body; depth:10; "
2659                                "content:\"four\"; distance:10; sid:1;)");
2660     if (de_ctx->sig_list == NULL) {
2661         printf("de_ctx->sig_list == NULL\n");
2662         goto end;
2663     }
2664 
2665     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
2666         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
2667         goto end;
2668     }
2669 
2670     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2671         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2672         goto end;
2673     }
2674 
2675     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
2676     DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
2677     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2678     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2679     if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
2680         cd2->flags != DETECT_CONTENT_DISTANCE ||
2681         memcmp(cd2->content, "four", cd2->content_len) != 0 ||
2682         hcbd1->flags != 0 ||
2683         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2684         hcbd2->flags != DETECT_CONTENT_DEPTH ||
2685         memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
2686         goto end;
2687     }
2688 
2689     if (DETECT_CONTENT_IS_SINGLE(cd2) ||
2690         !DETECT_CONTENT_IS_SINGLE(hcbd1) ||
2691         DETECT_CONTENT_IS_SINGLE(hcbd2)) {
2692         goto end;
2693     }
2694 
2695     result = 1;
2696 
2697  end:
2698     DetectEngineCtxFree(de_ctx);
2699     return result;
2700 }
2701 
DetectHttpClientBodyTest29(void)2702 static int DetectHttpClientBodyTest29(void)
2703 {
2704     DetectEngineCtx *de_ctx = NULL;
2705     int result = 0;
2706 
2707     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2708         goto end;
2709 
2710     de_ctx->flags |= DE_QUIET;
2711     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2712                                "(content:\"one\"; http_client_body; "
2713                                "content:\"two\"; distance:0; http_client_body; sid:1;)");
2714     if (de_ctx->sig_list == NULL) {
2715         printf("de_ctx->sig_list == NULL\n");
2716         goto end;
2717     }
2718 
2719     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2720         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
2721         goto end;
2722     }
2723 
2724     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2725         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2726         goto end;
2727     }
2728 
2729     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2730     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2731     if (hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2732         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2733         hcbd2->flags != DETECT_CONTENT_DISTANCE ||
2734         memcmp(hcbd2->content, "two", hcbd1->content_len) != 0) {
2735         goto end;
2736     }
2737 
2738     result = 1;
2739 
2740  end:
2741     DetectEngineCtxFree(de_ctx);
2742     return result;
2743 }
2744 
DetectHttpClientBodyTest30(void)2745 static int DetectHttpClientBodyTest30(void)
2746 {
2747     DetectEngineCtx *de_ctx = NULL;
2748     int result = 0;
2749 
2750     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2751         goto end;
2752 
2753     de_ctx->flags |= DE_QUIET;
2754     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2755                                "(content:\"one\"; http_client_body; "
2756                                "content:\"two\"; within:5; http_client_body; sid:1;)");
2757     if (de_ctx->sig_list == NULL) {
2758         printf("de_ctx->sig_list == NULL\n");
2759         goto end;
2760     }
2761 
2762     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2763         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
2764         goto end;
2765     }
2766 
2767     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2768         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2769         goto end;
2770     }
2771 
2772     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2773     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2774     if (hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2775         memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
2776         hcbd2->flags != DETECT_CONTENT_WITHIN ||
2777         memcmp(hcbd2->content, "two", hcbd1->content_len) != 0) {
2778         goto end;
2779     }
2780 
2781     result = 1;
2782 
2783  end:
2784     DetectEngineCtxFree(de_ctx);
2785     return result;
2786 }
2787 
DetectHttpClientBodyTest31(void)2788 static int DetectHttpClientBodyTest31(void)
2789 {
2790     DetectEngineCtx *de_ctx = NULL;
2791     int result = 0;
2792 
2793     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2794         goto end;
2795 
2796     de_ctx->flags |= DE_QUIET;
2797     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2798                                "(content:\"one\"; within:5; http_client_body; sid:1;)");
2799     if (de_ctx->sig_list == NULL) {
2800         printf("de_ctx->sig_list == NULL\n");
2801         goto end;
2802     }
2803 
2804     result = 1;
2805 
2806  end:
2807     DetectEngineCtxFree(de_ctx);
2808     return result;
2809 }
2810 
DetectHttpClientBodyTest32(void)2811 static int DetectHttpClientBodyTest32(void)
2812 {
2813     DetectEngineCtx *de_ctx = NULL;
2814     int result = 0;
2815 
2816     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2817         goto end;
2818 
2819     de_ctx->flags |= DE_QUIET;
2820     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2821                                "(content:\"one\"; http_client_body; within:5; sid:1;)");
2822     if (de_ctx->sig_list == NULL) {
2823         printf("de_ctx->sig_list != NULL\n");
2824         goto end;
2825     }
2826 
2827     result = 1;
2828 
2829  end:
2830     DetectEngineCtxFree(de_ctx);
2831     return result;
2832 }
2833 
DetectHttpClientBodyTest33(void)2834 static int DetectHttpClientBodyTest33(void)
2835 {
2836     DetectEngineCtx *de_ctx = NULL;
2837     int result = 0;
2838 
2839     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2840         goto end;
2841 
2842     de_ctx->flags |= DE_QUIET;
2843     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2844                                "(content:\"one\"; within:5; sid:1;)");
2845     if (de_ctx->sig_list == NULL) {
2846         printf("de_ctx->sig_list == NULL\n");
2847         goto end;
2848     }
2849 
2850     result = 1;
2851 
2852  end:
2853     DetectEngineCtxFree(de_ctx);
2854     return result;
2855 }
2856 
DetectHttpClientBodyTest34(void)2857 static int DetectHttpClientBodyTest34(void)
2858 {
2859     DetectEngineCtx *de_ctx = NULL;
2860     int result = 0;
2861 
2862     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2863         goto end;
2864 
2865     de_ctx->flags |= DE_QUIET;
2866     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2867                                "(pcre:/one/P; "
2868                                "content:\"two\"; within:5; http_client_body; sid:1;)");
2869     if (de_ctx->sig_list == NULL) {
2870         printf("de_ctx->sig_list == NULL\n");
2871         goto end;
2872     }
2873 
2874     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2875         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
2876         goto end;
2877     }
2878 
2879     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2880         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2881         goto end;
2882     }
2883 
2884     if (de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id] == NULL ||
2885         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->type != DETECT_CONTENT ||
2886         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev == NULL ||
2887         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->type != DETECT_PCRE) {
2888 
2889         goto end;
2890     }
2891 
2892     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2893     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2894     if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
2895         hcbd2->flags != DETECT_CONTENT_WITHIN ||
2896         memcmp(hcbd2->content, "two", hcbd2->content_len) != 0) {
2897         goto end;
2898     }
2899 
2900     result = 1;
2901 
2902  end:
2903     DetectEngineCtxFree(de_ctx);
2904     return result;
2905 }
2906 
DetectHttpClientBodyTest35(void)2907 static int DetectHttpClientBodyTest35(void)
2908 {
2909     DetectEngineCtx *de_ctx = NULL;
2910     int result = 0;
2911 
2912     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2913         goto end;
2914 
2915     de_ctx->flags |= DE_QUIET;
2916     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2917                                "(content:\"two\"; http_client_body; "
2918                                "pcre:/one/PR; sid:1;)");
2919     if (de_ctx->sig_list == NULL) {
2920         printf("de_ctx->sig_list == NULL\n");
2921         goto end;
2922     }
2923 
2924     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2925         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
2926         goto end;
2927     }
2928 
2929     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2930         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2931         goto end;
2932     }
2933 
2934     if (de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id] == NULL ||
2935         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->type != DETECT_PCRE ||
2936         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev == NULL ||
2937         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->type != DETECT_CONTENT) {
2938 
2939         goto end;
2940     }
2941 
2942     DetectContentData *hcbd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2943     DetectPcreData *pd2 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2944     if (pd2->flags != (DETECT_PCRE_RELATIVE) ||
2945         hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
2946         memcmp(hcbd1->content, "two", hcbd1->content_len) != 0) {
2947         goto end;
2948     }
2949 
2950     result = 1;
2951 
2952  end:
2953     DetectEngineCtxFree(de_ctx);
2954     return result;
2955 }
2956 
DetectHttpClientBodyTest36(void)2957 static int DetectHttpClientBodyTest36(void)
2958 {
2959     DetectEngineCtx *de_ctx = NULL;
2960     int result = 0;
2961 
2962     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
2963         goto end;
2964 
2965     de_ctx->flags |= DE_QUIET;
2966     de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
2967                                "(pcre:/one/P; "
2968                                "content:\"two\"; distance:5; http_client_body; sid:1;)");
2969     if (de_ctx->sig_list == NULL) {
2970         printf("de_ctx->sig_list == NULL\n");
2971         goto end;
2972     }
2973 
2974     if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2975         printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
2976         goto end;
2977     }
2978 
2979     if (de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL) {
2980         printf("de_ctx->sig_list->sm_lists[g_http_client_body_buffer_id] == NULL\n");
2981         goto end;
2982     }
2983 
2984     if (de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id] == NULL ||
2985         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->type != DETECT_CONTENT ||
2986         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev == NULL ||
2987         de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->type != DETECT_PCRE) {
2988 
2989         goto end;
2990     }
2991 
2992     DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->prev->ctx;
2993     DetectContentData *hcbd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_client_body_buffer_id]->ctx;
2994     if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
2995         hcbd2->flags != DETECT_CONTENT_DISTANCE ||
2996         memcmp(hcbd2->content, "two", hcbd2->content_len) != 0) {
2997         goto end;
2998     }
2999 
3000     result = 1;
3001 
3002  end:
3003     DetectEngineCtxFree(de_ctx);
3004     return result;
3005 }
3006 
DetectHttpClientBodyIsdataatParseTest(void)3007 static int DetectHttpClientBodyIsdataatParseTest(void)
3008 {
3009     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3010     FAIL_IF_NULL(de_ctx);
3011     de_ctx->flags |= DE_QUIET;
3012 
3013     Signature *s = DetectEngineAppendSig(de_ctx,
3014             "alert tcp any any -> any any ("
3015             "content:\"one\"; http_client_body; "
3016             "isdataat:!4,relative; sid:1;)");
3017     FAIL_IF_NULL(s);
3018 
3019     SigMatch *sm = s->init_data->smlists_tail[g_http_client_body_buffer_id];
3020     FAIL_IF_NULL(sm);
3021     FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
3022 
3023     DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
3024     FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
3025     FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
3026     FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
3027 
3028     DetectEngineCtxFree(de_ctx);
3029     PASS;
3030 }
3031 
DetectHttpClientBodyRegisterTests(void)3032 void DetectHttpClientBodyRegisterTests(void)
3033 {
3034     UtRegisterTest("DetectHttpClientBodyParserTest01", DetectHttpClientBodyParserTest01);
3035     UtRegisterTest("DetectHttpClientBodyParserTest02", DetectHttpClientBodyParserTest02);
3036     UtRegisterTest("DetectHttpClientBodyTest01", DetectHttpClientBodyTest01);
3037     UtRegisterTest("DetectHttpClientBodyTest02", DetectHttpClientBodyTest02);
3038     UtRegisterTest("DetectHttpClientBodyTest03", DetectHttpClientBodyTest03);
3039     UtRegisterTest("DetectHttpClientBodyTest04", DetectHttpClientBodyTest04);
3040     UtRegisterTest("DetectHttpClientBodyTest05", DetectHttpClientBodyTest05);
3041     UtRegisterTest("DetectHttpClientBodyTest06", DetectHttpClientBodyTest06);
3042     UtRegisterTest("DetectHttpClientBodyTest07", DetectHttpClientBodyTest07);
3043     UtRegisterTest("DetectHttpClientBodyTest08", DetectHttpClientBodyTest08);
3044     UtRegisterTest("DetectHttpClientBodyTest09", DetectHttpClientBodyTest09);
3045     UtRegisterTest("DetectHttpClientBodyTest10", DetectHttpClientBodyTest10);
3046     UtRegisterTest("DetectHttpClientBodyTest11", DetectHttpClientBodyTest11);
3047     UtRegisterTest("DetectHttpClientBodyTest12", DetectHttpClientBodyTest12);
3048     UtRegisterTest("DetectHttpClientBodyTest13", DetectHttpClientBodyTest13);
3049     UtRegisterTest("DetectHttpClientBodyTest14", DetectHttpClientBodyTest14);
3050     UtRegisterTest("DetectHttpClientBodyTest15", DetectHttpClientBodyTest15);
3051 
3052     UtRegisterTest("DetectHttpClientBodyTest22", DetectHttpClientBodyTest22);
3053     UtRegisterTest("DetectHttpClientBodyTest23", DetectHttpClientBodyTest23);
3054     UtRegisterTest("DetectHttpClientBodyTest24", DetectHttpClientBodyTest24);
3055     UtRegisterTest("DetectHttpClientBodyTest25", DetectHttpClientBodyTest25);
3056     UtRegisterTest("DetectHttpClientBodyTest26", DetectHttpClientBodyTest26);
3057     UtRegisterTest("DetectHttpClientBodyTest27", DetectHttpClientBodyTest27);
3058     UtRegisterTest("DetectHttpClientBodyTest28", DetectHttpClientBodyTest28);
3059     UtRegisterTest("DetectHttpClientBodyTest29", DetectHttpClientBodyTest29);
3060     UtRegisterTest("DetectHttpClientBodyTest30", DetectHttpClientBodyTest30);
3061     UtRegisterTest("DetectHttpClientBodyTest31", DetectHttpClientBodyTest31);
3062     UtRegisterTest("DetectHttpClientBodyTest32", DetectHttpClientBodyTest32);
3063     UtRegisterTest("DetectHttpClientBodyTest33", DetectHttpClientBodyTest33);
3064     UtRegisterTest("DetectHttpClientBodyTest34", DetectHttpClientBodyTest34);
3065     UtRegisterTest("DetectHttpClientBodyTest35", DetectHttpClientBodyTest35);
3066     UtRegisterTest("DetectHttpClientBodyTest36", DetectHttpClientBodyTest36);
3067 
3068     UtRegisterTest("DetectHttpClientBodyIsdataatParseTest",
3069             DetectHttpClientBodyIsdataatParseTest);
3070 
3071     UtRegisterTest("DetectEngineHttpClientBodyTest01",
3072                    DetectEngineHttpClientBodyTest01);
3073     UtRegisterTest("DetectEngineHttpClientBodyTest02",
3074                    DetectEngineHttpClientBodyTest02);
3075     UtRegisterTest("DetectEngineHttpClientBodyTest03",
3076                    DetectEngineHttpClientBodyTest03);
3077     UtRegisterTest("DetectEngineHttpClientBodyTest04",
3078                    DetectEngineHttpClientBodyTest04);
3079     UtRegisterTest("DetectEngineHttpClientBodyTest05",
3080                    DetectEngineHttpClientBodyTest05);
3081     UtRegisterTest("DetectEngineHttpClientBodyTest06",
3082                    DetectEngineHttpClientBodyTest06);
3083     UtRegisterTest("DetectEngineHttpClientBodyTest07",
3084                    DetectEngineHttpClientBodyTest07);
3085     UtRegisterTest("DetectEngineHttpClientBodyTest08",
3086                    DetectEngineHttpClientBodyTest08);
3087     UtRegisterTest("DetectEngineHttpClientBodyTest09",
3088                    DetectEngineHttpClientBodyTest09);
3089     UtRegisterTest("DetectEngineHttpClientBodyTest10",
3090                    DetectEngineHttpClientBodyTest10);
3091     UtRegisterTest("DetectEngineHttpClientBodyTest11",
3092                    DetectEngineHttpClientBodyTest11);
3093     UtRegisterTest("DetectEngineHttpClientBodyTest12",
3094                    DetectEngineHttpClientBodyTest12);
3095     UtRegisterTest("DetectEngineHttpClientBodyTest13",
3096                    DetectEngineHttpClientBodyTest13);
3097     UtRegisterTest("DetectEngineHttpClientBodyTest14",
3098                    DetectEngineHttpClientBodyTest14);
3099     UtRegisterTest("DetectEngineHttpClientBodyTest15",
3100                    DetectEngineHttpClientBodyTest15);
3101     UtRegisterTest("DetectEngineHttpClientBodyTest16",
3102                    DetectEngineHttpClientBodyTest16);
3103     UtRegisterTest("DetectEngineHttpClientBodyTest17",
3104                    DetectEngineHttpClientBodyTest17);
3105     UtRegisterTest("DetectEngineHttpClientBodyTest18",
3106                    DetectEngineHttpClientBodyTest18);
3107     UtRegisterTest("DetectEngineHttpClientBodyTest19",
3108                    DetectEngineHttpClientBodyTest19);
3109     UtRegisterTest("DetectEngineHttpClientBodyTest20",
3110                    DetectEngineHttpClientBodyTest20);
3111     UtRegisterTest("DetectEngineHttpClientBodyTest21",
3112                    DetectEngineHttpClientBodyTest21);
3113     UtRegisterTest("DetectEngineHttpClientBodyTest22",
3114                    DetectEngineHttpClientBodyTest22);
3115     UtRegisterTest("DetectEngineHttpClientBodyTest23",
3116                    DetectEngineHttpClientBodyTest23);
3117     UtRegisterTest("DetectEngineHttpClientBodyTest24",
3118                    DetectEngineHttpClientBodyTest24);
3119     UtRegisterTest("DetectEngineHttpClientBodyTest25",
3120                    DetectEngineHttpClientBodyTest25);
3121     UtRegisterTest("DetectEngineHttpClientBodyTest26",
3122                    DetectEngineHttpClientBodyTest26);
3123     UtRegisterTest("DetectEngineHttpClientBodyTest27",
3124                    DetectEngineHttpClientBodyTest27);
3125     UtRegisterTest("DetectEngineHttpClientBodyTest28",
3126                    DetectEngineHttpClientBodyTest28);
3127     UtRegisterTest("DetectEngineHttpClientBodyTest29",
3128                    DetectEngineHttpClientBodyTest29);
3129 
3130     UtRegisterTest("DetectEngineHttpClientBodyTest30",
3131                    DetectEngineHttpClientBodyTest30);
3132     UtRegisterTest("DetectEngineHttpClientBodyTest31",
3133                    DetectEngineHttpClientBodyTest31);
3134 }
3135 
3136 #endif
3137 
3138 /**
3139  * @}
3140  */
3141