1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  */
23 
24 #include "suricata-common.h"
25 #include "detect-engine.h"
26 #include "detect-engine-prefilter.h"
27 #include "detect-engine-prefilter-common.h"
28 #include "detect-parse.h"
29 #include "detect-app-layer-protocol.h"
30 #include "app-layer.h"
31 #include "app-layer-parser.h"
32 #include "util-debug.h"
33 #include "util-unittest.h"
34 #include "util-unittest-helper.h"
35 
36 #ifdef UNITTESTS
37 static void DetectAppLayerProtocolRegisterTests(void);
38 #endif
39 
DetectAppLayerProtocolPacketMatch(DetectEngineThreadCtx * det_ctx,Packet * p,const Signature * s,const SigMatchCtx * ctx)40 static int DetectAppLayerProtocolPacketMatch(
41         DetectEngineThreadCtx *det_ctx,
42         Packet *p, const Signature *s, const SigMatchCtx *ctx)
43 {
44     SCEnter();
45 
46     int r = 0;
47     const DetectAppLayerProtocolData *data = (const DetectAppLayerProtocolData *)ctx;
48 
49     /* if the sig is PD-only we only match when PD packet flags are set */
50     if ((s->flags & SIG_FLAG_PDONLY) &&
51         (p->flags & (PKT_PROTO_DETECT_TS_DONE|PKT_PROTO_DETECT_TC_DONE)) == 0)
52     {
53         SCLogDebug("packet %"PRIu64": flags not set", p->pcap_cnt);
54         SCReturnInt(0);
55     }
56 
57     const Flow *f = p->flow;
58     if (f == NULL) {
59         SCLogDebug("packet %"PRIu64": no flow", p->pcap_cnt);
60         SCReturnInt(0);
61     }
62 
63     /* unknown means protocol detection isn't ready yet */
64 
65     if ((f->alproto_ts != ALPROTO_UNKNOWN) && (p->flowflags & FLOW_PKT_TOSERVER))
66     {
67         SCLogDebug("toserver packet %"PRIu64": looking for %u/neg %u, got %u",
68                 p->pcap_cnt, data->alproto, data->negated, f->alproto_ts);
69 
70         r = (data->negated) ? (f->alproto_ts != data->alproto) :
71             (f->alproto_ts == data->alproto);
72 
73     } else if ((f->alproto_tc != ALPROTO_UNKNOWN) && (p->flowflags & FLOW_PKT_TOCLIENT))
74     {
75         SCLogDebug("toclient packet %"PRIu64": looking for %u/neg %u, got %u",
76                 p->pcap_cnt, data->alproto, data->negated, f->alproto_tc);
77 
78         r = (data->negated) ? (f->alproto_tc != data->alproto) :
79             (f->alproto_tc == data->alproto);
80     }
81     else {
82         SCLogDebug("packet %"PRIu64": default case: direction %02x, approtos %u/%u/%u",
83             p->pcap_cnt,
84             p->flowflags & (FLOW_PKT_TOCLIENT|FLOW_PKT_TOSERVER),
85             f->alproto, f->alproto_ts, f->alproto_tc);
86     }
87 
88     SCReturnInt(r);
89 }
90 
DetectAppLayerProtocolParse(const char * arg,bool negate)91 static DetectAppLayerProtocolData *DetectAppLayerProtocolParse(const char *arg, bool negate)
92 {
93     DetectAppLayerProtocolData *data;
94     AppProto alproto = ALPROTO_UNKNOWN;
95 
96     if (strcmp(arg, "failed") == 0) {
97         alproto = ALPROTO_FAILED;
98     } else {
99         alproto = AppLayerGetProtoByName((char *)arg);
100         if (alproto == ALPROTO_UNKNOWN) {
101             SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-protocol "
102                     "keyword supplied with unknown protocol \"%s\"", arg);
103             return NULL;
104         }
105     }
106 
107     data = SCMalloc(sizeof(DetectAppLayerProtocolData));
108     if (unlikely(data == NULL))
109         return NULL;
110     data->alproto = alproto;
111     data->negated = negate;
112 
113     return data;
114 }
115 
HasConflicts(const DetectAppLayerProtocolData * us,const DetectAppLayerProtocolData * them)116 static bool HasConflicts(const DetectAppLayerProtocolData *us,
117                           const DetectAppLayerProtocolData *them)
118 {
119     /* mixing negated and non negated is illegal */
120     if (them->negated ^ us->negated)
121         return TRUE;
122     /* multiple non-negated is illegal */
123     if (!us->negated)
124         return TRUE;
125     /* duplicate option */
126     if (us->alproto == them->alproto)
127         return TRUE;
128 
129     /* all good */
130     return FALSE;
131 }
132 
DetectAppLayerProtocolSetup(DetectEngineCtx * de_ctx,Signature * s,const char * arg)133 static int DetectAppLayerProtocolSetup(DetectEngineCtx *de_ctx,
134         Signature *s, const char *arg)
135 {
136     DetectAppLayerProtocolData *data = NULL;
137     SigMatch *sm = NULL;
138 
139     if (s->alproto != ALPROTO_UNKNOWN) {
140         SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "Either we already "
141                    "have the rule match on an app layer protocol set through "
142                    "other keywords that match on this protocol, or have "
143                    "already seen a non-negated app-layer-protocol.");
144         goto error;
145     }
146 
147     data = DetectAppLayerProtocolParse(arg, s->init_data->negated);
148     if (data == NULL)
149         goto error;
150 
151     SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
152     for ( ; tsm != NULL; tsm = tsm->next) {
153         if (tsm->type == DETECT_AL_APP_LAYER_PROTOCOL) {
154             const DetectAppLayerProtocolData *them = (const DetectAppLayerProtocolData *)tsm->ctx;
155 
156             if (HasConflicts(data, them)) {
157                 SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "can't mix "
158                         "positive app-layer-protocol match with negated "
159                         "match or match for 'failed'.");
160                 goto error;
161             }
162         }
163     }
164 
165     sm = SigMatchAlloc();
166     if (sm == NULL)
167         goto error;
168 
169     sm->type = DETECT_AL_APP_LAYER_PROTOCOL;
170     sm->ctx = (void *)data;
171 
172     SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
173     return 0;
174 
175 error:
176     if (data != NULL)
177         SCFree(data);
178     return -1;
179 }
180 
DetectAppLayerProtocolFree(DetectEngineCtx * de_ctx,void * ptr)181 static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr)
182 {
183     SCFree(ptr);
184     return;
185 }
186 
187 /** \internal
188  *  \brief prefilter function for protocol detect matching
189  */
190 static void
PrefilterPacketAppProtoMatch(DetectEngineThreadCtx * det_ctx,Packet * p,const void * pectx)191 PrefilterPacketAppProtoMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
192 {
193     const PrefilterPacketHeaderCtx *ctx = pectx;
194 
195     if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE) {
196         SCLogDebug("packet %"PRIu64": extra match failed", p->pcap_cnt);
197         SCReturn;
198     }
199 
200     if (p->flow == NULL) {
201         SCLogDebug("packet %"PRIu64": no flow, no alproto", p->pcap_cnt);
202         SCReturn;
203     }
204 
205     if ((p->flags & (PKT_PROTO_DETECT_TS_DONE|PKT_PROTO_DETECT_TC_DONE)) == 0) {
206         SCLogDebug("packet %"PRIu64": flags not set", p->pcap_cnt);
207         SCReturn;
208     }
209 
210     if ((p->flags & PKT_PROTO_DETECT_TS_DONE) && (p->flowflags & FLOW_PKT_TOSERVER))
211     {
212         int r = (ctx->v1.u16[0] == p->flow->alproto_ts) ^ ctx->v1.u8[2];
213         if (r) {
214             PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
215         }
216     } else if ((p->flags & PKT_PROTO_DETECT_TC_DONE) && (p->flowflags & FLOW_PKT_TOCLIENT))
217     {
218         int r = (ctx->v1.u16[0] == p->flow->alproto_tc) ^ ctx->v1.u8[2];
219         if (r) {
220             PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
221         }
222     }
223 }
224 
225 static void
PrefilterPacketAppProtoSet(PrefilterPacketHeaderValue * v,void * smctx)226 PrefilterPacketAppProtoSet(PrefilterPacketHeaderValue *v, void *smctx)
227 {
228     const DetectAppLayerProtocolData *a = smctx;
229     v->u16[0] = a->alproto;
230     v->u8[2] = (uint8_t)a->negated;
231 }
232 
233 static bool
PrefilterPacketAppProtoCompare(PrefilterPacketHeaderValue v,void * smctx)234 PrefilterPacketAppProtoCompare(PrefilterPacketHeaderValue v, void *smctx)
235 {
236     const DetectAppLayerProtocolData *a = smctx;
237     if (v.u16[0] == a->alproto &&
238         v.u8[2] == (uint8_t)a->negated)
239         return TRUE;
240     return FALSE;
241 }
242 
PrefilterSetupAppProto(DetectEngineCtx * de_ctx,SigGroupHead * sgh)243 static int PrefilterSetupAppProto(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
244 {
245     return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_AL_APP_LAYER_PROTOCOL,
246         PrefilterPacketAppProtoSet,
247         PrefilterPacketAppProtoCompare,
248         PrefilterPacketAppProtoMatch);
249 }
250 
PrefilterAppProtoIsPrefilterable(const Signature * s)251 static bool PrefilterAppProtoIsPrefilterable(const Signature *s)
252 {
253     if (s->flags & SIG_FLAG_PDONLY) {
254         SCLogDebug("prefilter on PD %u", s->id);
255         return TRUE;
256     }
257     return FALSE;
258 }
259 
DetectAppLayerProtocolRegister(void)260 void DetectAppLayerProtocolRegister(void)
261 {
262     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
263     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].desc = "match on the detected app-layer protocol";
264     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].url = "/rules/app-layer.html#app-layer-protocol";
265     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Match =
266         DetectAppLayerProtocolPacketMatch;
267     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Setup =
268         DetectAppLayerProtocolSetup;
269     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Free =
270         DetectAppLayerProtocolFree;
271 #ifdef UNITTESTS
272     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].RegisterTests =
273         DetectAppLayerProtocolRegisterTests;
274 #endif
275     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].flags =
276         (SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_HANDLE_NEGATION);
277 
278     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].SetupPrefilter =
279         PrefilterSetupAppProto;
280     sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].SupportsPrefilter =
281         PrefilterAppProtoIsPrefilterable;
282     return;
283 }
284 
285 /**********************************Unittests***********************************/
286 
287 #ifdef UNITTESTS
288 
DetectAppLayerProtocolTest01(void)289 static int DetectAppLayerProtocolTest01(void)
290 {
291     DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", false);
292     FAIL_IF_NULL(data);
293     FAIL_IF(data->alproto != ALPROTO_HTTP);
294     FAIL_IF(data->negated != 0);
295     DetectAppLayerProtocolFree(NULL, data);
296     PASS;
297 }
298 
DetectAppLayerProtocolTest02(void)299 static int DetectAppLayerProtocolTest02(void)
300 {
301     DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", true);
302     FAIL_IF_NULL(data);
303     FAIL_IF(data->alproto != ALPROTO_HTTP);
304     FAIL_IF(data->negated == 0);
305     DetectAppLayerProtocolFree(NULL, data);
306     PASS;
307 }
308 
DetectAppLayerProtocolTest03(void)309 static int DetectAppLayerProtocolTest03(void)
310 {
311     Signature *s = NULL;
312     DetectAppLayerProtocolData *data = NULL;
313     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
314     FAIL_IF_NULL(de_ctx);
315     de_ctx->flags |= DE_QUIET;
316 
317     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
318             "(app-layer-protocol:http; sid:1;)");
319     FAIL_IF_NULL(s);
320 
321     FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
322 
323     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]);
324     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
325 
326     data = (DetectAppLayerProtocolData *)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
327     FAIL_IF(data->alproto != ALPROTO_HTTP);
328     FAIL_IF(data->negated);
329     DetectEngineCtxFree(de_ctx);
330     PASS;
331 }
332 
DetectAppLayerProtocolTest04(void)333 static int DetectAppLayerProtocolTest04(void)
334 {
335     Signature *s = NULL;
336     DetectAppLayerProtocolData *data = NULL;
337     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
338     FAIL_IF_NULL(de_ctx);
339     de_ctx->flags |= DE_QUIET;
340 
341     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
342             "(app-layer-protocol:!http; sid:1;)");
343     FAIL_IF_NULL(s);
344     FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
345     FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
346 
347     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]);
348     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
349 
350     data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
351     FAIL_IF_NULL(data);
352     FAIL_IF(data->alproto != ALPROTO_HTTP);
353     FAIL_IF(data->negated == 0);
354 
355     DetectEngineCtxFree(de_ctx);
356     PASS;
357 }
358 
DetectAppLayerProtocolTest05(void)359 static int DetectAppLayerProtocolTest05(void)
360 {
361     Signature *s = NULL;
362     DetectAppLayerProtocolData *data = NULL;
363     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
364     FAIL_IF_NULL(de_ctx);
365     de_ctx->flags |= DE_QUIET;
366 
367     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
368             "(app-layer-protocol:!http; app-layer-protocol:!smtp; sid:1;)");
369     FAIL_IF_NULL(s);
370     FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
371     FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
372 
373     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]);
374     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
375 
376     data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
377     FAIL_IF_NULL(data);
378     FAIL_IF(data->alproto != ALPROTO_HTTP);
379     FAIL_IF(data->negated == 0);
380 
381     data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->next->ctx;
382     FAIL_IF_NULL(data);
383     FAIL_IF(data->alproto != ALPROTO_SMTP);
384     FAIL_IF(data->negated == 0);
385 
386     DetectEngineCtxFree(de_ctx);
387     PASS;
388 }
389 
DetectAppLayerProtocolTest06(void)390 static int DetectAppLayerProtocolTest06(void)
391 {
392     Signature *s = NULL;
393     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
394     FAIL_IF_NULL(de_ctx);
395     de_ctx->flags |= DE_QUIET;
396 
397     s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
398             "(app-layer-protocol:smtp; sid:1;)");
399     FAIL_IF_NOT_NULL(s);
400     DetectEngineCtxFree(de_ctx);
401     PASS;
402 }
403 
DetectAppLayerProtocolTest07(void)404 static int DetectAppLayerProtocolTest07(void)
405 {
406     Signature *s = NULL;
407     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
408     FAIL_IF_NULL(de_ctx);
409     de_ctx->flags |= DE_QUIET;
410 
411     s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
412             "(app-layer-protocol:!smtp; sid:1;)");
413     FAIL_IF_NOT_NULL(s);
414     DetectEngineCtxFree(de_ctx);
415     PASS;
416 }
417 
DetectAppLayerProtocolTest08(void)418 static int DetectAppLayerProtocolTest08(void)
419 {
420     Signature *s = NULL;
421     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
422     FAIL_IF_NULL(de_ctx);
423     de_ctx->flags |= DE_QUIET;
424 
425     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
426             "(app-layer-protocol:!smtp; app-layer-protocol:http; sid:1;)");
427     FAIL_IF_NOT_NULL(s);
428     DetectEngineCtxFree(de_ctx);
429     PASS;
430 }
431 
DetectAppLayerProtocolTest09(void)432 static int DetectAppLayerProtocolTest09(void)
433 {
434     Signature *s = NULL;
435     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
436     FAIL_IF_NULL(de_ctx);
437     de_ctx->flags |= DE_QUIET;
438 
439     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
440             "(app-layer-protocol:http; app-layer-protocol:!smtp; sid:1;)");
441     FAIL_IF_NOT_NULL(s);
442     DetectEngineCtxFree(de_ctx);
443     PASS;
444 }
445 
DetectAppLayerProtocolTest10(void)446 static int DetectAppLayerProtocolTest10(void)
447 {
448     Signature *s = NULL;
449     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
450     FAIL_IF_NULL(de_ctx);
451     de_ctx->flags |= DE_QUIET;
452 
453     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
454             "(app-layer-protocol:smtp; app-layer-protocol:!http; sid:1;)");
455     FAIL_IF_NOT_NULL(s);
456     DetectEngineCtxFree(de_ctx);
457     PASS;
458 }
459 
DetectAppLayerProtocolTest11(void)460 static int DetectAppLayerProtocolTest11(void)
461 {
462     DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", false);
463     FAIL_IF_NULL(data);
464     FAIL_IF(data->alproto != ALPROTO_FAILED);
465     FAIL_IF(data->negated != 0);
466     DetectAppLayerProtocolFree(NULL, data);
467     PASS;
468 }
469 
DetectAppLayerProtocolTest12(void)470 static int DetectAppLayerProtocolTest12(void)
471 {
472     DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", true);
473     FAIL_IF_NULL(data);
474     FAIL_IF(data->alproto != ALPROTO_FAILED);
475     FAIL_IF(data->negated == 0);
476     DetectAppLayerProtocolFree(NULL, data);
477     PASS;
478 }
479 
DetectAppLayerProtocolTest13(void)480 static int DetectAppLayerProtocolTest13(void)
481 {
482     Signature *s = NULL;
483     DetectAppLayerProtocolData *data = NULL;
484     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
485     FAIL_IF_NULL(de_ctx);
486     de_ctx->flags |= DE_QUIET;
487 
488     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
489             "(app-layer-protocol:failed; sid:1;)");
490     FAIL_IF_NULL(s);
491 
492     FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
493 
494     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]);
495     FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
496 
497     data = (DetectAppLayerProtocolData *)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
498     FAIL_IF(data->alproto != ALPROTO_FAILED);
499     FAIL_IF(data->negated);
500     DetectEngineCtxFree(de_ctx);
501     PASS;
502 }
503 
DetectAppLayerProtocolTest14(void)504 static int DetectAppLayerProtocolTest14(void)
505 {
506     DetectAppLayerProtocolData *data = NULL;
507     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
508     FAIL_IF_NULL(de_ctx);
509     de_ctx->flags |= DE_QUIET;
510 
511     Signature *s1 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
512             "(app-layer-protocol:http; flowbits:set,blah; sid:1;)");
513     FAIL_IF_NULL(s1);
514     FAIL_IF(s1->alproto != ALPROTO_UNKNOWN);
515     FAIL_IF_NULL(s1->sm_lists[DETECT_SM_LIST_MATCH]);
516     FAIL_IF_NULL(s1->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
517     data = (DetectAppLayerProtocolData *)s1->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
518     FAIL_IF(data->alproto != ALPROTO_HTTP);
519     FAIL_IF(data->negated);
520 
521     Signature *s2 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
522             "(app-layer-protocol:http; flow:to_client; sid:2;)");
523     FAIL_IF_NULL(s2);
524     FAIL_IF(s2->alproto != ALPROTO_UNKNOWN);
525     FAIL_IF_NULL(s2->sm_lists[DETECT_SM_LIST_MATCH]);
526     FAIL_IF_NULL(s2->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
527     data = (DetectAppLayerProtocolData *)s2->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
528     FAIL_IF(data->alproto != ALPROTO_HTTP);
529     FAIL_IF(data->negated);
530 
531     /* flow:established and other options not supported for PD-only */
532     Signature *s3 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
533             "(app-layer-protocol:http; flow:to_client,established; sid:3;)");
534     FAIL_IF_NULL(s3);
535     FAIL_IF(s3->alproto != ALPROTO_UNKNOWN);
536     FAIL_IF_NULL(s3->sm_lists[DETECT_SM_LIST_MATCH]);
537     FAIL_IF_NULL(s3->sm_lists[DETECT_SM_LIST_MATCH]->ctx);
538     data = (DetectAppLayerProtocolData *)s3->sm_lists[DETECT_SM_LIST_MATCH]->ctx;
539     FAIL_IF(data->alproto != ALPROTO_HTTP);
540     FAIL_IF(data->negated);
541 
542     SigGroupBuild(de_ctx);
543     FAIL_IF_NOT(s1->flags & SIG_FLAG_PDONLY);
544     FAIL_IF_NOT(s2->flags & SIG_FLAG_PDONLY);
545     FAIL_IF(s3->flags & SIG_FLAG_PDONLY); // failure now
546 
547     DetectEngineCtxFree(de_ctx);
548     PASS;
549 }
550 
551 
DetectAppLayerProtocolRegisterTests(void)552 static void DetectAppLayerProtocolRegisterTests(void)
553 {
554     UtRegisterTest("DetectAppLayerProtocolTest01",
555                    DetectAppLayerProtocolTest01);
556     UtRegisterTest("DetectAppLayerProtocolTest02",
557                    DetectAppLayerProtocolTest02);
558     UtRegisterTest("DetectAppLayerProtocolTest03",
559                    DetectAppLayerProtocolTest03);
560     UtRegisterTest("DetectAppLayerProtocolTest04",
561                    DetectAppLayerProtocolTest04);
562     UtRegisterTest("DetectAppLayerProtocolTest05",
563                    DetectAppLayerProtocolTest05);
564     UtRegisterTest("DetectAppLayerProtocolTest06",
565                    DetectAppLayerProtocolTest06);
566     UtRegisterTest("DetectAppLayerProtocolTest07",
567                    DetectAppLayerProtocolTest07);
568     UtRegisterTest("DetectAppLayerProtocolTest08",
569                    DetectAppLayerProtocolTest08);
570     UtRegisterTest("DetectAppLayerProtocolTest09",
571                    DetectAppLayerProtocolTest09);
572     UtRegisterTest("DetectAppLayerProtocolTest10",
573                    DetectAppLayerProtocolTest10);
574     UtRegisterTest("DetectAppLayerProtocolTest11",
575                    DetectAppLayerProtocolTest11);
576     UtRegisterTest("DetectAppLayerProtocolTest12",
577                    DetectAppLayerProtocolTest12);
578     UtRegisterTest("DetectAppLayerProtocolTest13",
579                    DetectAppLayerProtocolTest13);
580     UtRegisterTest("DetectAppLayerProtocolTest14",
581                    DetectAppLayerProtocolTest14);
582 }
583 #endif /* UNITTESTS */
584