1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \ingroup httplayer
20  *
21  * @{
22  */
23 
24 
25 /** \file
26  *
27  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
28  *
29  * \brief Handle HTTP method match
30  *
31  */
32 
33 #include "../suricata-common.h"
34 #include "../suricata.h"
35 #include "../flow-util.h"
36 #include "../flow.h"
37 #include "../app-layer-parser.h"
38 
39 #include "../util-unittest.h"
40 #include "../util-unittest-helper.h"
41 #include "../app-layer.h"
42 #include "../app-layer-htp.h"
43 #include "../app-layer-protos.h"
44 #include "../detect-isdataat.h"
45 
46 /**
47  * \test Test that the http_method content matches against a http request
48  *       which holds the content.
49  */
DetectEngineHttpMethodTest01(void)50 static int DetectEngineHttpMethodTest01(void)
51 {
52     TcpSession ssn;
53     Packet *p = NULL;
54     ThreadVars th_v;
55     DetectEngineCtx *de_ctx = NULL;
56     DetectEngineThreadCtx *det_ctx = NULL;
57     HtpState *http_state = NULL;
58     Flow f;
59     uint8_t http_buf[] =
60         "GET /index.html HTTP/1.0\r\n"
61         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
62     uint32_t http_len = sizeof(http_buf) - 1;
63     int result = 0;
64     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
65 
66     memset(&th_v, 0, sizeof(th_v));
67     memset(&f, 0, sizeof(f));
68     memset(&ssn, 0, sizeof(ssn));
69 
70     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
71 
72     FLOW_INITIALIZE(&f);
73     f.protoctx = (void *)&ssn;
74     f.proto = IPPROTO_TCP;
75     f.flags |= FLOW_IPV4;
76     p->flow = &f;
77     p->flowflags |= FLOW_PKT_TOSERVER;
78     p->flowflags |= FLOW_PKT_ESTABLISHED;
79     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
80     f.alproto = ALPROTO_HTTP;
81 
82     StreamTcpInitConfig(TRUE);
83 
84     de_ctx = DetectEngineCtxInit();
85     if (de_ctx == NULL)
86         goto end;
87 
88     de_ctx->flags |= DE_QUIET;
89 
90     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
91                                "(msg:\"http header test\"; "
92                                "content:\"GET\"; http_method; "
93                                "sid:1;)");
94     if (de_ctx->sig_list == NULL)
95         goto end;
96 
97     SigGroupBuild(de_ctx);
98     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
99 
100     FLOWLOCK_WRLOCK(&f);
101     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
102                                 STREAM_TOSERVER, http_buf, http_len);
103     if (r != 0) {
104         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
105         result = 0;
106         FLOWLOCK_UNLOCK(&f);
107         goto end;
108     }
109     FLOWLOCK_UNLOCK(&f);
110 
111     http_state = f.alstate;
112     if (http_state == NULL) {
113         printf("no http state: ");
114         result = 0;
115         goto end;
116     }
117 
118     /* do detect */
119     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
120 
121     if (!(PacketAlertCheck(p, 1))) {
122         printf("sid 1 didn't match but should have: ");
123         goto end;
124     }
125 
126     result = 1;
127 
128 end:
129     if (alp_tctx != NULL)
130         AppLayerParserThreadCtxFree(alp_tctx);
131     if (de_ctx != NULL)
132         DetectEngineCtxFree(de_ctx);
133 
134     StreamTcpFreeConfig(TRUE);
135     FLOW_DESTROY(&f);
136     UTHFreePackets(&p, 1);
137     return result;
138 }
139 
140 /**
141  * \test Test that the http_method content matches against a http request
142  *       which holds the content.
143  */
DetectEngineHttpMethodTest02(void)144 static int DetectEngineHttpMethodTest02(void)
145 {
146     TcpSession ssn;
147     Packet *p = NULL;
148     ThreadVars th_v;
149     DetectEngineCtx *de_ctx = NULL;
150     DetectEngineThreadCtx *det_ctx = NULL;
151     HtpState *http_state = NULL;
152     Flow f;
153     uint8_t http_buf[] =
154         "CONNECT /index.html HTTP/1.0\r\n"
155         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
156     uint32_t http_len = sizeof(http_buf) - 1;
157     int result = 0;
158     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
159 
160     memset(&th_v, 0, sizeof(th_v));
161     memset(&f, 0, sizeof(f));
162     memset(&ssn, 0, sizeof(ssn));
163 
164     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
165 
166     FLOW_INITIALIZE(&f);
167     f.protoctx = (void *)&ssn;
168     f.proto = IPPROTO_TCP;
169     f.flags |= FLOW_IPV4;
170     p->flow = &f;
171     p->flowflags |= FLOW_PKT_TOSERVER;
172     p->flowflags |= FLOW_PKT_ESTABLISHED;
173     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
174     f.alproto = ALPROTO_HTTP;
175 
176     StreamTcpInitConfig(TRUE);
177 
178     de_ctx = DetectEngineCtxInit();
179     if (de_ctx == NULL)
180         goto end;
181 
182     de_ctx->flags |= DE_QUIET;
183 
184     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
185                                "(msg:\"http header test\"; "
186                                "content:\"CO\"; depth:4; http_method; "
187                                "sid:1;)");
188     if (de_ctx->sig_list == NULL)
189         goto end;
190 
191     SigGroupBuild(de_ctx);
192     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
193 
194     FLOWLOCK_WRLOCK(&f);
195     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
196                                 STREAM_TOSERVER, http_buf, http_len);
197     if (r != 0) {
198         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
199         result = 0;
200         FLOWLOCK_UNLOCK(&f);
201         goto end;
202     }
203     FLOWLOCK_UNLOCK(&f);
204 
205     http_state = f.alstate;
206     if (http_state == NULL) {
207         printf("no http state: ");
208         result = 0;
209         goto end;
210     }
211 
212     /* do detect */
213     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
214 
215     if (!(PacketAlertCheck(p, 1))) {
216         printf("sid 1 didn't match but should have: ");
217         goto end;
218     }
219 
220     result = 1;
221 
222 end:
223     if (alp_tctx != NULL)
224         AppLayerParserThreadCtxFree(alp_tctx);
225     if (de_ctx != NULL)
226         DetectEngineCtxFree(de_ctx);
227 
228     StreamTcpFreeConfig(TRUE);
229     FLOW_DESTROY(&f);
230     UTHFreePackets(&p, 1);
231     return result;
232 }
233 
234 /**
235  * \test Test that the http_method content matches against a http request
236  *       which holds the content.
237  */
DetectEngineHttpMethodTest03(void)238 static int DetectEngineHttpMethodTest03(void)
239 {
240     TcpSession ssn;
241     Packet *p = NULL;
242     ThreadVars th_v;
243     DetectEngineCtx *de_ctx = NULL;
244     DetectEngineThreadCtx *det_ctx = NULL;
245     HtpState *http_state = NULL;
246     Flow f;
247     uint8_t http_buf[] =
248         "CONNECT /index.html HTTP/1.0\r\n"
249         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
250     uint32_t http_len = sizeof(http_buf) - 1;
251     int result = 0;
252     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
253 
254     memset(&th_v, 0, sizeof(th_v));
255     memset(&f, 0, sizeof(f));
256     memset(&ssn, 0, sizeof(ssn));
257 
258     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
259 
260     FLOW_INITIALIZE(&f);
261     f.protoctx = (void *)&ssn;
262     f.proto = IPPROTO_TCP;
263     f.flags |= FLOW_IPV4;
264     p->flow = &f;
265     p->flowflags |= FLOW_PKT_TOSERVER;
266     p->flowflags |= FLOW_PKT_ESTABLISHED;
267     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
268     f.alproto = ALPROTO_HTTP;
269 
270     StreamTcpInitConfig(TRUE);
271 
272     de_ctx = DetectEngineCtxInit();
273     if (de_ctx == NULL)
274         goto end;
275 
276     de_ctx->flags |= DE_QUIET;
277 
278     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
279                                "(msg:\"http header test\"; "
280                                "content:!\"ECT\"; depth:4; http_method; "
281                                "sid:1;)");
282     if (de_ctx->sig_list == NULL)
283         goto end;
284 
285     SigGroupBuild(de_ctx);
286     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
287 
288     FLOWLOCK_WRLOCK(&f);
289     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
290                                 STREAM_TOSERVER, http_buf, http_len);
291     if (r != 0) {
292         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
293         result = 0;
294         FLOWLOCK_UNLOCK(&f);
295         goto end;
296     }
297     FLOWLOCK_UNLOCK(&f);
298 
299     http_state = f.alstate;
300     if (http_state == NULL) {
301         printf("no http state: ");
302         result = 0;
303         goto end;
304     }
305 
306     /* do detect */
307     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
308 
309     if (!(PacketAlertCheck(p, 1))) {
310         printf("sid 1 didn't match but should have: ");
311         goto end;
312     }
313 
314     result = 1;
315 
316 end:
317     if (alp_tctx != NULL)
318         AppLayerParserThreadCtxFree(alp_tctx);
319     if (de_ctx != NULL)
320         DetectEngineCtxFree(de_ctx);
321 
322     StreamTcpFreeConfig(TRUE);
323     FLOW_DESTROY(&f);
324     UTHFreePackets(&p, 1);
325     return result;
326 }
327 
328 /**
329  * \test Test that the http_method content matches against a http request
330  *       which holds the content.
331  */
DetectEngineHttpMethodTest04(void)332 static int DetectEngineHttpMethodTest04(void)
333 {
334     TcpSession ssn;
335     Packet *p = NULL;
336     ThreadVars th_v;
337     DetectEngineCtx *de_ctx = NULL;
338     DetectEngineThreadCtx *det_ctx = NULL;
339     HtpState *http_state = NULL;
340     Flow f;
341     uint8_t http_buf[] =
342         "CONNECT /index.html HTTP/1.0\r\n"
343         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
344     uint32_t http_len = sizeof(http_buf) - 1;
345     int result = 0;
346     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
347 
348     memset(&th_v, 0, sizeof(th_v));
349     memset(&f, 0, sizeof(f));
350     memset(&ssn, 0, sizeof(ssn));
351 
352     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
353 
354     FLOW_INITIALIZE(&f);
355     f.protoctx = (void *)&ssn;
356     f.proto = IPPROTO_TCP;
357     f.flags |= FLOW_IPV4;
358     p->flow = &f;
359     p->flowflags |= FLOW_PKT_TOSERVER;
360     p->flowflags |= FLOW_PKT_ESTABLISHED;
361     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
362     f.alproto = ALPROTO_HTTP;
363 
364     StreamTcpInitConfig(TRUE);
365 
366     de_ctx = DetectEngineCtxInit();
367     if (de_ctx == NULL)
368         goto end;
369 
370     de_ctx->flags |= DE_QUIET;
371 
372     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
373                                "(msg:\"http header test\"; "
374                                "content:\"ECT\"; depth:4; http_method; "
375                                "sid:1;)");
376     if (de_ctx->sig_list == NULL)
377         goto end;
378 
379     SigGroupBuild(de_ctx);
380     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
381 
382     FLOWLOCK_WRLOCK(&f);
383     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
384                                 STREAM_TOSERVER, http_buf, http_len);
385     if (r != 0) {
386         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
387         result = 0;
388         FLOWLOCK_UNLOCK(&f);
389         goto end;
390     }
391     FLOWLOCK_UNLOCK(&f);
392 
393     http_state = f.alstate;
394     if (http_state == NULL) {
395         printf("no http state: ");
396         result = 0;
397         goto end;
398     }
399 
400     /* do detect */
401     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
402 
403     if (PacketAlertCheck(p, 1)) {
404         printf("sid 1 matched but shouldn't have: ");
405         goto end;
406     }
407 
408     result = 1;
409 
410 end:
411     if (alp_tctx != NULL)
412         AppLayerParserThreadCtxFree(alp_tctx);
413     if (de_ctx != NULL)
414         DetectEngineCtxFree(de_ctx);
415 
416     StreamTcpFreeConfig(TRUE);
417     FLOW_DESTROY(&f);
418     UTHFreePackets(&p, 1);
419     return result;
420 }
421 
422 /**
423  * \test Test that the http_method content matches against a http request
424  *       which holds the content.
425  */
DetectEngineHttpMethodTest05(void)426 static int DetectEngineHttpMethodTest05(void)
427 {
428     TcpSession ssn;
429     Packet *p = NULL;
430     ThreadVars th_v;
431     DetectEngineCtx *de_ctx = NULL;
432     DetectEngineThreadCtx *det_ctx = NULL;
433     HtpState *http_state = NULL;
434     Flow f;
435     uint8_t http_buf[] =
436         "CONNECT /index.html HTTP/1.0\r\n"
437         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
438     uint32_t http_len = sizeof(http_buf) - 1;
439     int result = 0;
440     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
441 
442     memset(&th_v, 0, sizeof(th_v));
443     memset(&f, 0, sizeof(f));
444     memset(&ssn, 0, sizeof(ssn));
445 
446     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
447 
448     FLOW_INITIALIZE(&f);
449     f.protoctx = (void *)&ssn;
450     f.proto = IPPROTO_TCP;
451     f.flags |= FLOW_IPV4;
452     p->flow = &f;
453     p->flowflags |= FLOW_PKT_TOSERVER;
454     p->flowflags |= FLOW_PKT_ESTABLISHED;
455     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
456     f.alproto = ALPROTO_HTTP;
457 
458     StreamTcpInitConfig(TRUE);
459 
460     de_ctx = DetectEngineCtxInit();
461     if (de_ctx == NULL)
462         goto end;
463 
464     de_ctx->flags |= DE_QUIET;
465 
466     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
467                                "(msg:\"http header test\"; "
468                                "content:!\"CON\"; depth:4; http_method; "
469                                "sid:1;)");
470     if (de_ctx->sig_list == NULL)
471         goto end;
472 
473     SigGroupBuild(de_ctx);
474     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
475 
476     FLOWLOCK_WRLOCK(&f);
477     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
478                                 STREAM_TOSERVER, http_buf, http_len);
479     if (r != 0) {
480         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
481         result = 0;
482         FLOWLOCK_UNLOCK(&f);
483         goto end;
484     }
485     FLOWLOCK_UNLOCK(&f);
486 
487     http_state = f.alstate;
488     if (http_state == NULL) {
489         printf("no http state: ");
490         result = 0;
491         goto end;
492     }
493 
494     /* do detect */
495     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
496 
497     if (PacketAlertCheck(p, 1)) {
498         printf("sid 1 matched but shouldn't have: ");
499         goto end;
500     }
501 
502     result = 1;
503 
504 end:
505     if (alp_tctx != NULL)
506         AppLayerParserThreadCtxFree(alp_tctx);
507     if (de_ctx != NULL)
508         DetectEngineCtxFree(de_ctx);
509 
510     StreamTcpFreeConfig(TRUE);
511     FLOW_DESTROY(&f);
512     UTHFreePackets(&p, 1);
513     return result;
514 }
515 
516 /**
517  * \test Test that the http_method content matches against a http request
518  *       which holds the content.
519  */
DetectEngineHttpMethodTest06(void)520 static int DetectEngineHttpMethodTest06(void)
521 {
522     TcpSession ssn;
523     Packet *p = NULL;
524     ThreadVars th_v;
525     DetectEngineCtx *de_ctx = NULL;
526     DetectEngineThreadCtx *det_ctx = NULL;
527     HtpState *http_state = NULL;
528     Flow f;
529     uint8_t http_buf[] =
530         "CONNECT /index.html HTTP/1.0\r\n"
531         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
532     uint32_t http_len = sizeof(http_buf) - 1;
533     int result = 0;
534     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
535 
536     memset(&th_v, 0, sizeof(th_v));
537     memset(&f, 0, sizeof(f));
538     memset(&ssn, 0, sizeof(ssn));
539 
540     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
541 
542     FLOW_INITIALIZE(&f);
543     f.protoctx = (void *)&ssn;
544     f.proto = IPPROTO_TCP;
545     f.flags |= FLOW_IPV4;
546     p->flow = &f;
547     p->flowflags |= FLOW_PKT_TOSERVER;
548     p->flowflags |= FLOW_PKT_ESTABLISHED;
549     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
550     f.alproto = ALPROTO_HTTP;
551 
552     StreamTcpInitConfig(TRUE);
553 
554     de_ctx = DetectEngineCtxInit();
555     if (de_ctx == NULL)
556         goto end;
557 
558     de_ctx->flags |= DE_QUIET;
559 
560     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
561                                "(msg:\"http header test\"; "
562                                "content:\"ECT\"; offset:3; http_method; "
563                                "sid:1;)");
564     if (de_ctx->sig_list == NULL)
565         goto end;
566 
567     SigGroupBuild(de_ctx);
568     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
569 
570     FLOWLOCK_WRLOCK(&f);
571     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
572                                 STREAM_TOSERVER, http_buf, http_len);
573     if (r != 0) {
574         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
575         result = 0;
576         FLOWLOCK_UNLOCK(&f);
577         goto end;
578     }
579     FLOWLOCK_UNLOCK(&f);
580 
581     http_state = f.alstate;
582     if (http_state == NULL) {
583         printf("no http state: ");
584         result = 0;
585         goto end;
586     }
587 
588     /* do detect */
589     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
590 
591     if (!(PacketAlertCheck(p, 1))) {
592         printf("sid 1 didn't match but should have: ");
593         goto end;
594     }
595 
596     result = 1;
597 
598 end:
599     if (alp_tctx != NULL)
600         AppLayerParserThreadCtxFree(alp_tctx);
601     if (de_ctx != NULL)
602         DetectEngineCtxFree(de_ctx);
603 
604     StreamTcpFreeConfig(TRUE);
605     FLOW_DESTROY(&f);
606     UTHFreePackets(&p, 1);
607     return result;
608 }
609 
610 /**
611  * \test Test that the http_method content matches against a http request
612  *       which holds the content.
613  */
DetectEngineHttpMethodTest07(void)614 static int DetectEngineHttpMethodTest07(void)
615 {
616     TcpSession ssn;
617     Packet *p = NULL;
618     ThreadVars th_v;
619     DetectEngineCtx *de_ctx = NULL;
620     DetectEngineThreadCtx *det_ctx = NULL;
621     HtpState *http_state = NULL;
622     Flow f;
623     uint8_t http_buf[] =
624         "CONNECT /index.html HTTP/1.0\r\n"
625         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
626     uint32_t http_len = sizeof(http_buf) - 1;
627     int result = 0;
628     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
629 
630     memset(&th_v, 0, sizeof(th_v));
631     memset(&f, 0, sizeof(f));
632     memset(&ssn, 0, sizeof(ssn));
633 
634     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
635 
636     FLOW_INITIALIZE(&f);
637     f.protoctx = (void *)&ssn;
638     f.proto = IPPROTO_TCP;
639     f.flags |= FLOW_IPV4;
640     p->flow = &f;
641     p->flowflags |= FLOW_PKT_TOSERVER;
642     p->flowflags |= FLOW_PKT_ESTABLISHED;
643     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
644     f.alproto = ALPROTO_HTTP;
645 
646     StreamTcpInitConfig(TRUE);
647 
648     de_ctx = DetectEngineCtxInit();
649     if (de_ctx == NULL)
650         goto end;
651 
652     de_ctx->flags |= DE_QUIET;
653 
654     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
655                                "(msg:\"http header test\"; "
656                                "content:!\"CO\"; offset:3; http_method; "
657                                "sid:1;)");
658     if (de_ctx->sig_list == NULL)
659         goto end;
660 
661     SigGroupBuild(de_ctx);
662     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
663 
664     FLOWLOCK_WRLOCK(&f);
665     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
666                                 STREAM_TOSERVER, http_buf, http_len);
667     if (r != 0) {
668         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
669         result = 0;
670         FLOWLOCK_UNLOCK(&f);
671         goto end;
672     }
673     FLOWLOCK_UNLOCK(&f);
674 
675     http_state = f.alstate;
676     if (http_state == NULL) {
677         printf("no http state: ");
678         result = 0;
679         goto end;
680     }
681 
682     /* do detect */
683     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
684 
685     if (!(PacketAlertCheck(p, 1))) {
686         printf("sid 1 didn't match but should have: ");
687         goto end;
688     }
689 
690     result = 1;
691 
692 end:
693     if (alp_tctx != NULL)
694         AppLayerParserThreadCtxFree(alp_tctx);
695     if (de_ctx != NULL)
696         DetectEngineCtxFree(de_ctx);
697 
698     StreamTcpFreeConfig(TRUE);
699     FLOW_DESTROY(&f);
700     UTHFreePackets(&p, 1);
701     return result;
702 }
703 
704 /**
705  * \test Test that the http_method content matches against a http request
706  *       which holds the content.
707  */
DetectEngineHttpMethodTest08(void)708 static int DetectEngineHttpMethodTest08(void)
709 {
710     TcpSession ssn;
711     Packet *p = NULL;
712     ThreadVars th_v;
713     DetectEngineCtx *de_ctx = NULL;
714     DetectEngineThreadCtx *det_ctx = NULL;
715     HtpState *http_state = NULL;
716     Flow f;
717     uint8_t http_buf[] =
718         "CONNECT /index.html HTTP/1.0\r\n"
719         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
720     uint32_t http_len = sizeof(http_buf) - 1;
721     int result = 0;
722     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
723 
724     memset(&th_v, 0, sizeof(th_v));
725     memset(&f, 0, sizeof(f));
726     memset(&ssn, 0, sizeof(ssn));
727 
728     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
729 
730     FLOW_INITIALIZE(&f);
731     f.protoctx = (void *)&ssn;
732     f.proto = IPPROTO_TCP;
733     f.flags |= FLOW_IPV4;
734     p->flow = &f;
735     p->flowflags |= FLOW_PKT_TOSERVER;
736     p->flowflags |= FLOW_PKT_ESTABLISHED;
737     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
738     f.alproto = ALPROTO_HTTP;
739 
740     StreamTcpInitConfig(TRUE);
741 
742     de_ctx = DetectEngineCtxInit();
743     if (de_ctx == NULL)
744         goto end;
745 
746     de_ctx->flags |= DE_QUIET;
747 
748     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
749                                "(msg:\"http header test\"; "
750                                "content:!\"ECT\"; offset:3; http_method; "
751                                "sid:1;)");
752     if (de_ctx->sig_list == NULL)
753         goto end;
754 
755     SigGroupBuild(de_ctx);
756     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
757 
758     FLOWLOCK_WRLOCK(&f);
759     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
760                                 STREAM_TOSERVER, http_buf, http_len);
761     if (r != 0) {
762         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
763         result = 0;
764         FLOWLOCK_UNLOCK(&f);
765         goto end;
766     }
767     FLOWLOCK_UNLOCK(&f);
768 
769     http_state = f.alstate;
770     if (http_state == NULL) {
771         printf("no http state: ");
772         result = 0;
773         goto end;
774     }
775 
776     /* do detect */
777     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
778 
779     if (PacketAlertCheck(p, 1)) {
780         printf("sid 1 matched but shouldn't have: ");
781         goto end;
782     }
783 
784     result = 1;
785 
786 end:
787     if (alp_tctx != NULL)
788         AppLayerParserThreadCtxFree(alp_tctx);
789     if (de_ctx != NULL)
790         DetectEngineCtxFree(de_ctx);
791 
792     StreamTcpFreeConfig(TRUE);
793     FLOW_DESTROY(&f);
794     UTHFreePackets(&p, 1);
795     return result;
796 }
797 
798 /**
799  * \test Test that the http_method content matches against a http request
800  *       which holds the content.
801  */
DetectEngineHttpMethodTest09(void)802 static int DetectEngineHttpMethodTest09(void)
803 {
804     TcpSession ssn;
805     Packet *p = NULL;
806     ThreadVars th_v;
807     DetectEngineCtx *de_ctx = NULL;
808     DetectEngineThreadCtx *det_ctx = NULL;
809     HtpState *http_state = NULL;
810     Flow f;
811     uint8_t http_buf[] =
812         "CONNECT /index.html HTTP/1.0\r\n"
813         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
814     uint32_t http_len = sizeof(http_buf) - 1;
815     int result = 0;
816     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
817 
818     memset(&th_v, 0, sizeof(th_v));
819     memset(&f, 0, sizeof(f));
820     memset(&ssn, 0, sizeof(ssn));
821 
822     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
823 
824     FLOW_INITIALIZE(&f);
825     f.protoctx = (void *)&ssn;
826     f.proto = IPPROTO_TCP;
827     f.flags |= FLOW_IPV4;
828     p->flow = &f;
829     p->flowflags |= FLOW_PKT_TOSERVER;
830     p->flowflags |= FLOW_PKT_ESTABLISHED;
831     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
832     f.alproto = ALPROTO_HTTP;
833 
834     StreamTcpInitConfig(TRUE);
835 
836     de_ctx = DetectEngineCtxInit();
837     if (de_ctx == NULL)
838         goto end;
839 
840     de_ctx->flags |= DE_QUIET;
841 
842     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
843                                "(msg:\"http header test\"; "
844                                "content:\"CON\"; offset:3; http_method; "
845                                "sid:1;)");
846     if (de_ctx->sig_list == NULL)
847         goto end;
848 
849     SigGroupBuild(de_ctx);
850     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
851 
852     FLOWLOCK_WRLOCK(&f);
853     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
854                                 STREAM_TOSERVER, http_buf, http_len);
855     if (r != 0) {
856         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
857         result = 0;
858         FLOWLOCK_UNLOCK(&f);
859         goto end;
860     }
861     FLOWLOCK_UNLOCK(&f);
862 
863     http_state = f.alstate;
864     if (http_state == NULL) {
865         printf("no http state: ");
866         result = 0;
867         goto end;
868     }
869 
870     /* do detect */
871     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
872 
873     if (PacketAlertCheck(p, 1)) {
874         printf("sid 1 matched but shouldn't have: ");
875         goto end;
876     }
877 
878     result = 1;
879 
880 end:
881     if (alp_tctx != NULL)
882         AppLayerParserThreadCtxFree(alp_tctx);
883     if (de_ctx != NULL)
884         DetectEngineCtxFree(de_ctx);
885 
886     StreamTcpFreeConfig(TRUE);
887     FLOW_DESTROY(&f);
888     UTHFreePackets(&p, 1);
889     return result;
890 }
891 
892 /**
893  * \test Test that the http_method content matches against a http request
894  *       which holds the content.
895  */
DetectEngineHttpMethodTest10(void)896 static int DetectEngineHttpMethodTest10(void)
897 {
898     TcpSession ssn;
899     Packet *p = NULL;
900     ThreadVars th_v;
901     DetectEngineCtx *de_ctx = NULL;
902     DetectEngineThreadCtx *det_ctx = NULL;
903     HtpState *http_state = NULL;
904     Flow f;
905     uint8_t http_buf[] =
906         "CONNECT /index.html HTTP/1.0\r\n"
907         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
908     uint32_t http_len = sizeof(http_buf) - 1;
909     int result = 0;
910     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
911 
912     memset(&th_v, 0, sizeof(th_v));
913     memset(&f, 0, sizeof(f));
914     memset(&ssn, 0, sizeof(ssn));
915 
916     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
917 
918     FLOW_INITIALIZE(&f);
919     f.protoctx = (void *)&ssn;
920     f.proto = IPPROTO_TCP;
921     f.flags |= FLOW_IPV4;
922     p->flow = &f;
923     p->flowflags |= FLOW_PKT_TOSERVER;
924     p->flowflags |= FLOW_PKT_ESTABLISHED;
925     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
926     f.alproto = ALPROTO_HTTP;
927 
928     StreamTcpInitConfig(TRUE);
929 
930     de_ctx = DetectEngineCtxInit();
931     if (de_ctx == NULL)
932         goto end;
933 
934     de_ctx->flags |= DE_QUIET;
935 
936     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
937                                "(msg:\"http header test\"; "
938                                "content:\"CO\"; http_method; "
939                                "content:\"EC\"; within:4; http_method; "
940                                "sid:1;)");
941     if (de_ctx->sig_list == NULL)
942         goto end;
943 
944     SigGroupBuild(de_ctx);
945     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
946 
947     FLOWLOCK_WRLOCK(&f);
948     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
949                                 STREAM_TOSERVER, http_buf, http_len);
950     if (r != 0) {
951         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
952         result = 0;
953         FLOWLOCK_UNLOCK(&f);
954         goto end;
955     }
956     FLOWLOCK_UNLOCK(&f);
957 
958     http_state = f.alstate;
959     if (http_state == NULL) {
960         printf("no http state: ");
961         result = 0;
962         goto end;
963     }
964 
965     /* do detect */
966     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
967 
968     if (!PacketAlertCheck(p, 1)) {
969         printf("sid 1 didn't match but should have: ");
970         goto end;
971     }
972 
973     result = 1;
974 
975 end:
976     if (alp_tctx != NULL)
977         AppLayerParserThreadCtxFree(alp_tctx);
978     if (de_ctx != NULL)
979         DetectEngineCtxFree(de_ctx);
980 
981     StreamTcpFreeConfig(TRUE);
982     FLOW_DESTROY(&f);
983     UTHFreePackets(&p, 1);
984     return result;
985 }
986 
987 /**
988  * \test Test that the http_method content matches against a http request
989  *       which holds the content.
990  */
DetectEngineHttpMethodTest11(void)991 static int DetectEngineHttpMethodTest11(void)
992 {
993     TcpSession ssn;
994     Packet *p = NULL;
995     ThreadVars th_v;
996     DetectEngineCtx *de_ctx = NULL;
997     DetectEngineThreadCtx *det_ctx = NULL;
998     HtpState *http_state = NULL;
999     Flow f;
1000     uint8_t http_buf[] =
1001         "CONNECT /index.html HTTP/1.0\r\n"
1002         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1003     uint32_t http_len = sizeof(http_buf) - 1;
1004     int result = 0;
1005     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1006 
1007     memset(&th_v, 0, sizeof(th_v));
1008     memset(&f, 0, sizeof(f));
1009     memset(&ssn, 0, sizeof(ssn));
1010 
1011     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1012 
1013     FLOW_INITIALIZE(&f);
1014     f.protoctx = (void *)&ssn;
1015     f.proto = IPPROTO_TCP;
1016     f.flags |= FLOW_IPV4;
1017     p->flow = &f;
1018     p->flowflags |= FLOW_PKT_TOSERVER;
1019     p->flowflags |= FLOW_PKT_ESTABLISHED;
1020     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1021     f.alproto = ALPROTO_HTTP;
1022 
1023     StreamTcpInitConfig(TRUE);
1024 
1025     de_ctx = DetectEngineCtxInit();
1026     if (de_ctx == NULL)
1027         goto end;
1028 
1029     de_ctx->flags |= DE_QUIET;
1030 
1031     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1032                                "(msg:\"http header test\"; "
1033                                "content:\"CO\"; http_method; "
1034                                "content:!\"EC\"; within:3; http_method; "
1035                                "sid:1;)");
1036     if (de_ctx->sig_list == NULL)
1037         goto end;
1038 
1039     SigGroupBuild(de_ctx);
1040     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1041 
1042     FLOWLOCK_WRLOCK(&f);
1043     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1044                                 STREAM_TOSERVER, http_buf, http_len);
1045     if (r != 0) {
1046         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1047         result = 0;
1048         FLOWLOCK_UNLOCK(&f);
1049         goto end;
1050     }
1051     FLOWLOCK_UNLOCK(&f);
1052 
1053     http_state = f.alstate;
1054     if (http_state == NULL) {
1055         printf("no http state: ");
1056         result = 0;
1057         goto end;
1058     }
1059 
1060     /* do detect */
1061     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1062 
1063     if (!PacketAlertCheck(p, 1)) {
1064         printf("sid 1 didn't match but should have: ");
1065         goto end;
1066     }
1067 
1068     result = 1;
1069 
1070 end:
1071     if (alp_tctx != NULL)
1072         AppLayerParserThreadCtxFree(alp_tctx);
1073     if (de_ctx != NULL)
1074         DetectEngineCtxFree(de_ctx);
1075 
1076     StreamTcpFreeConfig(TRUE);
1077     FLOW_DESTROY(&f);
1078     UTHFreePackets(&p, 1);
1079     return result;
1080 }
1081 
1082 /**
1083  * \test Test that the http_method content matches against a http request
1084  *       which holds the content.
1085  */
DetectEngineHttpMethodTest12(void)1086 static int DetectEngineHttpMethodTest12(void)
1087 {
1088     TcpSession ssn;
1089     Packet *p = NULL;
1090     ThreadVars th_v;
1091     DetectEngineCtx *de_ctx = NULL;
1092     DetectEngineThreadCtx *det_ctx = NULL;
1093     HtpState *http_state = NULL;
1094     Flow f;
1095     uint8_t http_buf[] =
1096         "CONNECT /index.html HTTP/1.0\r\n"
1097         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1098     uint32_t http_len = sizeof(http_buf) - 1;
1099     int result = 0;
1100     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1101 
1102     memset(&th_v, 0, sizeof(th_v));
1103     memset(&f, 0, sizeof(f));
1104     memset(&ssn, 0, sizeof(ssn));
1105 
1106     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1107 
1108     FLOW_INITIALIZE(&f);
1109     f.protoctx = (void *)&ssn;
1110     f.proto = IPPROTO_TCP;
1111     f.flags |= FLOW_IPV4;
1112     p->flow = &f;
1113     p->flowflags |= FLOW_PKT_TOSERVER;
1114     p->flowflags |= FLOW_PKT_ESTABLISHED;
1115     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1116     f.alproto = ALPROTO_HTTP;
1117 
1118     StreamTcpInitConfig(TRUE);
1119 
1120     de_ctx = DetectEngineCtxInit();
1121     if (de_ctx == NULL)
1122         goto end;
1123 
1124     de_ctx->flags |= DE_QUIET;
1125 
1126     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1127                                "(msg:\"http header test\"; "
1128                                "content:\"CO\"; http_method; "
1129                                "content:\"EC\"; within:3; http_method; "
1130                                "sid:1;)");
1131     if (de_ctx->sig_list == NULL)
1132         goto end;
1133 
1134     SigGroupBuild(de_ctx);
1135     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1136 
1137     FLOWLOCK_WRLOCK(&f);
1138     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1139                                 STREAM_TOSERVER, http_buf, http_len);
1140     if (r != 0) {
1141         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1142         result = 0;
1143         FLOWLOCK_UNLOCK(&f);
1144         goto end;
1145     }
1146     FLOWLOCK_UNLOCK(&f);
1147 
1148     http_state = f.alstate;
1149     if (http_state == NULL) {
1150         printf("no http state: ");
1151         result = 0;
1152         goto end;
1153     }
1154 
1155     /* do detect */
1156     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1157 
1158     if (PacketAlertCheck(p, 1)) {
1159         printf("sid 1 matched but shouldn't have: ");
1160         goto end;
1161     }
1162 
1163     result = 1;
1164 
1165 end:
1166     if (alp_tctx != NULL)
1167         AppLayerParserThreadCtxFree(alp_tctx);
1168     if (de_ctx != NULL)
1169         DetectEngineCtxFree(de_ctx);
1170 
1171     StreamTcpFreeConfig(TRUE);
1172     FLOW_DESTROY(&f);
1173     UTHFreePackets(&p, 1);
1174     return result;
1175 }
1176 
1177 /**
1178  * \test Test that the http_method content matches against a http request
1179  *       which holds the content.
1180  */
DetectEngineHttpMethodTest13(void)1181 static int DetectEngineHttpMethodTest13(void)
1182 {
1183     TcpSession ssn;
1184     Packet *p = NULL;
1185     ThreadVars th_v;
1186     DetectEngineCtx *de_ctx = NULL;
1187     DetectEngineThreadCtx *det_ctx = NULL;
1188     HtpState *http_state = NULL;
1189     Flow f;
1190     uint8_t http_buf[] =
1191         "CONNECT /index.html HTTP/1.0\r\n"
1192         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1193     uint32_t http_len = sizeof(http_buf) - 1;
1194     int result = 0;
1195     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1196 
1197     memset(&th_v, 0, sizeof(th_v));
1198     memset(&f, 0, sizeof(f));
1199     memset(&ssn, 0, sizeof(ssn));
1200 
1201     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1202 
1203     FLOW_INITIALIZE(&f);
1204     f.protoctx = (void *)&ssn;
1205     f.proto = IPPROTO_TCP;
1206     f.flags |= FLOW_IPV4;
1207     p->flow = &f;
1208     p->flowflags |= FLOW_PKT_TOSERVER;
1209     p->flowflags |= FLOW_PKT_ESTABLISHED;
1210     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1211     f.alproto = ALPROTO_HTTP;
1212 
1213     StreamTcpInitConfig(TRUE);
1214 
1215     de_ctx = DetectEngineCtxInit();
1216     if (de_ctx == NULL)
1217         goto end;
1218 
1219     de_ctx->flags |= DE_QUIET;
1220 
1221     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1222                                "(msg:\"http header test\"; "
1223                                "content:\"CO\"; http_method; "
1224                                "content:!\"EC\"; within:4; http_method; "
1225                                "sid:1;)");
1226     if (de_ctx->sig_list == NULL)
1227         goto end;
1228 
1229     SigGroupBuild(de_ctx);
1230     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1231 
1232     FLOWLOCK_WRLOCK(&f);
1233     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1234                                 STREAM_TOSERVER, http_buf, http_len);
1235     if (r != 0) {
1236         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1237         result = 0;
1238         FLOWLOCK_UNLOCK(&f);
1239         goto end;
1240     }
1241     FLOWLOCK_UNLOCK(&f);
1242 
1243     http_state = f.alstate;
1244     if (http_state == NULL) {
1245         printf("no http state: ");
1246         result = 0;
1247         goto end;
1248     }
1249 
1250     /* do detect */
1251     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1252 
1253     if (PacketAlertCheck(p, 1)) {
1254         printf("sid 1 matched but shouldn't have: ");
1255         goto end;
1256     }
1257 
1258     result = 1;
1259 
1260 end:
1261     if (alp_tctx != NULL)
1262         AppLayerParserThreadCtxFree(alp_tctx);
1263     if (de_ctx != NULL)
1264         DetectEngineCtxFree(de_ctx);
1265 
1266     StreamTcpFreeConfig(TRUE);
1267     FLOW_DESTROY(&f);
1268     UTHFreePackets(&p, 1);
1269     return result;
1270 }
1271 
1272 /**
1273  * \test Test that the http_method content matches against a http request
1274  *       which holds the content.
1275  */
DetectEngineHttpMethodTest14(void)1276 static int DetectEngineHttpMethodTest14(void)
1277 {
1278     TcpSession ssn;
1279     Packet *p = NULL;
1280     ThreadVars th_v;
1281     DetectEngineCtx *de_ctx = NULL;
1282     DetectEngineThreadCtx *det_ctx = NULL;
1283     HtpState *http_state = NULL;
1284     Flow f;
1285     uint8_t http_buf[] =
1286         "CONNECT /index.html HTTP/1.0\r\n"
1287         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1288     uint32_t http_len = sizeof(http_buf) - 1;
1289     int result = 0;
1290     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1291 
1292     memset(&th_v, 0, sizeof(th_v));
1293     memset(&f, 0, sizeof(f));
1294     memset(&ssn, 0, sizeof(ssn));
1295 
1296     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1297 
1298     FLOW_INITIALIZE(&f);
1299     f.protoctx = (void *)&ssn;
1300     f.proto = IPPROTO_TCP;
1301     f.flags |= FLOW_IPV4;
1302     p->flow = &f;
1303     p->flowflags |= FLOW_PKT_TOSERVER;
1304     p->flowflags |= FLOW_PKT_ESTABLISHED;
1305     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1306     f.alproto = ALPROTO_HTTP;
1307 
1308     StreamTcpInitConfig(TRUE);
1309 
1310     de_ctx = DetectEngineCtxInit();
1311     if (de_ctx == NULL)
1312         goto end;
1313 
1314     de_ctx->flags |= DE_QUIET;
1315 
1316     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1317                                "(msg:\"http header test\"; "
1318                                "content:\"CO\"; http_method; "
1319                                "content:\"EC\"; distance:2; http_method; "
1320                                "sid:1;)");
1321     if (de_ctx->sig_list == NULL)
1322         goto end;
1323 
1324     SigGroupBuild(de_ctx);
1325     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1326 
1327     FLOWLOCK_WRLOCK(&f);
1328     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1329                                 STREAM_TOSERVER, http_buf, http_len);
1330     if (r != 0) {
1331         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1332         result = 0;
1333         FLOWLOCK_UNLOCK(&f);
1334         goto end;
1335     }
1336     FLOWLOCK_UNLOCK(&f);
1337 
1338     http_state = f.alstate;
1339     if (http_state == NULL) {
1340         printf("no http state: ");
1341         result = 0;
1342         goto end;
1343     }
1344 
1345     /* do detect */
1346     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1347 
1348     if (!PacketAlertCheck(p, 1)) {
1349         printf("sid 1 didn't match but should have: ");
1350         goto end;
1351     }
1352 
1353     result = 1;
1354 
1355 end:
1356     if (alp_tctx != NULL)
1357         AppLayerParserThreadCtxFree(alp_tctx);
1358     if (de_ctx != NULL)
1359         DetectEngineCtxFree(de_ctx);
1360 
1361     StreamTcpFreeConfig(TRUE);
1362     FLOW_DESTROY(&f);
1363     UTHFreePackets(&p, 1);
1364     return result;
1365 }
1366 
1367 /**
1368  * \test Test that the http_method content matches against a http request
1369  *       which holds the content.
1370  */
DetectEngineHttpMethodTest15(void)1371 static int DetectEngineHttpMethodTest15(void)
1372 {
1373     TcpSession ssn;
1374     Packet *p = NULL;
1375     ThreadVars th_v;
1376     DetectEngineCtx *de_ctx = NULL;
1377     DetectEngineThreadCtx *det_ctx = NULL;
1378     HtpState *http_state = NULL;
1379     Flow f;
1380     uint8_t http_buf[] =
1381         "CONNECT /index.html HTTP/1.0\r\n"
1382         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1383     uint32_t http_len = sizeof(http_buf) - 1;
1384     int result = 0;
1385     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1386 
1387     memset(&th_v, 0, sizeof(th_v));
1388     memset(&f, 0, sizeof(f));
1389     memset(&ssn, 0, sizeof(ssn));
1390 
1391     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1392 
1393     FLOW_INITIALIZE(&f);
1394     f.protoctx = (void *)&ssn;
1395     f.proto = IPPROTO_TCP;
1396     f.flags |= FLOW_IPV4;
1397     p->flow = &f;
1398     p->flowflags |= FLOW_PKT_TOSERVER;
1399     p->flowflags |= FLOW_PKT_ESTABLISHED;
1400     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1401     f.alproto = ALPROTO_HTTP;
1402 
1403     StreamTcpInitConfig(TRUE);
1404 
1405     de_ctx = DetectEngineCtxInit();
1406     if (de_ctx == NULL)
1407         goto end;
1408 
1409     de_ctx->flags |= DE_QUIET;
1410 
1411     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1412                                "(msg:\"http header test\"; "
1413                                "content:\"CO\"; http_method; "
1414                                "content:!\"EC\"; distance:3; http_method; "
1415                                "sid:1;)");
1416     if (de_ctx->sig_list == NULL)
1417         goto end;
1418 
1419     SigGroupBuild(de_ctx);
1420     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1421 
1422     FLOWLOCK_WRLOCK(&f);
1423     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1424                                 STREAM_TOSERVER, http_buf, http_len);
1425     if (r != 0) {
1426         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1427         result = 0;
1428         FLOWLOCK_UNLOCK(&f);
1429         goto end;
1430     }
1431     FLOWLOCK_UNLOCK(&f);
1432 
1433     http_state = f.alstate;
1434     if (http_state == NULL) {
1435         printf("no http state: ");
1436         result = 0;
1437         goto end;
1438     }
1439 
1440     /* do detect */
1441     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1442 
1443     if (!PacketAlertCheck(p, 1)) {
1444         printf("sid 1 didn't match but should have: ");
1445         goto end;
1446     }
1447 
1448     result = 1;
1449 
1450 end:
1451     if (alp_tctx != NULL)
1452         AppLayerParserThreadCtxFree(alp_tctx);
1453     if (de_ctx != NULL)
1454         DetectEngineCtxFree(de_ctx);
1455 
1456     StreamTcpFreeConfig(TRUE);
1457     FLOW_DESTROY(&f);
1458     UTHFreePackets(&p, 1);
1459     return result;
1460 }
1461 
1462 /**
1463  * \test Test that the http_method content matches against a http request
1464  *       which holds the content.
1465  */
DetectEngineHttpMethodTest16(void)1466 static int DetectEngineHttpMethodTest16(void)
1467 {
1468     TcpSession ssn;
1469     Packet *p = NULL;
1470     ThreadVars th_v;
1471     DetectEngineCtx *de_ctx = NULL;
1472     DetectEngineThreadCtx *det_ctx = NULL;
1473     HtpState *http_state = NULL;
1474     Flow f;
1475     uint8_t http_buf[] =
1476         "CONNECT /index.html HTTP/1.0\r\n"
1477         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1478     uint32_t http_len = sizeof(http_buf) - 1;
1479     int result = 0;
1480     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1481 
1482     memset(&th_v, 0, sizeof(th_v));
1483     memset(&f, 0, sizeof(f));
1484     memset(&ssn, 0, sizeof(ssn));
1485 
1486     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1487 
1488     FLOW_INITIALIZE(&f);
1489     f.protoctx = (void *)&ssn;
1490     f.proto = IPPROTO_TCP;
1491     f.flags |= FLOW_IPV4;
1492     p->flow = &f;
1493     p->flowflags |= FLOW_PKT_TOSERVER;
1494     p->flowflags |= FLOW_PKT_ESTABLISHED;
1495     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1496     f.alproto = ALPROTO_HTTP;
1497 
1498     StreamTcpInitConfig(TRUE);
1499 
1500     de_ctx = DetectEngineCtxInit();
1501     if (de_ctx == NULL)
1502         goto end;
1503 
1504     de_ctx->flags |= DE_QUIET;
1505 
1506     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1507                                "(msg:\"http header test\"; "
1508                                "content:\"CO\"; http_method; "
1509                                "content:\"EC\"; distance:3; http_method; "
1510                                "sid:1;)");
1511     if (de_ctx->sig_list == NULL)
1512         goto end;
1513 
1514     SigGroupBuild(de_ctx);
1515     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1516 
1517     FLOWLOCK_WRLOCK(&f);
1518     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1519                                 STREAM_TOSERVER, http_buf, http_len);
1520     if (r != 0) {
1521         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1522         result = 0;
1523         FLOWLOCK_UNLOCK(&f);
1524         goto end;
1525     }
1526     FLOWLOCK_UNLOCK(&f);
1527 
1528     http_state = f.alstate;
1529     if (http_state == NULL) {
1530         printf("no http state: ");
1531         result = 0;
1532         goto end;
1533     }
1534 
1535     /* do detect */
1536     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1537 
1538     if (PacketAlertCheck(p, 1)) {
1539         printf("sid 1 matched but shouldn't have: ");
1540         goto end;
1541     }
1542 
1543     result = 1;
1544 
1545 end:
1546     if (alp_tctx != NULL)
1547         AppLayerParserThreadCtxFree(alp_tctx);
1548     if (de_ctx != NULL)
1549         DetectEngineCtxFree(de_ctx);
1550 
1551     StreamTcpFreeConfig(TRUE);
1552     FLOW_DESTROY(&f);
1553     UTHFreePackets(&p, 1);
1554     return result;
1555 }
1556 
1557 /**
1558  * \test Test that the http_method content matches against a http request
1559  *       which holds the content.
1560  */
DetectEngineHttpMethodTest17(void)1561 static int DetectEngineHttpMethodTest17(void)
1562 {
1563     TcpSession ssn;
1564     Packet *p = NULL;
1565     ThreadVars th_v;
1566     DetectEngineCtx *de_ctx = NULL;
1567     DetectEngineThreadCtx *det_ctx = NULL;
1568     HtpState *http_state = NULL;
1569     Flow f;
1570     uint8_t http_buf[] =
1571         "CONNECT /index.html HTTP/1.0\r\n"
1572         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
1573     uint32_t http_len = sizeof(http_buf) - 1;
1574     int result = 0;
1575     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1576 
1577     memset(&th_v, 0, sizeof(th_v));
1578     memset(&f, 0, sizeof(f));
1579     memset(&ssn, 0, sizeof(ssn));
1580 
1581     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1582 
1583     FLOW_INITIALIZE(&f);
1584     f.protoctx = (void *)&ssn;
1585     f.proto = IPPROTO_TCP;
1586     f.flags |= FLOW_IPV4;
1587     p->flow = &f;
1588     p->flowflags |= FLOW_PKT_TOSERVER;
1589     p->flowflags |= FLOW_PKT_ESTABLISHED;
1590     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1591     f.alproto = ALPROTO_HTTP;
1592 
1593     StreamTcpInitConfig(TRUE);
1594 
1595     de_ctx = DetectEngineCtxInit();
1596     if (de_ctx == NULL)
1597         goto end;
1598 
1599     de_ctx->flags |= DE_QUIET;
1600 
1601     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
1602                                "(msg:\"http header test\"; "
1603                                "content:\"CO\"; http_method; "
1604                                "content:!\"EC\"; distance:2; http_method; "
1605                                "sid:1;)");
1606     if (de_ctx->sig_list == NULL)
1607         goto end;
1608 
1609     SigGroupBuild(de_ctx);
1610     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1611 
1612     FLOWLOCK_WRLOCK(&f);
1613     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1614                                 STREAM_TOSERVER, http_buf, http_len);
1615     if (r != 0) {
1616         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1617         result = 0;
1618         FLOWLOCK_UNLOCK(&f);
1619         goto end;
1620     }
1621     FLOWLOCK_UNLOCK(&f);
1622 
1623     http_state = f.alstate;
1624     if (http_state == NULL) {
1625         printf("no http state: ");
1626         result = 0;
1627         goto end;
1628     }
1629 
1630     /* do detect */
1631     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1632 
1633     if (PacketAlertCheck(p, 1)) {
1634         printf("sid 1 matched but shouldn't have: ");
1635         goto end;
1636     }
1637 
1638     result = 1;
1639 
1640 end:
1641     if (alp_tctx != NULL)
1642         AppLayerParserThreadCtxFree(alp_tctx);
1643     if (de_ctx != NULL)
1644         DetectEngineCtxFree(de_ctx);
1645 
1646     StreamTcpFreeConfig(TRUE);
1647     FLOW_DESTROY(&f);
1648     UTHFreePackets(&p, 1);
1649     return result;
1650 }
1651 
1652 /** \test Check a signature with content */
DetectHttpMethodTest01(void)1653 static int DetectHttpMethodTest01(void)
1654 {
1655     DetectEngineCtx *de_ctx = NULL;
1656     int result = 0;
1657 
1658     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1659         goto end;
1660 
1661     de_ctx->flags |= DE_QUIET;
1662     de_ctx->sig_list = SigInit(de_ctx,
1663                                "alert tcp any any -> any any "
1664                                "(msg:\"Testing http_method\"; "
1665                                "content:\"GET\"; "
1666                                "http_method; sid:1;)");
1667 
1668     if (de_ctx->sig_list != NULL) {
1669         result = 1;
1670     } else {
1671         printf("sig parse failed: ");
1672     }
1673 
1674  end:
1675     if (de_ctx != NULL)
1676         DetectEngineCtxFree(de_ctx);
1677     return result;
1678 }
1679 
1680 /** \test Check a signature without content (fail) */
DetectHttpMethodTest02(void)1681 static int DetectHttpMethodTest02(void)
1682 {
1683     DetectEngineCtx *de_ctx = NULL;
1684     int result = 0;
1685 
1686     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1687         goto end;
1688 
1689     de_ctx->flags |= DE_QUIET;
1690     de_ctx->sig_list = SigInit(de_ctx,
1691                                "alert tcp any any -> any any "
1692                                "(msg:\"Testing http_method\"; "
1693                                "http_method; sid:1;)");
1694 
1695     if (de_ctx->sig_list == NULL) {
1696         result = 1;
1697     }
1698 
1699  end:
1700     if (de_ctx != NULL)
1701         DetectEngineCtxFree(de_ctx);
1702     return result;
1703 }
1704 
1705 /** \test Check a signature with parameter (fail) */
DetectHttpMethodTest03(void)1706 static int DetectHttpMethodTest03(void)
1707 {
1708     DetectEngineCtx *de_ctx = NULL;
1709     int result = 0;
1710 
1711     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1712         goto end;
1713 
1714     de_ctx->flags |= DE_QUIET;
1715     de_ctx->sig_list = SigInit(de_ctx,
1716                                "alert tcp any any -> any any "
1717                                "(msg:\"Testing http_method\"; "
1718                                "content:\"foobar\"; "
1719                                "http_method:\"GET\"; sid:1;)");
1720 
1721     if (de_ctx->sig_list == NULL) {
1722         result = 1;
1723     }
1724 
1725  end:
1726     if (de_ctx != NULL)
1727         DetectEngineCtxFree(de_ctx);
1728     return result;
1729 }
1730 
1731 /** \test Check a signature with fast_pattern (should work) */
DetectHttpMethodTest04(void)1732 static int DetectHttpMethodTest04(void)
1733 {
1734     DetectEngineCtx *de_ctx = NULL;
1735     int result = 0;
1736 
1737     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1738         goto end;
1739 
1740     de_ctx->flags |= DE_QUIET;
1741     de_ctx->sig_list = SigInit(de_ctx,
1742                                "alert tcp any any -> any any "
1743                                "(msg:\"Testing http_method\"; "
1744                                "content:\"GET\"; "
1745                                "fast_pattern; "
1746                                "http_method; sid:1;)");
1747 
1748     if (de_ctx->sig_list != NULL) {
1749         result = 1;
1750     }
1751 
1752  end:
1753     if (de_ctx != NULL)
1754         DetectEngineCtxFree(de_ctx);
1755     return result;
1756 }
1757 
1758 /** \test Check a signature with rawbytes (fail) */
DetectHttpMethodTest05(void)1759 static int DetectHttpMethodTest05(void)
1760 {
1761     DetectEngineCtx *de_ctx = NULL;
1762     int result = 0;
1763 
1764     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1765         goto end;
1766 
1767     de_ctx->flags |= DE_QUIET;
1768     de_ctx->sig_list = SigInit(de_ctx,
1769                                "alert tcp any any -> any any "
1770                                "(msg:\"Testing http_method\"; "
1771                                "content:\"GET\"; "
1772                                "rawbytes; "
1773                                "http_method; sid:1;)");
1774 
1775     if (de_ctx->sig_list == NULL) {
1776         result = 1;
1777     }
1778 
1779  end:
1780     if (de_ctx != NULL)
1781         DetectEngineCtxFree(de_ctx);
1782     return result;
1783 }
1784 
1785 /** \test setting the nocase flag */
DetectHttpMethodTest12(void)1786 static int DetectHttpMethodTest12(void)
1787 {
1788     DetectEngineCtx *de_ctx = NULL;
1789     int result = 0;
1790 
1791     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1792         goto end;
1793 
1794     de_ctx->flags |= DE_QUIET;
1795 
1796     if (DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
1797                                "(content:\"one\"; http_method; nocase; sid:1;)") == NULL) {
1798         printf("DetectEngineAppend == NULL: ");
1799         goto end;
1800     }
1801     if (DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
1802                                "(content:\"one\"; nocase; http_method; sid:2;)") == NULL) {
1803         printf("DetectEngineAppend == NULL: ");
1804         goto end;
1805     }
1806 
1807     if (de_ctx->sig_list->sm_lists[g_http_method_buffer_id] == NULL) {
1808         printf("de_ctx->sig_list->sm_lists[g_http_method_buffer_id] == NULL: ");
1809         goto end;
1810     }
1811 
1812     DetectContentData *hmd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_method_buffer_id]->ctx;
1813     DetectContentData *hmd2 = (DetectContentData *)de_ctx->sig_list->next->sm_lists_tail[g_http_method_buffer_id]->ctx;
1814 
1815     if (!(hmd1->flags & DETECT_CONTENT_NOCASE)) {
1816         printf("nocase flag not set on sig 1: ");
1817         goto end;
1818     }
1819 
1820     if (!(hmd2->flags & DETECT_CONTENT_NOCASE)) {
1821         printf("nocase flag not set on sig 2: ");
1822         goto end;
1823     }
1824     result = 1;
1825 
1826  end:
1827     DetectEngineCtxFree(de_ctx);
1828     return result;
1829 }
1830 
1831 /** \test Check a signature with method + within and pcre with /M (should work) */
DetectHttpMethodTest13(void)1832 static int DetectHttpMethodTest13(void)
1833 {
1834     DetectEngineCtx *de_ctx = NULL;
1835     int result = 0;
1836 
1837     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1838         goto end;
1839 
1840     de_ctx->flags |= DE_QUIET;
1841     de_ctx->sig_list = SigInit(de_ctx,
1842                                "alert tcp any any -> any any "
1843                                "(msg:\"Testing http_method\"; "
1844                                "pcre:\"/HE/M\"; "
1845                                "content:\"AD\"; "
1846                                "within:2; http_method; sid:1;)");
1847 
1848     if (de_ctx->sig_list != NULL) {
1849         result = 1;
1850     }
1851 
1852  end:
1853     if (de_ctx != NULL)
1854         DetectEngineCtxFree(de_ctx);
1855     return result;
1856 }
1857 
1858 /** \test Check a signature with method + within and pcre without /M (should fail) */
DetectHttpMethodTest14(void)1859 static int DetectHttpMethodTest14(void)
1860 {
1861     DetectEngineCtx *de_ctx = NULL;
1862     int result = 0;
1863 
1864     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1865         goto end;
1866 
1867     de_ctx->flags |= DE_QUIET;
1868     de_ctx->sig_list = SigInit(de_ctx,
1869                                "alert tcp any any -> any any "
1870                                "(msg:\"Testing http_method\"; "
1871                                "pcre:\"/HE/\"; "
1872                                "content:\"AD\"; "
1873                                "http_method; within:2; sid:1;)");
1874 
1875     if (de_ctx->sig_list != NULL) {
1876         result = 1;
1877     }
1878 
1879  end:
1880     if (de_ctx != NULL)
1881         DetectEngineCtxFree(de_ctx);
1882     return result;
1883 }
1884 
1885 /** \test Check a signature with method + within and pcre with /M (should work) */
DetectHttpMethodTest15(void)1886 static int DetectHttpMethodTest15(void)
1887 {
1888     DetectEngineCtx *de_ctx = NULL;
1889     int result = 0;
1890 
1891     if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1892         goto end;
1893 
1894     de_ctx->flags |= DE_QUIET;
1895     de_ctx->sig_list = SigInit(de_ctx,
1896                                "alert tcp any any -> any any "
1897                                "(msg:\"Testing http_method\"; "
1898                                "pcre:\"/HE/M\"; "
1899                                "content:\"AD\"; "
1900                                "http_method; within:2; sid:1;)");
1901 
1902     if (de_ctx->sig_list != NULL) {
1903         result = 1;
1904     }
1905 
1906  end:
1907     if (de_ctx != NULL)
1908         DetectEngineCtxFree(de_ctx);
1909     return result;
1910 }
1911 /** \test Check a signature with an known request method */
DetectHttpMethodSigTest01(void)1912 static int DetectHttpMethodSigTest01(void)
1913 {
1914     int result = 0;
1915     Flow f;
1916     uint8_t httpbuf1[] = "GET / HTTP/1.0\r\n"
1917                          "Host: foo.bar.tld\r\n"
1918                          "\r\n";
1919     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1920     TcpSession ssn;
1921     Packet *p = NULL;
1922     Signature *s = NULL;
1923     ThreadVars th_v;
1924     DetectEngineThreadCtx *det_ctx;
1925     HtpState *http_state = NULL;
1926     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1927 
1928     memset(&th_v, 0, sizeof(th_v));
1929     memset(&f, 0, sizeof(f));
1930     memset(&ssn, 0, sizeof(ssn));
1931 
1932     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1933 
1934     FLOW_INITIALIZE(&f);
1935     f.protoctx = (void *)&ssn;
1936     f.proto = IPPROTO_TCP;
1937     f.flags |= FLOW_IPV4;
1938 
1939     p->flow = &f;
1940     p->flowflags |= FLOW_PKT_TOSERVER;
1941     p->flowflags |= FLOW_PKT_ESTABLISHED;
1942     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1943     f.alproto = ALPROTO_HTTP;
1944 
1945     StreamTcpInitConfig(TRUE);
1946 
1947     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1948     if (de_ctx == NULL) {
1949         goto end;
1950     }
1951 
1952     de_ctx->flags |= DE_QUIET;
1953 
1954     s = de_ctx->sig_list = SigInit(de_ctx,
1955                                    "alert tcp any any -> any any "
1956                                    "(msg:\"Testing http_method\"; "
1957                                    "content:\"GET\"; "
1958                                    "http_method; sid:1;)");
1959     if (s == NULL) {
1960         goto end;
1961     }
1962 
1963     s = s->next = SigInit(de_ctx,
1964                           "alert tcp any any -> any any "
1965                           "(msg:\"Testing http_method\"; "
1966                           "content:\"POST\"; "
1967                           "http_method; sid:2;)");
1968     if (s == NULL) {
1969         goto end;
1970     }
1971 
1972     SigGroupBuild(de_ctx);
1973     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1974 
1975     FLOWLOCK_WRLOCK(&f);
1976     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1977                                 STREAM_TOSERVER, httpbuf1, httplen1);
1978     if (r != 0) {
1979         SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1980         FLOWLOCK_UNLOCK(&f);
1981         goto end;
1982     }
1983     FLOWLOCK_UNLOCK(&f);
1984 
1985     http_state = f.alstate;
1986     if (http_state == NULL) {
1987         SCLogDebug("no http state: ");
1988         goto end;
1989     }
1990 
1991     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1992 
1993     if (!(PacketAlertCheck(p, 1))) {
1994         goto end;
1995     }
1996     if (PacketAlertCheck(p, 2)) {
1997         goto end;
1998     }
1999 
2000     result = 1;
2001 
2002 end:
2003     if (alp_tctx != NULL)
2004         AppLayerParserThreadCtxFree(alp_tctx);
2005     if (de_ctx != NULL)
2006         DetectEngineCtxFree(de_ctx);
2007 
2008     StreamTcpFreeConfig(TRUE);
2009     FLOW_DESTROY(&f);
2010     UTHFreePackets(&p, 1);
2011     return result;
2012 }
2013 
2014 /** \test Check a signature with an unknown request method */
DetectHttpMethodSigTest02(void)2015 static int DetectHttpMethodSigTest02(void)
2016 {
2017     int result = 0;
2018     Flow f;
2019     uint8_t httpbuf1[] = "FOO / HTTP/1.0\r\n"
2020                          "Host: foo.bar.tld\r\n"
2021                          "\r\n";
2022     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2023     TcpSession ssn;
2024     Packet *p = NULL;
2025     Signature *s = NULL;
2026     ThreadVars th_v;
2027     DetectEngineThreadCtx *det_ctx = NULL;
2028     HtpState *http_state = NULL;
2029     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
2030 
2031     memset(&th_v, 0, sizeof(th_v));
2032     memset(&f, 0, sizeof(f));
2033     memset(&ssn, 0, sizeof(ssn));
2034 
2035     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2036 
2037     FLOW_INITIALIZE(&f);
2038     f.protoctx = (void *)&ssn;
2039     f.proto = IPPROTO_TCP;
2040     f.flags |= FLOW_IPV4;
2041 
2042     p->flow = &f;
2043     p->flowflags |= FLOW_PKT_TOSERVER;
2044     p->flowflags |= FLOW_PKT_ESTABLISHED;
2045     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
2046     f.alproto = ALPROTO_HTTP;
2047 
2048     StreamTcpInitConfig(TRUE);
2049 
2050     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2051     if (de_ctx == NULL) {
2052         goto end;
2053     }
2054 
2055     de_ctx->flags |= DE_QUIET;
2056 
2057     s = de_ctx->sig_list = SigInit(de_ctx,
2058                                    "alert tcp any any -> any any "
2059                                    "(msg:\"Testing http_method\"; "
2060                                    "content:\"FOO\"; "
2061                                    "http_method; sid:1;)");
2062     if (s == NULL) {
2063         goto end;
2064     }
2065 
2066     s = s->next = SigInit(de_ctx,
2067                           "alert tcp any any -> any any "
2068                           "(msg:\"Testing http_method\"; "
2069                           "content:\"BAR\"; "
2070                           "http_method; sid:2;)");
2071     if (s == NULL) {
2072         goto end;
2073     }
2074 
2075     SigGroupBuild(de_ctx);
2076     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2077 
2078     FLOWLOCK_WRLOCK(&f);
2079     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2080                                 STREAM_TOSERVER, httpbuf1, httplen1);
2081     if (r != 0) {
2082         SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2083         FLOWLOCK_UNLOCK(&f);
2084         goto end;
2085     }
2086     FLOWLOCK_UNLOCK(&f);
2087 
2088     http_state = f.alstate;
2089     if (http_state == NULL) {
2090         SCLogDebug("no http state: ");
2091         goto end;
2092     }
2093 
2094     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2095 
2096     if (!(PacketAlertCheck(p, 1))) {
2097         goto end;
2098     }
2099     if (PacketAlertCheck(p, 2)) {
2100         goto end;
2101     }
2102 
2103     result = 1;
2104 
2105 end:
2106     if (alp_tctx != NULL)
2107         AppLayerParserThreadCtxFree(alp_tctx);
2108     if (det_ctx != NULL)
2109         DetectEngineThreadCtxDeinit(&th_v, (void *) det_ctx);
2110     if (de_ctx != NULL)
2111         DetectEngineCtxFree(de_ctx);
2112 
2113     StreamTcpFreeConfig(TRUE);
2114     FLOW_DESTROY(&f);
2115     UTHFreePackets(&p, 1);
2116     return result;
2117 }
2118 
2119 /** \test Check a signature against an unparsable request */
DetectHttpMethodSigTest03(void)2120 static int DetectHttpMethodSigTest03(void)
2121 {
2122     int result = 0;
2123     Flow f;
2124     uint8_t httpbuf1[] = " ";
2125     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2126     TcpSession ssn;
2127     Packet *p = NULL;
2128     Signature *s = NULL;
2129     ThreadVars th_v;
2130     DetectEngineThreadCtx *det_ctx;
2131     HtpState *http_state = NULL;
2132     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
2133 
2134     memset(&th_v, 0, sizeof(th_v));
2135     memset(&f, 0, sizeof(f));
2136     memset(&ssn, 0, sizeof(ssn));
2137 
2138     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2139 
2140     FLOW_INITIALIZE(&f);
2141     f.protoctx = (void *)&ssn;
2142     f.proto = IPPROTO_TCP;
2143     f.flags |= FLOW_IPV4;
2144 
2145     p->flow = &f;
2146     p->flowflags |= FLOW_PKT_TOSERVER;
2147     p->flowflags |= FLOW_PKT_ESTABLISHED;
2148     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
2149     f.alproto = ALPROTO_HTTP;
2150 
2151     StreamTcpInitConfig(TRUE);
2152 
2153     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2154     if (de_ctx == NULL) {
2155         goto end;
2156     }
2157 
2158     de_ctx->flags |= DE_QUIET;
2159 
2160     s = de_ctx->sig_list = SigInit(de_ctx,
2161                                    "alert tcp any any -> any any "
2162                                    "(msg:\"Testing http_method\"; "
2163                                    "content:\"GET\"; "
2164                                    "http_method; sid:1;)");
2165     if (s == NULL) {
2166         SCLogDebug("Bad signature");
2167         goto end;
2168     }
2169 
2170     SigGroupBuild(de_ctx);
2171     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2172 
2173     FLOWLOCK_WRLOCK(&f);
2174     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2175                                 STREAM_TOSERVER, httpbuf1, httplen1);
2176     if (r != 0) {
2177         SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2178         FLOWLOCK_UNLOCK(&f);
2179         goto end;
2180     }
2181     FLOWLOCK_UNLOCK(&f);
2182 
2183     http_state = f.alstate;
2184     if (http_state == NULL) {
2185         SCLogDebug("no http state: ");
2186         goto end;
2187     }
2188 
2189     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2190 
2191     if (PacketAlertCheck(p, 1)) {
2192         goto end;
2193     }
2194 
2195     result = 1;
2196 
2197 end:
2198     if (alp_tctx != NULL)
2199         AppLayerParserThreadCtxFree(alp_tctx);
2200     if (de_ctx != NULL)
2201         DetectEngineCtxFree(de_ctx);
2202 
2203     StreamTcpFreeConfig(TRUE);
2204     FLOW_DESTROY(&f);
2205     UTHFreePackets(&p, 1);
2206     return result;
2207 }
2208 
2209 /** \test Check a signature with an request method and negation of the same */
DetectHttpMethodSigTest04(void)2210 static int DetectHttpMethodSigTest04(void)
2211 {
2212     int result = 0;
2213     Flow f;
2214     uint8_t httpbuf1[] = "GET / HTTP/1.0\r\n"
2215                          "Host: foo.bar.tld\r\n"
2216                          "\r\n";
2217     uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2218     TcpSession ssn;
2219     Packet *p = NULL;
2220     Signature *s = NULL;
2221     ThreadVars th_v;
2222     DetectEngineThreadCtx *det_ctx = NULL;
2223     HtpState *http_state = NULL;
2224     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
2225 
2226     memset(&th_v, 0, sizeof(th_v));
2227     memset(&f, 0, sizeof(f));
2228     memset(&ssn, 0, sizeof(ssn));
2229 
2230     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2231 
2232     FLOW_INITIALIZE(&f);
2233     f.protoctx = (void *)&ssn;
2234     f.proto = IPPROTO_TCP;
2235     f.flags |= FLOW_IPV4;
2236 
2237     p->flow = &f;
2238     p->flowflags |= FLOW_PKT_TOSERVER;
2239     p->flowflags |= FLOW_PKT_ESTABLISHED;
2240     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
2241     f.alproto = ALPROTO_HTTP;
2242 
2243     StreamTcpInitConfig(TRUE);
2244 
2245     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2246     if (de_ctx == NULL) {
2247         goto end;
2248     }
2249 
2250     de_ctx->flags |= DE_QUIET;
2251 
2252     s = de_ctx->sig_list = SigInit(de_ctx,
2253             "alert tcp any any -> any any (msg:\"Testing http_method\"; "
2254             "content:\"GET\"; http_method; sid:1;)");
2255     if (s == NULL) {
2256         goto end;
2257     }
2258 
2259     s = s->next = SigInit(de_ctx,
2260             "alert tcp any any -> any any (msg:\"Testing http_method\"; "
2261             "content:!\"GET\"; http_method; sid:2;)");
2262     if (s == NULL) {
2263         goto end;
2264     }
2265 
2266     SigGroupBuild(de_ctx);
2267     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2268 
2269     FLOWLOCK_WRLOCK(&f);
2270     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2271                                 STREAM_TOSERVER, httpbuf1, httplen1);
2272     if (r != 0) {
2273         SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2274         FLOWLOCK_UNLOCK(&f);
2275         goto end;
2276     }
2277     FLOWLOCK_UNLOCK(&f);
2278 
2279     http_state = f.alstate;
2280     if (http_state == NULL) {
2281         SCLogDebug("no http state: ");
2282         goto end;
2283     }
2284 
2285     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2286 
2287     if (!(PacketAlertCheck(p, 1))) {
2288         printf("sid 1 didn't match but should have: ");
2289         goto end;
2290     }
2291     if (PacketAlertCheck(p, 2)) {
2292         printf("sid 2 matched but shouldn't have: ");
2293         goto end;
2294     }
2295 
2296     result = 1;
2297 
2298 end:
2299     if (alp_tctx != NULL)
2300         AppLayerParserThreadCtxFree(alp_tctx);
2301     if (det_ctx != NULL) {
2302         DetectEngineThreadCtxDeinit(&th_v, (void *) det_ctx);
2303     }
2304     if (de_ctx != NULL) {
2305         DetectEngineCtxFree(de_ctx);
2306     }
2307 
2308     StreamTcpFreeConfig(TRUE);
2309     FLOW_DESTROY(&f);
2310     UTHFreePackets(&p, 1);
2311     return result;
2312 }
2313 
DetectHttpMethodIsdataatParseTest(void)2314 static int DetectHttpMethodIsdataatParseTest(void)
2315 {
2316     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2317     FAIL_IF_NULL(de_ctx);
2318     de_ctx->flags |= DE_QUIET;
2319 
2320     Signature *s = DetectEngineAppendSig(de_ctx,
2321             "alert tcp any any -> any any ("
2322             "content:\"one\"; http_method; "
2323             "isdataat:!4,relative; sid:1;)");
2324     FAIL_IF_NULL(s);
2325 
2326     SigMatch *sm = s->init_data->smlists_tail[g_http_method_buffer_id];
2327     FAIL_IF_NULL(sm);
2328     FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
2329 
2330     DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
2331     FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
2332     FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
2333     FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
2334 
2335     DetectEngineCtxFree(de_ctx);
2336     PASS;
2337 }
2338 
2339 /**
2340  * \brief this function registers unit tests for DetectHttpMethod
2341  */
DetectHttpMethodRegisterTests(void)2342 void DetectHttpMethodRegisterTests(void)
2343 {
2344     UtRegisterTest("DetectHttpMethodTest01", DetectHttpMethodTest01);
2345     UtRegisterTest("DetectHttpMethodTest02", DetectHttpMethodTest02);
2346     UtRegisterTest("DetectHttpMethodTest03", DetectHttpMethodTest03);
2347     UtRegisterTest("DetectHttpMethodTest04", DetectHttpMethodTest04);
2348     UtRegisterTest("DetectHttpMethodTest05", DetectHttpMethodTest05);
2349     UtRegisterTest("DetectHttpMethodTest12 -- nocase flag",
2350                    DetectHttpMethodTest12);
2351     UtRegisterTest("DetectHttpMethodTest13", DetectHttpMethodTest13);
2352     UtRegisterTest("DetectHttpMethodTest14", DetectHttpMethodTest14);
2353     UtRegisterTest("DetectHttpMethodTest15", DetectHttpMethodTest15);
2354     UtRegisterTest("DetectHttpMethodSigTest01", DetectHttpMethodSigTest01);
2355     UtRegisterTest("DetectHttpMethodSigTest02", DetectHttpMethodSigTest02);
2356     UtRegisterTest("DetectHttpMethodSigTest03", DetectHttpMethodSigTest03);
2357     UtRegisterTest("DetectHttpMethodSigTest04", DetectHttpMethodSigTest04);
2358 
2359     UtRegisterTest("DetectHttpMethodIsdataatParseTest",
2360             DetectHttpMethodIsdataatParseTest);
2361     UtRegisterTest("DetectEngineHttpMethodTest01",
2362                    DetectEngineHttpMethodTest01);
2363     UtRegisterTest("DetectEngineHttpMethodTest02",
2364                    DetectEngineHttpMethodTest02);
2365     UtRegisterTest("DetectEngineHttpMethodTest03",
2366                    DetectEngineHttpMethodTest03);
2367     UtRegisterTest("DetectEngineHttpMethodTest04",
2368                    DetectEngineHttpMethodTest04);
2369     UtRegisterTest("DetectEngineHttpMethodTest05",
2370                    DetectEngineHttpMethodTest05);
2371     UtRegisterTest("DetectEngineHttpMethodTest06",
2372                    DetectEngineHttpMethodTest06);
2373     UtRegisterTest("DetectEngineHttpMethodTest07",
2374                    DetectEngineHttpMethodTest07);
2375     UtRegisterTest("DetectEngineHttpMethodTest08",
2376                    DetectEngineHttpMethodTest08);
2377     UtRegisterTest("DetectEngineHttpMethodTest09",
2378                    DetectEngineHttpMethodTest09);
2379     UtRegisterTest("DetectEngineHttpMethodTest10",
2380                    DetectEngineHttpMethodTest10);
2381     UtRegisterTest("DetectEngineHttpMethodTest11",
2382                    DetectEngineHttpMethodTest11);
2383     UtRegisterTest("DetectEngineHttpMethodTest12",
2384                    DetectEngineHttpMethodTest12);
2385     UtRegisterTest("DetectEngineHttpMethodTest13",
2386                    DetectEngineHttpMethodTest13);
2387     UtRegisterTest("DetectEngineHttpMethodTest14",
2388                    DetectEngineHttpMethodTest14);
2389     UtRegisterTest("DetectEngineHttpMethodTest15",
2390                    DetectEngineHttpMethodTest15);
2391     UtRegisterTest("DetectEngineHttpMethodTest16",
2392                    DetectEngineHttpMethodTest16);
2393     UtRegisterTest("DetectEngineHttpMethodTest17",
2394                    DetectEngineHttpMethodTest17);
2395 }
2396 
2397 /**
2398  * @}
2399  */
2400