1 /* Copyright (C) 2007-2014 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 Victor Julien <victor@inliniac.net>
22  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  */
24 
25 #include "suricata-common.h"
26 #include "debug.h"
27 #include "decode.h"
28 #include "threads.h"
29 #include "threadvars.h"
30 #include "tm-threads.h"
31 
32 #include "detect.h"
33 #include "detect-engine-port.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-content.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-state.h"
39 
40 #include "util-print.h"
41 #include "util-pool.h"
42 #include "util-unittest.h"
43 #include "util-unittest-helper.h"
44 
45 #include "flow.h"
46 #include "flow-util.h"
47 #include "flow-private.h"
48 
49 #include "stream-tcp-private.h"
50 #include "stream-tcp-reassemble.h"
51 #include "stream-tcp.h"
52 #include "stream.h"
53 
54 #include "app-layer.h"
55 #include "app-layer-protos.h"
56 #include "app-layer-parser.h"
57 #include "app-layer-detect-proto.h"
58 #include "app-layer-expectation.h"
59 
60 #include "conf.h"
61 #include "util-memcmp.h"
62 #include "util-spm.h"
63 #include "util-debug.h"
64 #include "util-validate.h"
65 
66 #include "runmodes.h"
67 
68 typedef struct AppLayerProtoDetectProbingParserElement_ {
69     AppProto alproto;
70     /* \todo don't really need it.  See if you can get rid of it */
71     uint16_t port;
72     /* \todo calculate at runtime and get rid of this var */
73     uint32_t alproto_mask;
74     /* \todo check if we can reduce the bottom 2 vars to uint16_t */
75     /* the min length of data that has to be supplied to invoke the parser */
76     uint32_t min_depth;
77     /* the max length of data after which this parser won't be invoked */
78     uint32_t max_depth;
79 
80     /* the to_server probing parser function */
81     ProbingParserFPtr ProbingParserTs;
82 
83     /* the to_client probing parser function */
84     ProbingParserFPtr ProbingParserTc;
85 
86     struct AppLayerProtoDetectProbingParserElement_ *next;
87 } AppLayerProtoDetectProbingParserElement;
88 
89 typedef struct AppLayerProtoDetectProbingParserPort_ {
90     /* the port no for which probing parser(s) are invoked */
91     uint16_t port;
92 
93     uint32_t alproto_mask;
94 
95     /* the max depth for all the probing parsers registered for this port */
96     uint16_t dp_max_depth;
97     uint16_t sp_max_depth;
98 
99     AppLayerProtoDetectProbingParserElement *dp;
100     AppLayerProtoDetectProbingParserElement *sp;
101 
102     struct AppLayerProtoDetectProbingParserPort_ *next;
103 } AppLayerProtoDetectProbingParserPort;
104 
105 typedef struct AppLayerProtoDetectProbingParser_ {
106     uint8_t ipproto;
107     AppLayerProtoDetectProbingParserPort *port;
108 
109     struct AppLayerProtoDetectProbingParser_ *next;
110 } AppLayerProtoDetectProbingParser;
111 
112 typedef struct AppLayerProtoDetectPMSignature_ {
113     AppProto alproto;
114     uint8_t direction;  /**< direction for midstream */
115     SigIntId id;
116     /* \todo Change this into a non-pointer */
117     DetectContentData *cd;
118     uint16_t pp_min_depth;
119     uint16_t pp_max_depth;
120     ProbingParserFPtr PPFunc;
121     struct AppLayerProtoDetectPMSignature_ *next;
122 } AppLayerProtoDetectPMSignature;
123 
124 typedef struct AppLayerProtoDetectPMCtx_ {
125     uint16_t pp_max_len;
126     uint16_t min_len;
127     MpmCtx mpm_ctx;
128 
129     /** Mapping between pattern id and signature.  As each signature has a
130      *  unique pattern with a unique id, we can lookup the signature by
131      *  the pattern id. */
132     AppLayerProtoDetectPMSignature **map;
133     AppLayerProtoDetectPMSignature *head;
134 
135     /* \todo we don't need this except at setup time.  Get rid of it. */
136     PatIntId max_pat_id;
137     SigIntId max_sig_id;
138 } AppLayerProtoDetectPMCtx;
139 
140 typedef struct AppLayerProtoDetectCtxIpproto_ {
141     /* 0 - toserver, 1 - toclient */
142     AppLayerProtoDetectPMCtx ctx_pm[2];
143 } AppLayerProtoDetectCtxIpproto;
144 
145 /**
146  * \brief The app layer protocol detection context.
147  */
148 typedef struct AppLayerProtoDetectCtx_ {
149     /* Context per ip_proto.
150      * \todo Modify ctx_ipp to hold for only tcp and udp. The rest can be
151      *       implemented if needed.  Waste of space otherwise. */
152     AppLayerProtoDetectCtxIpproto ctx_ipp[FLOW_PROTO_DEFAULT];
153 
154     /* Global SPM thread context prototype. */
155     SpmGlobalThreadCtx *spm_global_thread_ctx;
156 
157     AppLayerProtoDetectProbingParser *ctx_pp;
158 
159     /* Indicates the protocols that have registered themselves
160      * for protocol detection.  This table is independent of the
161      * ipproto. */
162     const char *alproto_names[ALPROTO_MAX];
163 } AppLayerProtoDetectCtx;
164 
165 /**
166  * \brief The app layer protocol detection thread context.
167  */
168 struct AppLayerProtoDetectThreadCtx_ {
169     PrefilterRuleStore pmq;
170     /* The value 2 is for direction(0 - toserver, 1 - toclient). */
171     MpmThreadCtx mpm_tctx[FLOW_PROTO_DEFAULT][2];
172     SpmThreadCtx *spm_thread_ctx;
173 };
174 
175 /* The global app layer proto detection context. */
176 static AppLayerProtoDetectCtx alpd_ctx;
177 
178 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
179                                              uint8_t *ipprotos);
180 
181 /***** Static Internal Calls: Protocol Retrieval *****/
182 
183 /** \internal
184  *  \brief Handle SPM search for Signature
185  *  \param buflen full size of the input buffer
186  *  \param searchlen pattern matching portion of buffer */
AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature * s,AppLayerProtoDetectThreadCtx * tctx,Flow * f,uint8_t flags,const uint8_t * buf,uint16_t buflen,uint16_t searchlen,bool * rflow)187 static AppProto AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature *s,
188         AppLayerProtoDetectThreadCtx *tctx, Flow *f, uint8_t flags, const uint8_t *buf,
189         uint16_t buflen, uint16_t searchlen, bool *rflow)
190 {
191     SCEnter();
192 
193     if (s->cd->offset > searchlen) {
194         SCLogDebug("s->co->offset (%"PRIu16") > searchlen (%"PRIu16")",
195                    s->cd->offset, searchlen);
196         SCReturnUInt(ALPROTO_UNKNOWN);
197     }
198     if (s->cd->depth > searchlen) {
199         SCLogDebug("s->co->depth (%"PRIu16") > searchlen (%"PRIu16")",
200                    s->cd->depth, searchlen);
201         SCReturnUInt(ALPROTO_UNKNOWN);
202     }
203 
204     const uint8_t *sbuf = buf + s->cd->offset;
205     uint16_t ssearchlen = s->cd->depth - s->cd->offset;
206     SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
207                s->cd->offset, s->cd->depth);
208 
209     uint8_t *found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx,
210             sbuf, ssearchlen);
211     if (found == NULL) {
212         SCReturnUInt(ALPROTO_UNKNOWN);
213     }
214 
215     uint8_t direction = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
216     SCLogDebug("matching, s->direction %s, our dir %s",
217             (s->direction & STREAM_TOSERVER) ? "toserver" : "toclient",
218             (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
219     if (s->PPFunc == NULL) {
220         if (direction == s->direction) {
221             SCLogDebug("direction is correct");
222         } else {
223             SCLogDebug("direction is wrong, rflow = true");
224             *rflow = true;
225         }
226     /* validate using Probing Parser */
227     } else {
228         if (s->pp_min_depth > buflen) {
229             SCLogDebug("PP can't be run yet as pp_min_depth %u > buflen %u",
230                     s->pp_min_depth, buflen);
231             SCReturnInt(ALPROTO_UNKNOWN);
232         }
233 
234         uint8_t rdir = 0;
235         AppProto r = s->PPFunc(f, flags, buf, buflen, &rdir);
236         if (r == s->alproto) {
237             SCLogDebug("found %s/%u, rdir %02x reverse_flow? %s",
238                     AppProtoToString(r), r, rdir,
239                     (rdir && direction != rdir) ? "true" : "false");
240             *rflow = (rdir && direction != rdir);
241             SCReturnUInt(s->alproto);
242         } else if (r == ALPROTO_FAILED) {
243             SCReturnUInt(ALPROTO_FAILED);
244         } else {
245             /* unknown: lets see if we will try again later */
246             if (s->pp_max_depth < buflen) {
247                 SCLogDebug("depth reached and answer inconclusive: fail");
248                 SCReturnUInt(ALPROTO_FAILED);
249             }
250             SCReturnUInt(ALPROTO_UNKNOWN);
251         }
252     }
253     SCReturnUInt(s->alproto);
254 }
255 
256 /**
257  *  \retval 0 no matches
258  *  \retval -1 no matches, mpm depth reached
259  */
PMGetProtoInspect(AppLayerProtoDetectThreadCtx * tctx,AppLayerProtoDetectPMCtx * pm_ctx,MpmThreadCtx * mpm_tctx,Flow * f,const uint8_t * buf,uint16_t buflen,uint8_t flags,AppProto * pm_results,bool * rflow)260 static inline int PMGetProtoInspect(AppLayerProtoDetectThreadCtx *tctx,
261         AppLayerProtoDetectPMCtx *pm_ctx, MpmThreadCtx *mpm_tctx, Flow *f, const uint8_t *buf,
262         uint16_t buflen, uint8_t flags, AppProto *pm_results, bool *rflow)
263 {
264     int pm_matches = 0;
265 
266     uint16_t searchlen = MIN(buflen, pm_ctx->mpm_ctx.maxdepth);
267     SCLogDebug("searchlen %u buflen %u", searchlen, buflen);
268 
269     /* do the mpm search */
270     uint32_t search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(
271             &pm_ctx->mpm_ctx, mpm_tctx, &tctx->pmq,
272             buf, searchlen);
273     if (search_cnt == 0) {
274         if (buflen >= pm_ctx->mpm_ctx.maxdepth)
275             return -1;
276         return 0;
277     }
278 
279     /* alproto bit field */
280     uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
281     memset(pm_results_bf, 0, sizeof(pm_results_bf));
282 
283     /* loop through unique pattern id's. Can't use search_cnt here,
284      * as that contains all matches, tctx->pmq.pattern_id_array_cnt
285      * contains only *unique* matches. */
286     for (uint32_t cnt = 0; cnt < tctx->pmq.rule_id_array_cnt; cnt++) {
287         const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.rule_id_array[cnt]];
288         while (s != NULL) {
289             AppProto proto = AppLayerProtoDetectPMMatchSignature(
290                     s, tctx, f, flags, buf, buflen, searchlen, rflow);
291 
292             /* store each unique proto once */
293             if (AppProtoIsValid(proto) &&
294                 !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
295             {
296                 pm_results[pm_matches++] = proto;
297                 pm_results_bf[proto / 8] |= 1 << (proto % 8);
298             }
299             s = s->next;
300         }
301     }
302     if (pm_matches == 0 && buflen >= pm_ctx->pp_max_len) {
303         pm_matches = -2;
304     }
305     PmqReset(&tctx->pmq);
306     return pm_matches;
307 }
308 
309 /** \internal
310  *  \brief Run Pattern Sigs against buffer
311  *  \param direction direction for the patterns
312  *  \param pm_results[out] AppProto array of size ALPROTO_MAX */
AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx * tctx,Flow * f,const uint8_t * buf,uint16_t buflen,uint8_t flags,AppProto * pm_results,bool * rflow)313 static AppProto AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f,
314         const uint8_t *buf, uint16_t buflen, uint8_t flags, AppProto *pm_results, bool *rflow)
315 {
316     SCEnter();
317 
318     pm_results[0] = ALPROTO_UNKNOWN;
319 
320     AppLayerProtoDetectPMCtx *pm_ctx;
321     MpmThreadCtx *mpm_tctx;
322     int m = -1;
323 
324     if (f->protomap >= FLOW_PROTO_DEFAULT)
325         return ALPROTO_FAILED;
326 
327     if (flags & STREAM_TOSERVER) {
328         pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
329         mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
330     } else {
331         pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
332         mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
333     }
334     if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
335         m = PMGetProtoInspect(tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
336     }
337     /* pattern found, yay */
338     if (m > 0) {
339         FLOW_SET_PM_DONE(f, flags);
340         SCReturnUInt((uint16_t)m);
341 
342     /* handle non-found in non-midstream case */
343     } else if (!stream_config.midstream) {
344         /* we can give up if mpm gave no results and its search depth
345          * was reached. */
346         if (m < 0) {
347             FLOW_SET_PM_DONE(f, flags);
348             SCReturnUInt(0);
349         } else if (m == 0) {
350             SCReturnUInt(0);
351         }
352         SCReturnUInt((uint16_t)m);
353 
354     /* handle non-found in midstream case */
355     } else if (m <= 0) {
356         if (flags & STREAM_TOSERVER) {
357             pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
358             mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
359         } else {
360             pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
361             mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
362         }
363         SCLogDebug("no matches and in midstream mode, lets try the "
364                    "*patterns for the other side");
365 
366         int om = -1;
367         if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
368             om = PMGetProtoInspect(
369                     tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
370         }
371         /* found! */
372         if (om > 0) {
373             FLOW_SET_PM_DONE(f, flags);
374             SCReturnUInt((uint16_t)om);
375 
376         /* both sides failed */
377         } else if (om < 0 && m && m < 0) {
378             FLOW_SET_PM_DONE(f, flags);
379             SCReturnUInt(0);
380 
381         /* one side still uncertain */
382         } else if (om == 0 || m == 0) {
383             SCReturnUInt(0);
384         }
385     }
386     SCReturnUInt(0);
387 }
388 
AppLayerProtoDetectGetProbingParser(AppLayerProtoDetectProbingParser * pp,uint8_t ipproto,AppProto alproto)389 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectGetProbingParser(
390         AppLayerProtoDetectProbingParser *pp, uint8_t ipproto, AppProto alproto)
391 {
392     AppLayerProtoDetectProbingParserElement *pp_elem = NULL;
393     AppLayerProtoDetectProbingParserPort *pp_port = NULL;
394 
395     while (pp != NULL) {
396         if (pp->ipproto == ipproto)
397             break;
398         pp = pp->next;
399     }
400     if (pp == NULL)
401         return NULL;
402 
403     pp_port = pp->port;
404     while (pp_port != NULL) {
405         if (pp_port->dp != NULL && pp_port->dp->alproto == alproto) {
406             pp_elem = pp_port->dp;
407             break;
408         }
409         if (pp_port->sp != NULL && pp_port->sp->alproto == alproto) {
410             pp_elem = pp_port->sp;
411             break;
412         }
413         pp_port = pp_port->next;
414     }
415 
416     SCReturnPtr(pp_elem, "AppLayerProtoDetectProbingParserElement *");
417 }
418 
AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser * pp,uint8_t ipproto,uint16_t port)419 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
420                                                                                   uint8_t ipproto,
421                                                                                   uint16_t port)
422 {
423     AppLayerProtoDetectProbingParserPort *pp_port = NULL;
424 
425     while (pp != NULL) {
426         if (pp->ipproto == ipproto)
427             break;
428 
429         pp = pp->next;
430     }
431 
432     if (pp == NULL)
433         goto end;
434 
435     pp_port = pp->port;
436     while (pp_port != NULL) {
437         if (pp_port->port == port || pp_port->port == 0) {
438             break;
439         }
440         pp_port = pp_port->next;
441     }
442 
443  end:
444     SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
445 }
446 
447 
448 /**
449  * \brief Call the probing expectation to see if there is some for this flow.
450  *
451  */
AppLayerProtoDetectPEGetProto(Flow * f,uint8_t ipproto,uint8_t flags)452 static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto, uint8_t flags)
453 {
454     AppProto alproto = ALPROTO_UNKNOWN;
455 
456     SCLogDebug("expectation check for %p (dir %d)", f, flags);
457     FLOW_SET_PE_DONE(f, flags);
458 
459     alproto = AppLayerExpectationHandle(f, flags);
460 
461     return alproto;
462 }
463 
PPGetProto(const AppLayerProtoDetectProbingParserElement * pe,Flow * f,uint8_t flags,const uint8_t * buf,uint32_t buflen,uint32_t * alproto_masks,uint8_t * rdir)464 static inline AppProto PPGetProto(const AppLayerProtoDetectProbingParserElement *pe, Flow *f,
465         uint8_t flags, const uint8_t *buf, uint32_t buflen, uint32_t *alproto_masks, uint8_t *rdir)
466 {
467     while (pe != NULL) {
468         if ((buflen < pe->min_depth)  ||
469             (alproto_masks[0] & pe->alproto_mask)) {
470             pe = pe->next;
471             continue;
472         }
473 
474         AppProto alproto = ALPROTO_UNKNOWN;
475         if (flags & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
476             alproto = pe->ProbingParserTs(f, flags, buf, buflen, rdir);
477         } else if (flags & STREAM_TOCLIENT && pe->ProbingParserTc != NULL) {
478             alproto = pe->ProbingParserTc(f, flags, buf, buflen, rdir);
479         }
480         if (AppProtoIsValid(alproto)) {
481             SCReturnUInt(alproto);
482         }
483         if (alproto == ALPROTO_FAILED ||
484             (pe->max_depth != 0 && buflen > pe->max_depth)) {
485             alproto_masks[0] |= pe->alproto_mask;
486         }
487         pe = pe->next;
488     }
489 
490     SCReturnUInt(ALPROTO_UNKNOWN);
491 }
492 
493 /**
494  * \brief Call the probing parser if it exists for this flow.
495  *
496  * First we check the flow's dp as it's most likely to match. If that didn't
497  * lead to a PP, we try the sp.
498  *
499  */
AppLayerProtoDetectPPGetProto(Flow * f,const uint8_t * buf,uint32_t buflen,uint8_t ipproto,const uint8_t flags,bool * reverse_flow)500 static AppProto AppLayerProtoDetectPPGetProto(Flow *f, const uint8_t *buf, uint32_t buflen,
501         uint8_t ipproto, const uint8_t flags, bool *reverse_flow)
502 {
503     const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
504     const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
505     const AppLayerProtoDetectProbingParserElement *pe0 = NULL;
506     const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
507     const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
508     AppProto alproto = ALPROTO_UNKNOWN;
509     uint32_t *alproto_masks;
510     uint32_t mask = 0;
511     uint8_t idir = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
512     uint8_t dir = idir;
513     uint16_t dp = f->protodetect_dp ? f->protodetect_dp : FLOW_GET_DP(f);
514     uint16_t sp = FLOW_GET_SP(f);
515     bool probe_is_found = false;
516 
517 again_midstream:
518     if (idir != dir) {
519         SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
520     }
521     SCLogDebug("%u->%u %s", sp, dp,
522             (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
523 
524     if (dir == STREAM_TOSERVER) {
525         /* first try the destination port */
526         pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
527         alproto_masks = &f->probing_parser_toserver_alproto_masks;
528         if (pp_port_dp != NULL) {
529             SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);
530 
531             /* found based on destination port, so use dp registration */
532             pe1 = pp_port_dp->dp;
533         } else {
534             SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
535         }
536 
537         pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
538         if (pp_port_sp != NULL) {
539             SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);
540 
541             /* found based on source port, so use sp registration */
542             pe2 = pp_port_sp->sp;
543         } else {
544             SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
545         }
546     } else {
547         /* first try the destination port */
548         pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
549         alproto_masks = &f->probing_parser_toclient_alproto_masks;
550         if (pp_port_dp != NULL) {
551             SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);
552 
553             /* found based on destination port, so use dp registration */
554             pe1 = pp_port_dp->dp;
555         } else {
556             SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
557         }
558 
559         pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
560         if (pp_port_sp != NULL) {
561             SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);
562 
563             pe2 = pp_port_sp->sp;
564         } else {
565             SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
566         }
567     }
568 
569     if (dir == STREAM_TOSERVER && f->alproto_tc != ALPROTO_UNKNOWN) {
570         pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_tc);
571     } else if (dir == STREAM_TOCLIENT && f->alproto_ts != ALPROTO_UNKNOWN) {
572         pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_ts);
573     }
574 
575     if (pe1 == NULL && pe2 == NULL && pe0 == NULL) {
576         SCLogDebug("%s - No probing parsers found for either port",
577                 (dir == STREAM_TOSERVER) ? "toserver":"toclient");
578         goto noparsers;
579     } else {
580         probe_is_found = true;
581     }
582 
583     /* run the parser(s): always call with original direction */
584     uint8_t rdir = 0;
585     alproto = PPGetProto(pe0, f, flags, buf, buflen, alproto_masks, &rdir);
586     if (AppProtoIsValid(alproto))
587         goto end;
588     alproto = PPGetProto(pe1, f, flags, buf, buflen, alproto_masks, &rdir);
589     if (AppProtoIsValid(alproto))
590         goto end;
591     alproto = PPGetProto(pe2, f, flags, buf, buflen, alproto_masks, &rdir);
592     if (AppProtoIsValid(alproto))
593         goto end;
594 
595     /* get the mask we need for this direction */
596     if (dir == idir) {
597         if (pp_port_dp && pp_port_sp)
598             mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
599         else if (pp_port_dp)
600             mask = pp_port_dp->alproto_mask;
601         else if (pp_port_sp)
602             mask = pp_port_sp->alproto_mask;
603 
604         if (alproto_masks[0] == mask) {
605             FLOW_SET_PP_DONE(f, dir);
606             SCLogDebug("%s, mask is now %08x, needed %08x, so done",
607                     (dir == STREAM_TOSERVER) ? "toserver":"toclient",
608                     alproto_masks[0], mask);
609         } else {
610             SCLogDebug("%s, mask is now %08x, need %08x",
611                     (dir == STREAM_TOSERVER) ? "toserver":"toclient",
612                     alproto_masks[0], mask);
613         }
614     }
615 
616 noparsers:
617     if (stream_config.midstream && idir == dir) {
618         if (idir == STREAM_TOSERVER) {
619             dir = STREAM_TOCLIENT;
620         } else {
621             dir = STREAM_TOSERVER;
622         }
623         SCLogDebug("no match + midstream, retry the other direction %s",
624                 (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
625         goto again_midstream;
626     } else if (!probe_is_found) {
627         FLOW_SET_PP_DONE(f, idir);
628     }
629 
630  end:
631     if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
632         SCLogDebug("PP found %u, is reverse flow", alproto);
633         *reverse_flow = true;
634     }
635 
636     SCLogDebug("%s, mask is now %08x",
637             (idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
638     SCReturnUInt(alproto);
639 }
640 
641 /***** Static Internal Calls: PP registration *****/
642 
AppLayerProtoDetectPPGetIpprotos(AppProto alproto,uint8_t * ipprotos)643 static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
644                                              uint8_t *ipprotos)
645 {
646     SCEnter();
647 
648     const AppLayerProtoDetectProbingParser *pp;
649     const AppLayerProtoDetectProbingParserPort *pp_port;
650     const AppLayerProtoDetectProbingParserElement *pp_pe;
651 
652     for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
653         for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
654             for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
655                 if (alproto == pp_pe->alproto)
656                     ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
657             }
658             for (pp_pe = pp_port->sp; pp_pe != NULL; pp_pe = pp_pe->next) {
659                 if (alproto == pp_pe->alproto)
660                     ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
661             }
662         }
663     }
664 
665     SCReturn;
666 }
667 
AppLayerProtoDetectProbingParserGetMask(AppProto alproto)668 static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
669 {
670     SCEnter();
671 
672     if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
673         FatalError(SC_ERR_ALPARSER, "Unknown protocol detected - %u", alproto);
674     }
675 
676     SCReturnUInt(1UL << (uint32_t)alproto);
677 }
678 
AppLayerProtoDetectProbingParserElementAlloc(void)679 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
680 {
681     SCEnter();
682 
683     AppLayerProtoDetectProbingParserElement *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement));
684     if (unlikely(p == NULL)) {
685         exit(EXIT_FAILURE);
686     }
687     memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
688 
689     SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
690 }
691 
692 
AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement * p)693 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
694 {
695     SCEnter();
696     SCFree(p);
697     SCReturn;
698 }
699 
AppLayerProtoDetectProbingParserPortAlloc(void)700 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
701 {
702     SCEnter();
703 
704     AppLayerProtoDetectProbingParserPort *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort));
705     if (unlikely(p == NULL)) {
706         exit(EXIT_FAILURE);
707     }
708     memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
709 
710     SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
711 }
712 
AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort * p)713 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
714 {
715     SCEnter();
716 
717     AppLayerProtoDetectProbingParserElement *e;
718 
719     e = p->dp;
720     while (e != NULL) {
721         AppLayerProtoDetectProbingParserElement *e_next = e->next;
722         AppLayerProtoDetectProbingParserElementFree(e);
723         e = e_next;
724     }
725 
726     e = p->sp;
727     while (e != NULL) {
728         AppLayerProtoDetectProbingParserElement *e_next = e->next;
729         AppLayerProtoDetectProbingParserElementFree(e);
730         e = e_next;
731     }
732 
733     SCFree(p);
734 
735     SCReturn;
736 }
737 
AppLayerProtoDetectProbingParserAlloc(void)738 static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
739 {
740     SCEnter();
741 
742     AppLayerProtoDetectProbingParser *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParser));
743     if (unlikely(p == NULL)) {
744         exit(EXIT_FAILURE);
745     }
746     memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
747 
748     SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
749 }
750 
AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser * p)751 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
752 {
753     SCEnter();
754 
755     AppLayerProtoDetectProbingParserPort *pt = p->port;
756     while (pt != NULL) {
757         AppLayerProtoDetectProbingParserPort *pt_next = pt->next;
758         AppLayerProtoDetectProbingParserPortFree(pt);
759         pt = pt_next;
760     }
761 
762     SCFree(p);
763 
764     SCReturn;
765 }
766 
767 static AppLayerProtoDetectProbingParserElement *
AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,uint16_t port,uint16_t min_depth,uint16_t max_depth)768 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
769                                               uint16_t port,
770                                               uint16_t min_depth,
771                                               uint16_t max_depth)
772 {
773     AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
774 
775     pe->alproto = alproto;
776     pe->port = port;
777     pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
778     pe->min_depth = min_depth;
779     pe->max_depth = max_depth;
780     pe->next = NULL;
781 
782     if (max_depth != 0 && min_depth >= max_depth) {
783         SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
784                    "register the probing parser.  min_depth >= max_depth");
785         goto error;
786     }
787     if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
788         SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to register "
789                    "the probing parser.  Invalid alproto - %d", alproto);
790         goto error;
791     }
792 
793     SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
794  error:
795     AppLayerProtoDetectProbingParserElementFree(pe);
796     SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
797 }
798 
799 static AppLayerProtoDetectProbingParserElement *
AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement * pe)800 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
801 {
802     SCEnter();
803 
804     AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
805 
806     new_pe->alproto = pe->alproto;
807     new_pe->port = pe->port;
808     new_pe->alproto_mask = pe->alproto_mask;
809     new_pe->min_depth = pe->min_depth;
810     new_pe->max_depth = pe->max_depth;
811     new_pe->ProbingParserTs = pe->ProbingParserTs;
812     new_pe->ProbingParserTc = pe->ProbingParserTc;
813     new_pe->next = NULL;
814 
815     SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
816 }
817 
818 #ifdef DEBUG
AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser * pp)819 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
820 {
821     SCEnter();
822 
823     AppLayerProtoDetectProbingParserPort *pp_port = NULL;
824     AppLayerProtoDetectProbingParserElement *pp_pe = NULL;
825 
826     printf("\nProtocol Detection Configuration\n");
827 
828     for ( ; pp != NULL; pp = pp->next) {
829         /* print ip protocol */
830         if (pp->ipproto == IPPROTO_TCP)
831             printf("IPProto: TCP\n");
832         else if (pp->ipproto == IPPROTO_UDP)
833             printf("IPProto: UDP\n");
834         else
835             printf("IPProto: %"PRIu8"\n", pp->ipproto);
836 
837         pp_port = pp->port;
838         for ( ; pp_port != NULL; pp_port = pp_port->next) {
839             if (pp_port->dp != NULL) {
840                 printf("    Port: %"PRIu16 "\n", pp_port->port);
841 
842                 printf("        Destination port: (max-depth: %"PRIu16 ", "
843                         "mask - %"PRIu32")\n",
844                         pp_port->dp_max_depth,
845                         pp_port->alproto_mask);
846                 pp_pe = pp_port->dp;
847                 for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
848 
849                     if (pp_pe->alproto == ALPROTO_HTTP)
850                         printf("            alproto: ALPROTO_HTTP\n");
851                     else if (pp_pe->alproto == ALPROTO_FTP)
852                         printf("            alproto: ALPROTO_FTP\n");
853                     else if (pp_pe->alproto == ALPROTO_FTPDATA)
854                         printf("            alproto: ALPROTO_FTPDATA\n");
855                     else if (pp_pe->alproto == ALPROTO_SMTP)
856                         printf("            alproto: ALPROTO_SMTP\n");
857                     else if (pp_pe->alproto == ALPROTO_TLS)
858                         printf("            alproto: ALPROTO_TLS\n");
859                     else if (pp_pe->alproto == ALPROTO_SSH)
860                         printf("            alproto: ALPROTO_SSH\n");
861                     else if (pp_pe->alproto == ALPROTO_IMAP)
862                         printf("            alproto: ALPROTO_IMAP\n");
863                     else if (pp_pe->alproto == ALPROTO_JABBER)
864                         printf("            alproto: ALPROTO_JABBER\n");
865                     else if (pp_pe->alproto == ALPROTO_SMB)
866                         printf("            alproto: ALPROTO_SMB\n");
867                     else if (pp_pe->alproto == ALPROTO_DCERPC)
868                         printf("            alproto: ALPROTO_DCERPC\n");
869                     else if (pp_pe->alproto == ALPROTO_IRC)
870                         printf("            alproto: ALPROTO_IRC\n");
871                     else if (pp_pe->alproto == ALPROTO_DNS)
872                         printf("            alproto: ALPROTO_DNS\n");
873                     else if (pp_pe->alproto == ALPROTO_MODBUS)
874                         printf("            alproto: ALPROTO_MODBUS\n");
875                     else if (pp_pe->alproto == ALPROTO_ENIP)
876                         printf("            alproto: ALPROTO_ENIP\n");
877                     else if (pp_pe->alproto == ALPROTO_NFS)
878                         printf("            alproto: ALPROTO_NFS\n");
879                     else if (pp_pe->alproto == ALPROTO_NTP)
880                         printf("            alproto: ALPROTO_NTP\n");
881                     else if (pp_pe->alproto == ALPROTO_TFTP)
882                         printf("            alproto: ALPROTO_TFTP\n");
883                     else if (pp_pe->alproto == ALPROTO_IKEV2)
884                         printf("            alproto: ALPROTO_IKEV2\n");
885                     else if (pp_pe->alproto == ALPROTO_KRB5)
886                         printf("            alproto: ALPROTO_KRB5\n");
887                     else if (pp_pe->alproto == ALPROTO_DHCP)
888                         printf("            alproto: ALPROTO_DHCP\n");
889                     else if (pp_pe->alproto == ALPROTO_SNMP)
890                         printf("            alproto: ALPROTO_SNMP\n");
891                     else if (pp_pe->alproto == ALPROTO_SIP)
892                         printf("            alproto: ALPROTO_SIP\n");
893                     else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
894                         printf("            alproto: ALPROTO_TEMPLATE_RUST\n");
895                     else if (pp_pe->alproto == ALPROTO_RFB)
896                         printf("            alproto: ALPROTO_RFB\n");
897                     else if (pp_pe->alproto == ALPROTO_MQTT)
898                         printf("            alproto: ALPROTO_MQTT\n");
899                     else if (pp_pe->alproto == ALPROTO_TEMPLATE)
900                         printf("            alproto: ALPROTO_TEMPLATE\n");
901                     else if (pp_pe->alproto == ALPROTO_DNP3)
902                         printf("            alproto: ALPROTO_DNP3\n");
903                     else
904                         printf("impossible\n");
905 
906                     printf("            port: %"PRIu16 "\n", pp_pe->port);
907                     printf("            mask: %"PRIu32 "\n", pp_pe->alproto_mask);
908                     printf("            min_depth: %"PRIu32 "\n", pp_pe->min_depth);
909                     printf("            max_depth: %"PRIu32 "\n", pp_pe->max_depth);
910 
911                     printf("\n");
912                 }
913             }
914 
915             if (pp_port->sp == NULL) {
916                 continue;
917             }
918 
919             printf("        Source port: (max-depth: %"PRIu16 ", "
920                    "mask - %"PRIu32")\n",
921                    pp_port->sp_max_depth,
922                    pp_port->alproto_mask);
923             pp_pe = pp_port->sp;
924             for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
925 
926                 if (pp_pe->alproto == ALPROTO_HTTP)
927                     printf("            alproto: ALPROTO_HTTP\n");
928                 else if (pp_pe->alproto == ALPROTO_FTP)
929                     printf("            alproto: ALPROTO_FTP\n");
930                 else if (pp_pe->alproto == ALPROTO_FTPDATA)
931                     printf("            alproto: ALPROTO_FTPDATA\n");
932                 else if (pp_pe->alproto == ALPROTO_SMTP)
933                     printf("            alproto: ALPROTO_SMTP\n");
934                 else if (pp_pe->alproto == ALPROTO_TLS)
935                     printf("            alproto: ALPROTO_TLS\n");
936                 else if (pp_pe->alproto == ALPROTO_SSH)
937                     printf("            alproto: ALPROTO_SSH\n");
938                 else if (pp_pe->alproto == ALPROTO_IMAP)
939                     printf("            alproto: ALPROTO_IMAP\n");
940                 else if (pp_pe->alproto == ALPROTO_JABBER)
941                     printf("            alproto: ALPROTO_JABBER\n");
942                 else if (pp_pe->alproto == ALPROTO_SMB)
943                     printf("            alproto: ALPROTO_SMB\n");
944                 else if (pp_pe->alproto == ALPROTO_DCERPC)
945                     printf("            alproto: ALPROTO_DCERPC\n");
946                 else if (pp_pe->alproto == ALPROTO_IRC)
947                     printf("            alproto: ALPROTO_IRC\n");
948                 else if (pp_pe->alproto == ALPROTO_DNS)
949                     printf("            alproto: ALPROTO_DNS\n");
950                 else if (pp_pe->alproto == ALPROTO_MODBUS)
951                     printf("            alproto: ALPROTO_MODBUS\n");
952                 else if (pp_pe->alproto == ALPROTO_ENIP)
953                     printf("            alproto: ALPROTO_ENIP\n");
954                 else if (pp_pe->alproto == ALPROTO_NFS)
955                     printf("            alproto: ALPROTO_NFS\n");
956                 else if (pp_pe->alproto == ALPROTO_NTP)
957                     printf("            alproto: ALPROTO_NTP\n");
958                 else if (pp_pe->alproto == ALPROTO_TFTP)
959                     printf("            alproto: ALPROTO_TFTP\n");
960                 else if (pp_pe->alproto == ALPROTO_IKEV2)
961                     printf("            alproto: ALPROTO_IKEV2\n");
962                 else if (pp_pe->alproto == ALPROTO_KRB5)
963                     printf("            alproto: ALPROTO_KRB5\n");
964                 else if (pp_pe->alproto == ALPROTO_DHCP)
965                     printf("            alproto: ALPROTO_DHCP\n");
966                 else if (pp_pe->alproto == ALPROTO_SNMP)
967                     printf("            alproto: ALPROTO_SNMP\n");
968                 else if (pp_pe->alproto == ALPROTO_SIP)
969                     printf("            alproto: ALPROTO_SIP\n");
970                 else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
971                     printf("            alproto: ALPROTO_TEMPLATE_RUST\n");
972                 else if (pp_pe->alproto == ALPROTO_RFB)
973                     printf("            alproto: ALPROTO_RFB\n");
974                 else if (pp_pe->alproto == ALPROTO_MQTT)
975                     printf("            alproto: ALPROTO_MQTT\n");
976                 else if (pp_pe->alproto == ALPROTO_TEMPLATE)
977                     printf("            alproto: ALPROTO_TEMPLATE\n");
978                 else if (pp_pe->alproto == ALPROTO_DNP3)
979                     printf("            alproto: ALPROTO_DNP3\n");
980                 else
981                     printf("impossible\n");
982 
983                 printf("            port: %"PRIu16 "\n", pp_pe->port);
984                 printf("            mask: %"PRIu32 "\n", pp_pe->alproto_mask);
985                 printf("            min_depth: %"PRIu32 "\n", pp_pe->min_depth);
986                 printf("            max_depth: %"PRIu32 "\n", pp_pe->max_depth);
987 
988                 printf("\n");
989             }
990         }
991     }
992 
993     SCReturn;
994 }
995 #endif
996 
AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement ** head_pe,AppLayerProtoDetectProbingParserElement * new_pe)997 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
998                                                           AppLayerProtoDetectProbingParserElement *new_pe)
999 {
1000     SCEnter();
1001 
1002     if (*head_pe == NULL) {
1003         *head_pe = new_pe;
1004         goto end;
1005     }
1006 
1007     if ((*head_pe)->port == 0) {
1008         if (new_pe->port != 0) {
1009             new_pe->next = *head_pe;
1010             *head_pe = new_pe;
1011         } else {
1012             AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
1013             while (temp_pe->next != NULL)
1014                 temp_pe = temp_pe->next;
1015             temp_pe->next = new_pe;
1016         }
1017     } else {
1018         AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
1019         if (new_pe->port == 0) {
1020             while (temp_pe->next != NULL)
1021                 temp_pe = temp_pe->next;
1022             temp_pe->next = new_pe;
1023         } else {
1024             while (temp_pe->next != NULL && temp_pe->next->port != 0)
1025                 temp_pe = temp_pe->next;
1026             new_pe->next = temp_pe->next;
1027             temp_pe->next = new_pe;
1028 
1029         }
1030     }
1031 
1032  end:
1033     SCReturn;
1034 }
1035 
AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser ** head_pp,AppLayerProtoDetectProbingParser * new_pp)1036 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1037                                                    AppLayerProtoDetectProbingParser *new_pp)
1038 {
1039     SCEnter();
1040 
1041     if (*head_pp == NULL) {
1042         *head_pp = new_pp;
1043         goto end;
1044     }
1045 
1046     AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1047     while (temp_pp->next != NULL)
1048         temp_pp = temp_pp->next;
1049     temp_pp->next = new_pp;
1050 
1051  end:
1052     SCReturn;
1053 }
1054 
AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort ** head_port,AppLayerProtoDetectProbingParserPort * new_port)1055 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1056                                                        AppLayerProtoDetectProbingParserPort *new_port)
1057 {
1058     SCEnter();
1059 
1060     if (*head_port == NULL) {
1061         *head_port = new_port;
1062         goto end;
1063     }
1064 
1065     if ((*head_port)->port == 0) {
1066         new_port->next = *head_port;
1067         *head_port = new_port;
1068     } else {
1069         AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1070         while (temp_port->next != NULL && temp_port->next->port != 0) {
1071             temp_port = temp_port->next;
1072         }
1073         new_port->next = temp_port->next;
1074         temp_port->next = new_port;
1075     }
1076 
1077  end:
1078     SCReturn;
1079 }
1080 
AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser ** pp,uint8_t ipproto,uint16_t port,AppProto alproto,uint16_t min_depth,uint16_t max_depth,uint8_t direction,ProbingParserFPtr ProbingParser1,ProbingParserFPtr ProbingParser2)1081 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1082                                                              uint8_t ipproto,
1083                                                              uint16_t port,
1084                                                              AppProto alproto,
1085                                                              uint16_t min_depth, uint16_t max_depth,
1086                                                              uint8_t direction,
1087                                                              ProbingParserFPtr ProbingParser1,
1088                                                              ProbingParserFPtr ProbingParser2)
1089 {
1090     SCEnter();
1091 
1092     /* get the top level ipproto pp */
1093     AppLayerProtoDetectProbingParser *curr_pp = *pp;
1094     while (curr_pp != NULL) {
1095         if (curr_pp->ipproto == ipproto)
1096             break;
1097         curr_pp = curr_pp->next;
1098     }
1099     if (curr_pp == NULL) {
1100         AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1101         new_pp->ipproto = ipproto;
1102         AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1103         curr_pp = new_pp;
1104     }
1105 
1106     /* get the top level port pp */
1107     AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1108     while (curr_port != NULL) {
1109         if (curr_port->port == port)
1110             break;
1111         curr_port = curr_port->next;
1112     }
1113     if (curr_port == NULL) {
1114         AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1115         new_port->port = port;
1116         AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1117         curr_port = new_port;
1118         if (direction & STREAM_TOSERVER) {
1119             curr_port->dp_max_depth = max_depth;
1120         } else {
1121             curr_port->sp_max_depth = max_depth;
1122         }
1123 
1124         AppLayerProtoDetectProbingParserPort *zero_port;
1125 
1126         zero_port = curr_pp->port;
1127         while (zero_port != NULL && zero_port->port != 0) {
1128             zero_port = zero_port->next;
1129         }
1130         if (zero_port != NULL) {
1131             AppLayerProtoDetectProbingParserElement *zero_pe;
1132 
1133             zero_pe = zero_port->dp;
1134             for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1135                 if (curr_port->dp == NULL)
1136                     curr_port->dp_max_depth = zero_pe->max_depth;
1137                 if (zero_pe->max_depth == 0)
1138                     curr_port->dp_max_depth = zero_pe->max_depth;
1139                 if (curr_port->dp_max_depth != 0 &&
1140                     curr_port->dp_max_depth < zero_pe->max_depth) {
1141                     curr_port->dp_max_depth = zero_pe->max_depth;
1142                 }
1143 
1144                 AppLayerProtoDetectProbingParserElement *dup_pe =
1145                     AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1146                 AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1147                 curr_port->alproto_mask |= dup_pe->alproto_mask;
1148             }
1149 
1150             zero_pe = zero_port->sp;
1151             for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1152                 if (curr_port->sp == NULL)
1153                     curr_port->sp_max_depth = zero_pe->max_depth;
1154                 if (zero_pe->max_depth == 0)
1155                     curr_port->sp_max_depth = zero_pe->max_depth;
1156                 if (curr_port->sp_max_depth != 0 &&
1157                     curr_port->sp_max_depth < zero_pe->max_depth) {
1158                     curr_port->sp_max_depth = zero_pe->max_depth;
1159                 }
1160 
1161                 AppLayerProtoDetectProbingParserElement *dup_pe =
1162                     AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1163                 AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1164                 curr_port->alproto_mask |= dup_pe->alproto_mask;
1165             }
1166         } /* if (zero_port != NULL) */
1167     } /* if (curr_port == NULL) */
1168 
1169     /* insert the pe_pp */
1170     AppLayerProtoDetectProbingParserElement *curr_pe;
1171     if (direction & STREAM_TOSERVER)
1172         curr_pe = curr_port->dp;
1173     else
1174         curr_pe = curr_port->sp;
1175     while (curr_pe != NULL) {
1176         if (curr_pe->alproto == alproto) {
1177             SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
1178                        "ipproto - %"PRIu8" Port - %"PRIu16" "
1179                        "App Protocol - NULL, App Protocol(ID) - "
1180                        "%"PRIu16" min_depth - %"PRIu16" "
1181                        "max_dept - %"PRIu16".",
1182                        ipproto, port, alproto,
1183                        min_depth, max_depth);
1184             goto error;
1185         }
1186         curr_pe = curr_pe->next;
1187     }
1188     /* Get a new parser element */
1189     AppLayerProtoDetectProbingParserElement *new_pe =
1190         AppLayerProtoDetectProbingParserElementCreate(alproto,
1191                                                       curr_port->port,
1192                                                       min_depth, max_depth);
1193     if (new_pe == NULL)
1194         goto error;
1195     curr_pe = new_pe;
1196     AppLayerProtoDetectProbingParserElement **head_pe;
1197     if (direction & STREAM_TOSERVER) {
1198         curr_pe->ProbingParserTs = ProbingParser1;
1199         curr_pe->ProbingParserTc = ProbingParser2;
1200         if (curr_port->dp == NULL)
1201             curr_port->dp_max_depth = new_pe->max_depth;
1202         if (new_pe->max_depth == 0)
1203             curr_port->dp_max_depth = new_pe->max_depth;
1204         if (curr_port->dp_max_depth != 0 &&
1205             curr_port->dp_max_depth < new_pe->max_depth) {
1206             curr_port->dp_max_depth = new_pe->max_depth;
1207         }
1208         curr_port->alproto_mask |= new_pe->alproto_mask;
1209         head_pe = &curr_port->dp;
1210     } else {
1211         curr_pe->ProbingParserTs = ProbingParser2;
1212         curr_pe->ProbingParserTc = ProbingParser1;
1213         if (curr_port->sp == NULL)
1214             curr_port->sp_max_depth = new_pe->max_depth;
1215         if (new_pe->max_depth == 0)
1216             curr_port->sp_max_depth = new_pe->max_depth;
1217         if (curr_port->sp_max_depth != 0 &&
1218             curr_port->sp_max_depth < new_pe->max_depth) {
1219             curr_port->sp_max_depth = new_pe->max_depth;
1220         }
1221         curr_port->alproto_mask |= new_pe->alproto_mask;
1222         head_pe = &curr_port->sp;
1223     }
1224     AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1225 
1226     if (curr_port->port == 0) {
1227         AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1228         while (temp_port != NULL && temp_port->port != 0) {
1229             if (direction & STREAM_TOSERVER) {
1230                 if (temp_port->dp == NULL)
1231                     temp_port->dp_max_depth = curr_pe->max_depth;
1232                 if (curr_pe->max_depth == 0)
1233                     temp_port->dp_max_depth = curr_pe->max_depth;
1234                 if (temp_port->dp_max_depth != 0 &&
1235                     temp_port->dp_max_depth < curr_pe->max_depth) {
1236                     temp_port->dp_max_depth = curr_pe->max_depth;
1237                 }
1238                 AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1239                                                               AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1240                 temp_port->alproto_mask |= curr_pe->alproto_mask;
1241             } else {
1242                 if (temp_port->sp == NULL)
1243                     temp_port->sp_max_depth = curr_pe->max_depth;
1244                 if (curr_pe->max_depth == 0)
1245                     temp_port->sp_max_depth = curr_pe->max_depth;
1246                 if (temp_port->sp_max_depth != 0 &&
1247                     temp_port->sp_max_depth < curr_pe->max_depth) {
1248                     temp_port->sp_max_depth = curr_pe->max_depth;
1249                 }
1250                 AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1251                                                               AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1252                 temp_port->alproto_mask |= curr_pe->alproto_mask;
1253             }
1254             temp_port = temp_port->next;
1255         } /* while */
1256     } /* if */
1257 
1258  error:
1259     SCReturn;
1260 }
1261 
1262 /***** Static Internal Calls: PM registration *****/
1263 
AppLayerProtoDetectPMGetIpprotos(AppProto alproto,uint8_t * ipprotos)1264 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1265                                              uint8_t *ipprotos)
1266 {
1267     SCEnter();
1268 
1269     for (int i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1270         uint8_t ipproto = FlowGetReverseProtoMapping(i);
1271         for (int j = 0; j < 2; j++) {
1272             AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1273 
1274             for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1275                 const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1276                 if (s->alproto == alproto)
1277                     ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1278             }
1279         }
1280     }
1281 
1282     SCReturn;
1283 }
1284 
AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx * ctx)1285 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1286 {
1287     SCEnter();
1288 
1289     typedef struct TempContainer_ {
1290         PatIntId id;
1291         uint16_t content_len;
1292         uint8_t *content;
1293     } TempContainer;
1294 
1295     AppLayerProtoDetectPMSignature *s = NULL;
1296     uint32_t struct_total_size = 0;
1297     uint32_t content_total_size = 0;
1298     /* array hash buffer */
1299     uint8_t *ahb = NULL;
1300     uint8_t *content = NULL;
1301     uint8_t content_len = 0;
1302     PatIntId max_id = 0;
1303     TempContainer *struct_offset = NULL;
1304     uint8_t *content_offset = NULL;
1305     int ret = 0;
1306 
1307     if (ctx->head == NULL)
1308         goto end;
1309 
1310     for (s = ctx->head; s != NULL; s = s->next) {
1311         struct_total_size += sizeof(TempContainer);
1312         content_total_size += s->cd->content_len;
1313         ctx->max_sig_id++;
1314     }
1315 
1316     ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1317     if (unlikely(ahb == NULL))
1318         goto error;
1319 
1320     struct_offset = (TempContainer *)ahb;
1321     content_offset = ahb + struct_total_size;
1322     for (s = ctx->head; s != NULL; s = s->next) {
1323         TempContainer *tcdup = (TempContainer *)ahb;
1324         content = s->cd->content;
1325         content_len = s->cd->content_len;
1326 
1327         for (; tcdup != struct_offset; tcdup++) {
1328             if (tcdup->content_len != content_len ||
1329                 SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1330             {
1331                 continue;
1332             }
1333             break;
1334         }
1335 
1336         if (tcdup != struct_offset) {
1337             s->cd->id = tcdup->id;
1338             continue;
1339         }
1340 
1341         struct_offset->content_len = content_len;
1342         struct_offset->content = content_offset;
1343         content_offset += content_len;
1344         memcpy(struct_offset->content, content, content_len);
1345         struct_offset->id = max_id++;
1346         s->cd->id = struct_offset->id;
1347 
1348         struct_offset++;
1349     }
1350 
1351     ctx->max_pat_id = max_id;
1352 
1353     goto end;
1354  error:
1355     ret = -1;
1356  end:
1357     if (ahb != NULL)
1358         SCFree(ahb);
1359     SCReturnInt(ret);
1360 }
1361 
AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx * ctx)1362 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1363 {
1364     SCEnter();
1365 
1366     int ret = 0;
1367     AppLayerProtoDetectPMSignature *s, *next_s;
1368     int mpm_ret;
1369     SigIntId id = 0;
1370 
1371     ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1372     if (ctx->map == NULL)
1373         goto error;
1374     memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1375 
1376     /* add an array indexed by rule id to look up the sig */
1377     for (s = ctx->head; s != NULL; ) {
1378         next_s = s->next;
1379         s->id = id++;
1380         SCLogDebug("s->id %u offset %u depth %u",
1381                 s->id, s->cd->offset, s->cd->depth);
1382 
1383         if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1384             mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1385                     s->cd->content, s->cd->content_len,
1386                     s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1387             if (mpm_ret < 0)
1388                 goto error;
1389         } else {
1390             mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1391                     s->cd->content, s->cd->content_len,
1392                     s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1393             if (mpm_ret < 0)
1394                 goto error;
1395         }
1396 
1397         ctx->map[s->id] = s;
1398         s->next = NULL;
1399         s = next_s;
1400     }
1401     ctx->head = NULL;
1402 
1403     goto end;
1404  error:
1405     ret = -1;
1406  end:
1407     SCReturnInt(ret);
1408 }
1409 
AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx * ctx)1410 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1411 {
1412     SCEnter();
1413 
1414     int ret = 0;
1415     MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1416 
1417     if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1418         goto error;
1419 
1420     goto end;
1421  error:
1422     ret = -1;
1423  end:
1424     SCReturnInt(ret);
1425 }
1426 
AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature * sig)1427 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1428 {
1429     SCEnter();
1430     if (sig == NULL)
1431         SCReturn;
1432     if (sig->cd)
1433         DetectContentFree(NULL, sig->cd);
1434     SCFree(sig);
1435     SCReturn;
1436 }
1437 
AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx * ctx,DetectContentData * cd,AppProto alproto,uint8_t direction,ProbingParserFPtr PPFunc,uint16_t pp_min_depth,uint16_t pp_max_depth)1438 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1439                                              AppProto alproto, uint8_t direction,
1440                                              ProbingParserFPtr PPFunc,
1441                                              uint16_t pp_min_depth, uint16_t pp_max_depth)
1442 {
1443     SCEnter();
1444 
1445     AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1446     if (unlikely(s == NULL))
1447         SCReturnInt(-1);
1448 
1449     s->alproto = alproto;
1450     s->direction = direction;
1451     s->cd = cd;
1452     s->PPFunc = PPFunc;
1453     s->pp_min_depth = pp_min_depth;
1454     s->pp_max_depth = pp_max_depth;
1455 
1456     /* prepend to the list */
1457     s->next = ctx->head;
1458     ctx->head = s;
1459 
1460     SCReturnInt(0);
1461 }
1462 
AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto,AppProto alproto,const char * pattern,uint16_t depth,uint16_t offset,uint8_t direction,uint8_t is_cs,ProbingParserFPtr PPFunc,uint16_t pp_min_depth,uint16_t pp_max_depth)1463 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1464                                                 const char *pattern,
1465                                                 uint16_t depth, uint16_t offset,
1466                                                 uint8_t direction,
1467                                                 uint8_t is_cs,
1468                                                 ProbingParserFPtr PPFunc,
1469                                                 uint16_t pp_min_depth, uint16_t pp_max_depth)
1470 {
1471     SCEnter();
1472 
1473     AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1474     AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1475     int ret = 0;
1476 
1477     DetectContentData *cd = DetectContentParseEncloseQuotes(
1478             alpd_ctx.spm_global_thread_ctx, pattern);
1479     if (cd == NULL)
1480         goto error;
1481     cd->depth = depth;
1482     cd->offset = offset;
1483     if (!is_cs) {
1484         /* Rebuild as nocase */
1485         SpmDestroyCtx(cd->spm_ctx);
1486         cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1487                                  alpd_ctx.spm_global_thread_ctx);
1488         if (cd->spm_ctx == NULL) {
1489             goto error;
1490         }
1491         cd->flags |= DETECT_CONTENT_NOCASE;
1492     }
1493     if (depth < cd->content_len)
1494         goto error;
1495 
1496     if (direction & STREAM_TOSERVER)
1497         ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1498     else
1499         ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1500 
1501     if (pp_max_depth > ctx_pm->pp_max_len)
1502         ctx_pm->pp_max_len = pp_max_depth;
1503     if (depth < ctx_pm->min_len)
1504         ctx_pm->min_len = depth;
1505 
1506     /* Finally turn it into a signature and add to the ctx. */
1507     AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1508             PPFunc, pp_min_depth, pp_max_depth);
1509 
1510     goto end;
1511  error:
1512     DetectContentFree(NULL, cd);
1513     ret = -1;
1514  end:
1515     SCReturnInt(ret);
1516 }
1517 
1518 /***** Protocol Retrieval *****/
1519 
AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx * tctx,Flow * f,const uint8_t * buf,uint32_t buflen,uint8_t ipproto,uint8_t flags,bool * reverse_flow)1520 AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f,
1521         const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t flags, bool *reverse_flow)
1522 {
1523     SCEnter();
1524     SCLogDebug("buflen %u for %s direction", buflen,
1525             (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1526 
1527     AppProto alproto = ALPROTO_UNKNOWN;
1528     AppProto pm_alproto = ALPROTO_UNKNOWN;
1529 
1530     if (!FLOW_IS_PM_DONE(f, flags)) {
1531         AppProto pm_results[ALPROTO_MAX];
1532         uint16_t pm_matches = AppLayerProtoDetectPMGetProto(
1533                 tctx, f, buf, buflen, flags, pm_results, reverse_flow);
1534         if (pm_matches > 0) {
1535             alproto = pm_results[0];
1536 
1537             // rerun probing parser for other direction if it is unknown
1538             uint8_t reverse_dir = (flags & STREAM_TOSERVER) ? STREAM_TOCLIENT : STREAM_TOSERVER;
1539             if (FLOW_IS_PP_DONE(f, reverse_dir)) {
1540                 AppProto rev_alproto = (flags & STREAM_TOSERVER) ? f->alproto_tc : f->alproto_ts;
1541                 if (rev_alproto == ALPROTO_UNKNOWN) {
1542                     FLOW_RESET_PP_DONE(f, reverse_dir);
1543                 }
1544             }
1545 
1546             /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1547              * to avoid misdetecting DNS as DCERPC. */
1548             if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1549                 goto end;
1550 
1551             pm_alproto = alproto;
1552 
1553             /* fall through */
1554         }
1555     }
1556 
1557     if (!FLOW_IS_PP_DONE(f, flags)) {
1558         bool rflow = false;
1559         alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1560         if (AppProtoIsValid(alproto)) {
1561             if (rflow) {
1562                 *reverse_flow = true;
1563             }
1564             goto end;
1565         }
1566     }
1567 
1568     /* Look if flow can be found in expectation list */
1569     if (!FLOW_IS_PE_DONE(f, flags)) {
1570         alproto = AppLayerProtoDetectPEGetProto(f, ipproto, flags);
1571     }
1572 
1573  end:
1574     if (!AppProtoIsValid(alproto))
1575         alproto = pm_alproto;
1576 
1577     SCReturnUInt(alproto);
1578 }
1579 
AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser * pp)1580 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1581 {
1582     SCEnter();
1583 
1584     AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1585 
1586     if (pp == NULL)
1587         goto end;
1588 
1589     while (pp != NULL) {
1590         tmp_pp = pp->next;
1591         AppLayerProtoDetectProbingParserFree(pp);
1592         pp = tmp_pp;
1593     }
1594 
1595  end:
1596     SCReturn;
1597 }
1598 
1599 /***** State Preparation *****/
1600 
AppLayerProtoDetectPrepareState(void)1601 int AppLayerProtoDetectPrepareState(void)
1602 {
1603     SCEnter();
1604 
1605     AppLayerProtoDetectPMCtx *ctx_pm;
1606     int i, j;
1607     int ret = 0;
1608 
1609     for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1610         for (j = 0; j < 2; j++) {
1611             ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1612 
1613             if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1614                 goto error;
1615 
1616             if (ctx_pm->max_sig_id == 0)
1617                 continue;
1618 
1619             if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1620                 goto error;
1621             if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1622                 goto error;
1623         }
1624     }
1625 
1626 #ifdef DEBUG
1627     if (SCLogDebugEnabled()) {
1628         AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1629     }
1630 #endif
1631 
1632     goto end;
1633  error:
1634     ret = -1;
1635  end:
1636     SCReturnInt(ret);
1637 }
1638 
1639 /***** PP registration *****/
1640 
1641 /** \brief register parser at a port
1642  *
1643  *  \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1644  */
AppLayerProtoDetectPPRegister(uint8_t ipproto,const char * portstr,AppProto alproto,uint16_t min_depth,uint16_t max_depth,uint8_t direction,ProbingParserFPtr ProbingParser1,ProbingParserFPtr ProbingParser2)1645 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1646                                    const char *portstr,
1647                                    AppProto alproto,
1648                                    uint16_t min_depth, uint16_t max_depth,
1649                                    uint8_t direction,
1650                                    ProbingParserFPtr ProbingParser1,
1651                                    ProbingParserFPtr ProbingParser2)
1652 {
1653     SCEnter();
1654 
1655     DetectPort *head = NULL;
1656     DetectPortParse(NULL,&head, portstr);
1657     DetectPort *temp_dp = head;
1658     while (temp_dp != NULL) {
1659         uint32_t port = temp_dp->port;
1660         if (port == 0 && temp_dp->port2 != 0)
1661             port++;
1662         for ( ; port <= temp_dp->port2; port++) {
1663             AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1664                                                       ipproto,
1665                                                       port,
1666                                                       alproto,
1667                                                       min_depth, max_depth,
1668                                                       direction,
1669                                                       ProbingParser1,
1670                                                       ProbingParser2);
1671         }
1672         temp_dp = temp_dp->next;
1673     }
1674     DetectPortCleanupList(NULL,head);
1675 
1676     SCReturn;
1677 }
1678 
AppLayerProtoDetectPPParseConfPorts(const char * ipproto_name,uint8_t ipproto,const char * alproto_name,AppProto alproto,uint16_t min_depth,uint16_t max_depth,ProbingParserFPtr ProbingParserTs,ProbingParserFPtr ProbingParserTc)1679 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1680                                          uint8_t ipproto,
1681                                          const char *alproto_name,
1682                                          AppProto alproto,
1683                                          uint16_t min_depth, uint16_t max_depth,
1684                                          ProbingParserFPtr ProbingParserTs,
1685                                          ProbingParserFPtr ProbingParserTc)
1686 {
1687     SCEnter();
1688 
1689     char param[100];
1690     int r;
1691     ConfNode *node;
1692     ConfNode *port_node = NULL;
1693     int config = 0;
1694 
1695     r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1696                  alproto_name, ".detection-ports");
1697     if (r < 0) {
1698         FatalError(SC_ERR_FATAL, "snprintf failure.");
1699     } else if (r > (int)sizeof(param)) {
1700         FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1701     }
1702     node = ConfGetNode(param);
1703     if (node == NULL) {
1704         SCLogDebug("Entry for %s not found.", param);
1705         r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1706                      alproto_name, ".", ipproto_name, ".detection-ports");
1707         if (r < 0) {
1708             FatalError(SC_ERR_FATAL, "snprintf failure.");
1709         } else if (r > (int)sizeof(param)) {
1710             FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1711         }
1712         node = ConfGetNode(param);
1713         if (node == NULL)
1714             goto end;
1715     }
1716 
1717     /* detect by destination port of the flow (e.g. port 53 for DNS) */
1718     port_node = ConfNodeLookupChild(node, "dp");
1719     if (port_node == NULL)
1720         port_node = ConfNodeLookupChild(node, "toserver");
1721 
1722     if (port_node != NULL && port_node->val != NULL) {
1723         AppLayerProtoDetectPPRegister(ipproto,
1724                                       port_node->val,
1725                                       alproto,
1726                                       min_depth, max_depth,
1727                                       STREAM_TOSERVER, /* to indicate dp */
1728                                       ProbingParserTs, ProbingParserTc);
1729     }
1730 
1731     /* detect by source port of flow */
1732     port_node = ConfNodeLookupChild(node, "sp");
1733     if (port_node == NULL)
1734         port_node = ConfNodeLookupChild(node, "toclient");
1735 
1736     if (port_node != NULL && port_node->val != NULL) {
1737         AppLayerProtoDetectPPRegister(ipproto,
1738                                       port_node->val,
1739                                       alproto,
1740                                       min_depth, max_depth,
1741                                       STREAM_TOCLIENT, /* to indicate sp */
1742                                       ProbingParserTc, ProbingParserTs);
1743 
1744     }
1745 
1746     config = 1;
1747  end:
1748     SCReturnInt(config);
1749 }
1750 
1751 /***** PM registration *****/
1752 
AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto,AppProto alproto,const char * pattern,uint16_t depth,uint16_t offset,uint8_t direction)1753 int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto,
1754                                            const char *pattern,
1755                                            uint16_t depth, uint16_t offset,
1756                                            uint8_t direction)
1757 {
1758     SCEnter();
1759     int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1760             pattern, depth, offset,
1761             direction, 1 /* case-sensitive */,
1762             NULL, 0, 0);
1763     SCReturnInt(r);
1764 }
1765 
AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto,AppProto alproto,const char * pattern,uint16_t depth,uint16_t offset,uint8_t direction,ProbingParserFPtr PPFunc,uint16_t pp_min_depth,uint16_t pp_max_depth)1766 int AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto, AppProto alproto,
1767         const char *pattern, uint16_t depth, uint16_t offset,
1768         uint8_t direction,
1769         ProbingParserFPtr PPFunc,
1770         uint16_t pp_min_depth, uint16_t pp_max_depth)
1771 {
1772     SCEnter();
1773     int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1774             pattern, depth, offset,
1775             direction, 1 /* case-sensitive */,
1776             PPFunc, pp_min_depth, pp_max_depth);
1777     SCReturnInt(r);
1778 }
1779 
AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto,AppProto alproto,const char * pattern,uint16_t depth,uint16_t offset,uint8_t direction)1780 int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto,
1781                                            const char *pattern,
1782                                            uint16_t depth, uint16_t offset,
1783                                            uint8_t direction)
1784 {
1785     SCEnter();
1786     int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1787             pattern, depth, offset,
1788             direction, 0 /* !case-sensitive */,
1789             NULL, 0, 0);
1790     SCReturnInt(r);
1791 }
1792 
1793 /***** Setup/General Registration *****/
1794 
AppLayerProtoDetectSetup(void)1795 int AppLayerProtoDetectSetup(void)
1796 {
1797     SCEnter();
1798 
1799     int i, j;
1800 
1801     memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1802 
1803     uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1804     uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1805 
1806     alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1807     if (alpd_ctx.spm_global_thread_ctx == NULL) {
1808         FatalError(SC_ERR_FATAL, "Unable to alloc SpmGlobalThreadCtx.");
1809     }
1810 
1811     for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1812         for (j = 0; j < 2; j++) {
1813             MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1814         }
1815     }
1816 
1817     AppLayerExpectationSetup();
1818 
1819     SCReturnInt(0);
1820 }
1821 
1822 /**
1823  * \todo incomplete.  Need more work.
1824  */
AppLayerProtoDetectDeSetup(void)1825 int AppLayerProtoDetectDeSetup(void)
1826 {
1827     SCEnter();
1828 
1829     int ipproto_map = 0;
1830     int dir = 0;
1831     PatIntId id = 0;
1832     AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1833     AppLayerProtoDetectPMSignature *sig = NULL;
1834 
1835     for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1836         for (dir = 0; dir < 2; dir++) {
1837             pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1838             mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1839             for (id = 0; id < pm_ctx->max_sig_id; id++) {
1840                 sig = pm_ctx->map[id];
1841                 AppLayerProtoDetectPMFreeSignature(sig);
1842             }
1843             SCFree(pm_ctx->map);
1844             pm_ctx->map = NULL;
1845         }
1846     }
1847 
1848     SpmDestroyGlobalThreadCtx(alpd_ctx.spm_global_thread_ctx);
1849 
1850     AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1851 
1852     SCReturnInt(0);
1853 }
1854 
AppLayerProtoDetectRegisterProtocol(AppProto alproto,const char * alproto_name)1855 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1856 {
1857     SCEnter();
1858 
1859     if (alpd_ctx.alproto_names[alproto] == NULL)
1860         alpd_ctx.alproto_names[alproto] = alproto_name;
1861 
1862     SCReturn;
1863 }
1864 
1865 /** \brief request applayer to wrap up this protocol and rerun protocol
1866  *         detection.
1867  *
1868  *  When this is called, the old session is reset unconditionally. A
1869  *  'detect/log' flush packet is generated for both direction before
1870  *  the reset, so allow for final detection and logging.
1871  *
1872  *  \param f flow to act on
1873  *  \param dp destination port to use in protocol detection. Set to 443
1874  *            for start tls, set to the HTTP uri port for CONNECT and
1875  *            set to 0 to not use it.
1876  *  \param expect_proto expected protocol. AppLayer event will be set if
1877  *                      detected protocol differs from this.
1878  */
AppLayerRequestProtocolChange(Flow * f,uint16_t dp,AppProto expect_proto)1879 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1880 {
1881     FlowSetChangeProtoFlag(f);
1882     f->protodetect_dp = dp;
1883     f->alproto_expect = expect_proto;
1884     DEBUG_VALIDATE_BUG_ON(f->alproto == ALPROTO_UNKNOWN);
1885     f->alproto_orig = f->alproto;
1886     // If one side is unknown yet, set it to the other known side
1887     if (f->alproto_ts == ALPROTO_UNKNOWN) {
1888         f->alproto_ts = f->alproto;
1889     }
1890     if (f->alproto_tc == ALPROTO_UNKNOWN) {
1891         f->alproto_tc = f->alproto;
1892     }
1893 }
1894 
1895 /** \brief request applayer to wrap up this protocol and rerun protocol
1896  *         detection with expectation of TLS. Used by STARTTLS.
1897  *
1898  *  Sets detection port to 443 to make port based TLS detection work for
1899  *  SMTP, FTP etc as well.
1900  *
1901  *  \param f flow to act on
1902  */
AppLayerRequestProtocolTLSUpgrade(Flow * f)1903 void AppLayerRequestProtocolTLSUpgrade(Flow *f)
1904 {
1905     AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
1906 }
1907 
AppLayerProtoDetectReset(Flow * f)1908 void AppLayerProtoDetectReset(Flow *f)
1909 {
1910     FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1911     FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1912     FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1913     FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1914     FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1915     FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1916     f->probing_parser_toserver_alproto_masks = 0;
1917     f->probing_parser_toclient_alproto_masks = 0;
1918 
1919     // Does not free the structures for the parser
1920     // keeps f->alstate for new state creation
1921     f->alparser = NULL;
1922     f->alproto    = ALPROTO_UNKNOWN;
1923     f->alproto_ts = ALPROTO_UNKNOWN;
1924     f->alproto_tc = ALPROTO_UNKNOWN;
1925 }
1926 
AppLayerProtoDetectConfProtoDetectionEnabled(const char * ipproto,const char * alproto)1927 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto,
1928                                                  const char *alproto)
1929 {
1930     SCEnter();
1931 
1932     BUG_ON(ipproto == NULL || alproto == NULL);
1933 
1934     int enabled = 1;
1935     char param[100];
1936     ConfNode *node;
1937     int r;
1938 
1939     if (RunmodeIsUnittests())
1940         goto enabled;
1941 
1942     r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1943                  alproto, ".enabled");
1944     if (r < 0) {
1945         FatalError(SC_ERR_FATAL, "snprintf failure.");
1946     } else if (r > (int)sizeof(param)) {
1947         FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1948     }
1949 
1950     node = ConfGetNode(param);
1951     if (node == NULL) {
1952         SCLogDebug("Entry for %s not found.", param);
1953         r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1954                      alproto, ".", ipproto, ".enabled");
1955         if (r < 0) {
1956             FatalError(SC_ERR_FATAL, "snprintf failure.");
1957         } else if (r > (int)sizeof(param)) {
1958             FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1959         }
1960 
1961         node = ConfGetNode(param);
1962         if (node == NULL) {
1963             SCLogDebug("Entry for %s not found.", param);
1964             goto enabled;
1965         }
1966     }
1967 
1968     if (node->val) {
1969         if (ConfValIsTrue(node->val)) {
1970             goto enabled;
1971         } else if (ConfValIsFalse(node->val)) {
1972             goto disabled;
1973         } else if (strcasecmp(node->val, "detection-only") == 0) {
1974             goto enabled;
1975         }
1976     }
1977 
1978     /* Invalid or null value. */
1979     SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
1980     exit(EXIT_FAILURE);
1981 
1982  disabled:
1983     enabled = 0;
1984  enabled:
1985     SCReturnInt(enabled);
1986 }
1987 
AppLayerProtoDetectGetCtxThread(void)1988 AppLayerProtoDetectThreadCtx *AppLayerProtoDetectGetCtxThread(void)
1989 {
1990     SCEnter();
1991 
1992     AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
1993     MpmCtx *mpm_ctx;
1994     MpmThreadCtx *mpm_tctx;
1995     int i, j;
1996     PatIntId max_pat_id = 0;
1997 
1998     for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1999         for (j = 0; j < 2; j++) {
2000             if (max_pat_id == 0) {
2001                 max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2002 
2003             } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
2004                     max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
2005             {
2006                 max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2007             }
2008         }
2009     }
2010 
2011     alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
2012     if (alpd_tctx == NULL)
2013         goto error;
2014     memset(alpd_tctx, 0, sizeof(*alpd_tctx));
2015 
2016     /* Get the max pat id for all the mpm ctxs. */
2017     if (PmqSetup(&alpd_tctx->pmq) < 0)
2018         goto error;
2019 
2020     for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2021         for (j = 0; j < 2; j++) {
2022             mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2023             mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2024             mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
2025         }
2026     }
2027 
2028     alpd_tctx->spm_thread_ctx = SpmMakeThreadCtx(alpd_ctx.spm_global_thread_ctx);
2029     if (alpd_tctx->spm_thread_ctx == NULL) {
2030         goto error;
2031     }
2032 
2033     goto end;
2034  error:
2035     if (alpd_tctx != NULL)
2036         AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2037     alpd_tctx = NULL;
2038  end:
2039     SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2040 }
2041 
AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx * alpd_tctx)2042 void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
2043 {
2044     SCEnter();
2045 
2046     MpmCtx *mpm_ctx;
2047     MpmThreadCtx *mpm_tctx;
2048     int ipproto_map, dir;
2049 
2050     for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2051         for (dir = 0; dir < 2; dir++) {
2052             mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2053             mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2054             mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2055         }
2056     }
2057     PmqFree(&alpd_tctx->pmq);
2058     if (alpd_tctx->spm_thread_ctx != NULL) {
2059         SpmDestroyThreadCtx(alpd_tctx->spm_thread_ctx);
2060     }
2061     SCFree(alpd_tctx);
2062 
2063     SCReturn;
2064 }
2065 
2066 /***** Utility *****/
2067 
AppLayerProtoDetectSupportedIpprotos(AppProto alproto,uint8_t * ipprotos)2068 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2069 {
2070     SCEnter();
2071 
2072     AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2073     AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2074     AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2075 
2076     SCReturn;
2077 }
2078 
AppLayerProtoDetectGetProtoByName(const char * alproto_name)2079 AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
2080 {
2081     SCEnter();
2082 
2083     AppProto a;
2084     AppProto b = StringToAppProto(alproto_name);
2085     for (a = 0; a < ALPROTO_MAX; a++) {
2086         if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2087             SCReturnCT(b, "AppProto");
2088         }
2089     }
2090 
2091     SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2092 }
2093 
AppLayerProtoDetectGetProtoName(AppProto alproto)2094 const char *AppLayerProtoDetectGetProtoName(AppProto alproto)
2095 {
2096     return alpd_ctx.alproto_names[alproto];
2097 }
2098 
AppLayerProtoDetectSupportedAppProtocols(AppProto * alprotos)2099 void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
2100 {
2101     SCEnter();
2102 
2103     memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2104 
2105     int alproto;
2106 
2107     for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2108         if (alpd_ctx.alproto_names[alproto] != NULL)
2109             alprotos[alproto] = 1;
2110     }
2111 
2112     SCReturn;
2113 }
2114 
2115 uint8_t expectation_proto[ALPROTO_MAX];
2116 
AppLayerProtoDetectPEGetIpprotos(AppProto alproto,uint8_t * ipprotos)2117 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2118                                              uint8_t *ipprotos)
2119 {
2120     if (expectation_proto[alproto] == IPPROTO_TCP) {
2121         ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2122     }
2123     if (expectation_proto[alproto] == IPPROTO_UDP) {
2124         ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2125     }
2126 }
2127 
AppLayerRegisterExpectationProto(uint8_t proto,AppProto alproto)2128 void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
2129 {
2130     if (expectation_proto[alproto]) {
2131         if (proto != expectation_proto[alproto]) {
2132             SCLogError(SC_ERR_NOT_SUPPORTED,
2133                        "Expectation on 2 IP protocols are not supported");
2134         }
2135     }
2136     expectation_proto[alproto] = proto;
2137 }
2138 
2139 /***** Unittests *****/
2140 
2141 #ifdef UNITTESTS
2142 
2143 #include "app-layer-htp.h"
2144 
2145 static AppLayerProtoDetectCtx alpd_ctx_ut;
2146 
AppLayerProtoDetectUnittestCtxBackup(void)2147 void AppLayerProtoDetectUnittestCtxBackup(void)
2148 {
2149     SCEnter();
2150     alpd_ctx_ut = alpd_ctx;
2151     memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2152     SCReturn;
2153 }
2154 
AppLayerProtoDetectUnittestCtxRestore(void)2155 void AppLayerProtoDetectUnittestCtxRestore(void)
2156 {
2157     SCEnter();
2158     alpd_ctx = alpd_ctx_ut;
2159     memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2160     SCReturn;
2161 }
2162 
AppLayerProtoDetectTest01(void)2163 static int AppLayerProtoDetectTest01(void)
2164 {
2165     AppLayerProtoDetectUnittestCtxBackup();
2166     AppLayerProtoDetectSetup();
2167 
2168     const char *buf = "HTTP";
2169     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2170     buf = "GET";
2171     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOSERVER);
2172 
2173     AppLayerProtoDetectPrepareState();
2174     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2175     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2176 
2177     AppLayerProtoDetectDeSetup();
2178     AppLayerProtoDetectUnittestCtxRestore();
2179     PASS;
2180 }
2181 
AppLayerProtoDetectTest02(void)2182 static int AppLayerProtoDetectTest02(void)
2183 {
2184     AppLayerProtoDetectUnittestCtxBackup();
2185     AppLayerProtoDetectSetup();
2186 
2187     const char *buf = "HTTP";
2188     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2189     buf = "ftp";
2190     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2191 
2192     AppLayerProtoDetectPrepareState();
2193     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2194     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2195 
2196     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2197     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2198 
2199     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP);
2200     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP);
2201 
2202     AppLayerProtoDetectDeSetup();
2203     AppLayerProtoDetectUnittestCtxRestore();
2204     PASS;
2205 }
2206 
AppLayerProtoDetectTest03(void)2207 static int AppLayerProtoDetectTest03(void)
2208 {
2209     AppLayerProtoDetectUnittestCtxBackup();
2210     AppLayerProtoDetectSetup();
2211 
2212     uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2213     AppProto pm_results[ALPROTO_MAX];
2214     memset(pm_results, 0, sizeof(pm_results));
2215     Flow f;
2216     memset(&f, 0x00, sizeof(f));
2217     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2218 
2219 
2220     const char *buf = "HTTP";
2221     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2222     buf = "220 ";
2223     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2224 
2225     AppLayerProtoDetectPrepareState();
2226     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2227      * it sets internal structures which depends on the above function. */
2228     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2229     FAIL_IF_NULL(alpd_tctx);
2230 
2231     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2232     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2233     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2234     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2235     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP);
2236     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP);
2237 
2238     bool rflow = false;
2239     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2240                                                  &f, l7data, sizeof(l7data),
2241                                                  STREAM_TOCLIENT,
2242                                                  pm_results, &rflow);
2243     FAIL_IF(cnt != 1);
2244     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2245 
2246     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2247     AppLayerProtoDetectDeSetup();
2248     AppLayerProtoDetectUnittestCtxRestore();
2249     PASS;
2250 }
2251 
AppLayerProtoDetectTest04(void)2252 static int AppLayerProtoDetectTest04(void)
2253 {
2254     AppLayerProtoDetectUnittestCtxBackup();
2255     AppLayerProtoDetectSetup();
2256 
2257     uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2258     Flow f;
2259     memset(&f, 0x00, sizeof(f));
2260     AppProto pm_results[ALPROTO_MAX];
2261     memset(pm_results, 0, sizeof(pm_results));
2262     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2263 
2264     const char *buf = "200 ";
2265     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 13, 0, STREAM_TOCLIENT);
2266 
2267     AppLayerProtoDetectPrepareState();
2268     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2269      * it sets internal structures which depends on the above function. */
2270     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2271     FAIL_IF_NULL(alpd_tctx);
2272 
2273     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2274     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2275     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2276     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2277     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP);
2278 
2279     bool rdir = false;
2280     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2281             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2282             pm_results, &rdir);
2283     FAIL_IF(cnt != 1);
2284     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2285 
2286     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2287     AppLayerProtoDetectDeSetup();
2288     AppLayerProtoDetectUnittestCtxRestore();
2289     PASS;
2290 }
2291 
AppLayerProtoDetectTest05(void)2292 static int AppLayerProtoDetectTest05(void)
2293 {
2294     AppLayerProtoDetectUnittestCtxBackup();
2295     AppLayerProtoDetectSetup();
2296 
2297     uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2298     AppProto pm_results[ALPROTO_MAX];
2299     memset(pm_results, 0, sizeof(pm_results));
2300     Flow f;
2301     memset(&f, 0x00, sizeof(f));
2302     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2303 
2304     const char *buf = "HTTP";
2305     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2306     buf = "220 ";
2307     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2308 
2309     AppLayerProtoDetectPrepareState();
2310     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2311      * it sets internal structures which depends on the above function. */
2312     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2313     FAIL_IF_NULL(alpd_tctx);
2314 
2315     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2316     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2317     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2318     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2319     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP);
2320     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP);
2321 
2322     bool rdir = false;
2323     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2324             &f, l7data, sizeof(l7data),
2325             STREAM_TOCLIENT,
2326             pm_results, &rdir);
2327     FAIL_IF(cnt != 1);
2328     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2329 
2330     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2331     AppLayerProtoDetectDeSetup();
2332     AppLayerProtoDetectUnittestCtxRestore();
2333     PASS;
2334 }
2335 
AppLayerProtoDetectTest06(void)2336 static int AppLayerProtoDetectTest06(void)
2337 {
2338     AppLayerProtoDetectUnittestCtxBackup();
2339     AppLayerProtoDetectSetup();
2340 
2341     uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2342     AppProto pm_results[ALPROTO_MAX];
2343     memset(pm_results, 0, sizeof(pm_results));
2344     Flow f;
2345     memset(&f, 0x00, sizeof(f));
2346     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2347 
2348     const char *buf = "HTTP";
2349     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2350     buf = "220 ";
2351     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2352 
2353     AppLayerProtoDetectPrepareState();
2354     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2355      * it sets internal structures which depends on the above function. */
2356     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2357     FAIL_IF_NULL(alpd_tctx);
2358 
2359     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2360     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2361     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2362     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2363     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP);
2364     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP);
2365 
2366     bool rdir = false;
2367     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2368             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2369             pm_results, &rdir);
2370     FAIL_IF(cnt != 1);
2371     FAIL_IF(pm_results[0] != ALPROTO_FTP);
2372 
2373     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2374     AppLayerProtoDetectDeSetup();
2375     AppLayerProtoDetectUnittestCtxRestore();
2376     PASS;
2377 }
2378 
AppLayerProtoDetectTest07(void)2379 static int AppLayerProtoDetectTest07(void)
2380 {
2381     AppLayerProtoDetectUnittestCtxBackup();
2382     AppLayerProtoDetectSetup();
2383 
2384     uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2385     Flow f;
2386     memset(&f, 0x00, sizeof(f));
2387     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2388     AppProto pm_results[ALPROTO_MAX];
2389     memset(pm_results, 0, sizeof(pm_results));
2390 
2391     const char *buf = "HTTP";
2392     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
2393 
2394     AppLayerProtoDetectPrepareState();
2395     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2396      * it sets internal structures which depends on the above function. */
2397     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2398 
2399     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2400     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2401     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2402     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2403     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP);
2404 
2405     bool rdir = false;
2406     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2407             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2408             pm_results, &rdir);
2409     FAIL_IF(cnt != 0);
2410 
2411     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2412     AppLayerProtoDetectDeSetup();
2413     AppLayerProtoDetectUnittestCtxRestore();
2414     PASS;
2415 }
2416 
AppLayerProtoDetectTest08(void)2417 static int AppLayerProtoDetectTest08(void)
2418 {
2419     AppLayerProtoDetectUnittestCtxBackup();
2420     AppLayerProtoDetectSetup();
2421 
2422     uint8_t l7data[] = {
2423         0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2424         0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2425         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2426         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2427         0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2428         0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2429         0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2430         0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2431         0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2432         0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2433         0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2434         0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2435         0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2436         0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2437         0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2438         0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2439         0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2440         0x00
2441     };
2442     AppProto pm_results[ALPROTO_MAX];
2443     memset(pm_results, 0, sizeof(pm_results));
2444     Flow f;
2445     memset(&f, 0x00, sizeof(f));
2446     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2447 
2448     const char *buf = "|ff|SMB";
2449     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2450 
2451     AppLayerProtoDetectPrepareState();
2452     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2453      * it sets internal structures which depends on the above function. */
2454     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2455     FAIL_IF_NULL(alpd_tctx);
2456 
2457     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2458     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2459     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2460     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2461     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB);
2462 
2463     bool rdir = false;
2464     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2465             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2466             pm_results, &rdir);
2467     FAIL_IF(cnt != 1);
2468     FAIL_IF(pm_results[0] != ALPROTO_SMB);
2469 
2470     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2471     AppLayerProtoDetectDeSetup();
2472     AppLayerProtoDetectUnittestCtxRestore();
2473     PASS;
2474 }
2475 
AppLayerProtoDetectTest09(void)2476 static int AppLayerProtoDetectTest09(void)
2477 {
2478     AppLayerProtoDetectUnittestCtxBackup();
2479     AppLayerProtoDetectSetup();
2480 
2481     uint8_t l7data[] = {
2482         0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2483         0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2484         0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2485         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2486         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2487         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2488         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2489         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2490         0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2491         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2492         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2493         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2494         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2495         0x00, 0x02, 0x02
2496     };
2497     AppProto pm_results[ALPROTO_MAX];
2498     memset(pm_results, 0, sizeof(pm_results));
2499     Flow f;
2500     memset(&f, 0x00, sizeof(f));
2501     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2502 
2503     const char *buf = "|fe|SMB";
2504     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2505 
2506     AppLayerProtoDetectPrepareState();
2507     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2508      * it sets internal structures which depends on the above function. */
2509     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2510     FAIL_IF_NULL(alpd_tctx);
2511 
2512     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2513     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2514     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2515     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2516     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB);
2517 
2518     bool rdir = false;
2519     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2520             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2521             pm_results, &rdir);
2522     FAIL_IF(cnt != 1);
2523     FAIL_IF(pm_results[0] != ALPROTO_SMB);
2524 
2525     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2526     AppLayerProtoDetectDeSetup();
2527     AppLayerProtoDetectUnittestCtxRestore();
2528     PASS;
2529 }
2530 
AppLayerProtoDetectTest10(void)2531 static int AppLayerProtoDetectTest10(void)
2532 {
2533     AppLayerProtoDetectUnittestCtxBackup();
2534     AppLayerProtoDetectSetup();
2535 
2536     uint8_t l7data[] = {
2537         0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2538         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2539         0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2540         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2541         0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2542         0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2543         0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2544         0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2545         0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2546     };
2547     AppProto pm_results[ALPROTO_MAX];
2548     memset(pm_results, 0, sizeof(pm_results));
2549     Flow f;
2550     memset(&f, 0x00, sizeof(f));
2551     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2552 
2553     const char *buf = "|05 00|";
2554     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2555 
2556     AppLayerProtoDetectPrepareState();
2557     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2558      * it sets internal structures which depends on the above function. */
2559     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2560     FAIL_IF_NULL(alpd_tctx);
2561 
2562     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2563     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2564     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2565     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2566     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_DCERPC);
2567 
2568     bool rdir = false;
2569     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2570             &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2571             pm_results, &rdir);
2572     FAIL_IF(cnt != 1);
2573     FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2574 
2575     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2576     AppLayerProtoDetectDeSetup();
2577     AppLayerProtoDetectUnittestCtxRestore();
2578     PASS;
2579 }
2580 
2581 /**
2582  * \test Why we still get http for connect... obviously because
2583  *       we also match on the reply, duh
2584  */
AppLayerProtoDetectTest11(void)2585 static int AppLayerProtoDetectTest11(void)
2586 {
2587     AppLayerProtoDetectUnittestCtxBackup();
2588     AppLayerProtoDetectSetup();
2589 
2590     uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2591     uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2592     AppProto pm_results[ALPROTO_MAX];
2593     memset(pm_results, 0, sizeof(pm_results));
2594     Flow f;
2595     memset(&f, 0x00, sizeof(f));
2596     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2597 
2598     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2599     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2600     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2601     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2602     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2603     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2604     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2605     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
2606 
2607     AppLayerProtoDetectPrepareState();
2608     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2609      * it sets internal structures which depends on the above function. */
2610     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2611     FAIL_IF_NULL(alpd_tctx);
2612 
2613     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2614     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2615     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2616     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2617 
2618     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP);
2619     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP);
2620     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP);
2621     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP);
2622     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP);
2623     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP);
2624     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP);
2625     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP);
2626 
2627     bool rdir = false;
2628     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2629             &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2630             pm_results, &rdir);
2631     FAIL_IF(cnt != 1);
2632     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2633 
2634     memset(pm_results, 0, sizeof(pm_results));
2635     cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2636             &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2637             pm_results, &rdir);
2638     FAIL_IF(cnt != 1);
2639     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2640 
2641     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2642     AppLayerProtoDetectDeSetup();
2643     AppLayerProtoDetectUnittestCtxRestore();
2644     PASS;
2645 }
2646 
2647 /**
2648  * \test AlpProtoSignature test
2649  */
AppLayerProtoDetectTest12(void)2650 static int AppLayerProtoDetectTest12(void)
2651 {
2652     AppLayerProtoDetectUnittestCtxBackup();
2653     AppLayerProtoDetectSetup();
2654 
2655     int r = 0;
2656 
2657     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2658     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2659         alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2660     {
2661         printf("failure 1\n");
2662         goto end;
2663     }
2664 
2665     AppLayerProtoDetectPrepareState();
2666     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2667         printf("failure 2\n");
2668         goto end;
2669     }
2670     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2671         alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2672     {
2673         printf("failure 3\n");
2674         goto end;
2675     }
2676     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
2677         printf("failure 4\n");
2678         goto end;
2679     }
2680     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2681         printf("failure 5\n");
2682         goto end;
2683     }
2684     if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2685         printf("failure 6\n");
2686         goto end;
2687     }
2688 
2689     r = 1;
2690 
2691  end:
2692     AppLayerProtoDetectDeSetup();
2693     AppLayerProtoDetectUnittestCtxRestore();
2694     return r;
2695 }
2696 
2697 /**
2698  * \test What about if we add some sigs only for udp but call for tcp?
2699  *       It should not detect any proto
2700  */
AppLayerProtoDetectTest13(void)2701 static int AppLayerProtoDetectTest13(void)
2702 {
2703     AppLayerProtoDetectUnittestCtxBackup();
2704     AppLayerProtoDetectSetup();
2705 
2706     uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2707     uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2708     AppProto pm_results[ALPROTO_MAX];
2709 
2710     Flow f;
2711     memset(&f, 0x00, sizeof(f));
2712     f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2713 
2714     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2715     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2716     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2717     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2718     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2719     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2720     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2721     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
2722 
2723     AppLayerProtoDetectPrepareState();
2724     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2725      * it sets internal structures which depends on the above function. */
2726     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2727 
2728     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2729     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2730 
2731     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP);
2732     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP);
2733     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP);
2734     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP);
2735     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP);
2736     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP);
2737     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP);
2738     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP);
2739 
2740     memset(pm_results, 0, sizeof(pm_results));
2741     bool rdir = false;
2742     uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2743             &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2744             pm_results, &rdir);
2745     FAIL_IF(cnt != 0);
2746 
2747     memset(pm_results, 0, sizeof(pm_results));
2748     cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2749             &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2750             pm_results, &rdir);
2751     FAIL_IF(cnt != 0);
2752 
2753     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2754     AppLayerProtoDetectDeSetup();
2755     AppLayerProtoDetectUnittestCtxRestore();
2756     PASS;
2757 }
2758 
2759 /**
2760  * \test What about if we add some sigs only for udp calling it for UDP?
2761  *       It should detect ALPROTO_HTTP (over udp). This is just a check
2762  *       to ensure that TCP/UDP differences work correctly.
2763  */
AppLayerProtoDetectTest14(void)2764 static int AppLayerProtoDetectTest14(void)
2765 {
2766     AppLayerProtoDetectUnittestCtxBackup();
2767     AppLayerProtoDetectSetup();
2768 
2769     uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2770     uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2771     AppProto pm_results[ALPROTO_MAX];
2772     uint32_t cnt;
2773     Flow f;
2774     memset(&f, 0x00, sizeof(f));
2775     f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2776 
2777     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2778     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2779     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2780     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2781     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2782     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2783     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2784     AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
2785 
2786     AppLayerProtoDetectPrepareState();
2787     /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2788      * it sets internal structures which depends on the above function. */
2789     AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2790     FAIL_IF_NULL(alpd_tctx);
2791 
2792     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2793     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2794 
2795     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP);
2796     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP);
2797     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP);
2798     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP);
2799     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP);
2800     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP);
2801     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP);
2802     FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP);
2803 
2804     memset(pm_results, 0, sizeof(pm_results));
2805     bool rdir = false;
2806     cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2807             &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2808             pm_results, &rdir);
2809     FAIL_IF(cnt != 1);
2810     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2811 
2812     memset(pm_results, 0, sizeof(pm_results));
2813     cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2814             &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2815             pm_results, &rdir);
2816     FAIL_IF(cnt != 1);
2817     FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2818 
2819     AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2820     AppLayerProtoDetectDeSetup();
2821     AppLayerProtoDetectUnittestCtxRestore();
2822     PASS;
2823 }
2824 
2825 typedef struct AppLayerProtoDetectPPTestDataElement_ {
2826     const char *alproto_name;
2827     AppProto alproto;
2828     uint16_t port;
2829     uint32_t alproto_mask;
2830     uint32_t min_depth;
2831     uint32_t max_depth;
2832 } AppLayerProtoDetectPPTestDataElement;
2833 
2834 typedef struct AppLayerProtoDetectPPTestDataPort_ {
2835     uint16_t port;
2836     uint32_t alproto_mask;
2837     uint16_t dp_max_depth;
2838     uint16_t sp_max_depth;
2839 
2840     AppLayerProtoDetectPPTestDataElement *toserver_element;
2841     AppLayerProtoDetectPPTestDataElement *toclient_element;
2842     int ts_no_of_element;
2843     int tc_no_of_element;
2844 } AppLayerProtoDetectPPTestDataPort;
2845 
2846 
2847 typedef struct AppLayerProtoDetectPPTestDataIPProto_ {
2848     uint8_t ipproto;
2849 
2850     AppLayerProtoDetectPPTestDataPort *port;
2851     int no_of_port;
2852 } AppLayerProtoDetectPPTestDataIPProto;
2853 
AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser * pp,AppLayerProtoDetectPPTestDataIPProto * ip_proto,int no_of_ip_proto)2854 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2855                                          AppLayerProtoDetectPPTestDataIPProto *ip_proto,
2856                                          int no_of_ip_proto)
2857 {
2858     int result = 0;
2859     int i = -1, j = -1 , k = -1;
2860 #ifdef DEBUG
2861     int dir = 0;
2862 #endif
2863     for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2864         if (pp->ipproto != ip_proto[i].ipproto)
2865             goto end;
2866 
2867         AppLayerProtoDetectProbingParserPort *pp_port = pp->port;
2868         for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2869             if (pp_port->port != ip_proto[i].port[k].port)
2870                 goto end;
2871             if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2872                 goto end;
2873             if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2874                 goto end;
2875             if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2876                 goto end;
2877             if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2878                 goto end;
2879 
2880             AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2881 #ifdef DEBUG
2882             dir = 0;
2883 #endif
2884             for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2885                  j++, pp_element = pp_element->next) {
2886 
2887                 if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2888                     goto end;
2889                 }
2890                 if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2891                     goto end;
2892                 }
2893                 if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2894                     goto end;
2895                 }
2896                 if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2897                     goto end;
2898                 }
2899                 if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2900                     goto end;
2901                 }
2902             } /* for */
2903             if (pp_element != NULL)
2904                 goto end;
2905 
2906             pp_element = pp_port->sp;
2907 #ifdef DEBUG
2908             dir = 1;
2909 #endif
2910             for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2911                 if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2912                     goto end;
2913                 }
2914                 if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2915                     goto end;
2916                 }
2917                 if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2918                     goto end;
2919                 }
2920                 if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2921                     goto end;
2922                 }
2923                 if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2924                     goto end;
2925                 }
2926             } /* for */
2927             if (pp_element != NULL)
2928                 goto end;
2929         }
2930         if (pp_port != NULL)
2931             goto end;
2932     }
2933     if (pp != NULL)
2934         goto end;
2935 
2936     result = 1;
2937  end:
2938 #ifdef DEBUG
2939     printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2940 #endif
2941     return result;
2942 }
2943 
ProbingParserDummyForTesting(Flow * f,uint8_t direction,const uint8_t * input,uint32_t input_len,uint8_t * rdir)2944 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2945                                              const uint8_t *input,
2946                                              uint32_t input_len, uint8_t *rdir)
2947 {
2948     return 0;
2949 }
2950 
AppLayerProtoDetectTest15(void)2951 static int AppLayerProtoDetectTest15(void)
2952 {
2953     AppLayerProtoDetectUnittestCtxBackup();
2954     AppLayerProtoDetectSetup();
2955 
2956     int result = 0;
2957 
2958     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2959                                   "80",
2960                                   ALPROTO_HTTP,
2961                                   5, 8,
2962                                   STREAM_TOSERVER,
2963                                   ProbingParserDummyForTesting, NULL);
2964     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2965                                   "80",
2966                                   ALPROTO_SMB,
2967                                   5, 6,
2968                                   STREAM_TOSERVER,
2969                                   ProbingParserDummyForTesting, NULL);
2970     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2971                                   "80",
2972                                   ALPROTO_FTP,
2973                                   7, 10,
2974                                   STREAM_TOSERVER,
2975                                   ProbingParserDummyForTesting, NULL);
2976 
2977     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2978                                   "81",
2979                                   ALPROTO_DCERPC,
2980                                   9, 10,
2981                                   STREAM_TOSERVER,
2982                                   ProbingParserDummyForTesting, NULL);
2983     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2984                                   "81",
2985                                   ALPROTO_FTP,
2986                                   7, 15,
2987                                   STREAM_TOSERVER,
2988                                   ProbingParserDummyForTesting, NULL);
2989     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2990                                   "0",
2991                                   ALPROTO_SMTP,
2992                                   12, 0,
2993                                   STREAM_TOSERVER,
2994                                   ProbingParserDummyForTesting, NULL);
2995     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2996                                   "0",
2997                                   ALPROTO_TLS,
2998                                   12, 18,
2999                                   STREAM_TOSERVER,
3000                                   ProbingParserDummyForTesting, NULL);
3001 
3002     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3003                                   "85",
3004                                   ALPROTO_DCERPC,
3005                                   9, 10,
3006                                   STREAM_TOSERVER,
3007                                   ProbingParserDummyForTesting, NULL);
3008     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3009                                   "85",
3010                                   ALPROTO_FTP,
3011                                   7, 15,
3012                                   STREAM_TOSERVER,
3013                                   ProbingParserDummyForTesting, NULL);
3014     result = 1;
3015 
3016     AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3017                                   "85",
3018                                   ALPROTO_IMAP,
3019                                   12, 23,
3020                                   STREAM_TOSERVER,
3021                                   ProbingParserDummyForTesting, NULL);
3022 
3023     /* toclient */
3024     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3025                                   "0",
3026                                   ALPROTO_JABBER,
3027                                   12, 23,
3028                                   STREAM_TOCLIENT,
3029                                   ProbingParserDummyForTesting, NULL);
3030     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3031                                   "0",
3032                                   ALPROTO_IRC,
3033                                   12, 14,
3034                                   STREAM_TOCLIENT,
3035                                   ProbingParserDummyForTesting, NULL);
3036 
3037     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3038                                   "85",
3039                                   ALPROTO_DCERPC,
3040                                   9, 10,
3041                                   STREAM_TOCLIENT,
3042                                   ProbingParserDummyForTesting, NULL);
3043     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3044                                   "81",
3045                                   ALPROTO_FTP,
3046                                   7, 15,
3047                                   STREAM_TOCLIENT,
3048                                   ProbingParserDummyForTesting, NULL);
3049     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3050                                   "0",
3051                                   ALPROTO_TLS,
3052                                   12, 18,
3053                                   STREAM_TOCLIENT,
3054                                   ProbingParserDummyForTesting, NULL);
3055     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3056                                   "80",
3057                                   ALPROTO_HTTP,
3058                                   5, 8,
3059                                   STREAM_TOCLIENT,
3060                                   ProbingParserDummyForTesting, NULL);
3061     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3062                                   "81",
3063                                   ALPROTO_DCERPC,
3064                                   9, 10,
3065                                   STREAM_TOCLIENT,
3066                                   ProbingParserDummyForTesting, NULL);
3067     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3068                                   "90",
3069                                   ALPROTO_FTP,
3070                                   7, 15,
3071                                   STREAM_TOCLIENT,
3072                                   ProbingParserDummyForTesting, NULL);
3073     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3074                                   "80",
3075                                   ALPROTO_SMB,
3076                                   5, 6,
3077                                   STREAM_TOCLIENT,
3078                                   ProbingParserDummyForTesting, NULL);
3079     AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3080                                   "85",
3081                                   ALPROTO_IMAP,
3082                                   12, 23,
3083                                   STREAM_TOCLIENT,
3084                                   ProbingParserDummyForTesting, NULL);
3085     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3086                                   "0",
3087                                   ALPROTO_SMTP,
3088                                   12, 17,
3089                                   STREAM_TOCLIENT,
3090                                   ProbingParserDummyForTesting, NULL);
3091     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3092                                   "80",
3093                                   ALPROTO_FTP,
3094                                   7, 10,
3095                                   STREAM_TOCLIENT,
3096                                   ProbingParserDummyForTesting, NULL);
3097 
3098     AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3099         { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3100           { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3101           { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3102           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3103           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3104           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3105           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3106         };
3107     AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
3108         { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3109           { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3110           { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3111           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3112           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3113           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3114           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3115         };
3116 
3117     AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3118         { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3119           { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3120           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3121           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3122           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3123           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3124         };
3125     AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3126         { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3127           { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3128           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3129           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3130           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3131           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3132         };
3133 
3134     AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3135         { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3136           { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3137           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3138           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3139           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3140           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3141         };
3142     AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3143         { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3144           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3145           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3146           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3147           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3148         };
3149 
3150     AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3151         { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3152           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3153           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3154           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3155         };
3156     AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3157         { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3158           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3159           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3160           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3161           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3162         };
3163 
3164     AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3165         { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3166           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3167           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3168           { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3169         };
3170     AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3171         { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3172           { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3173           { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3174           { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3175         };
3176 
3177 
3178     AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3179         { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3180         };
3181     AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3182         { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3183         };
3184 
3185     AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3186         { 80,
3187           ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3188            (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3189           ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3190            (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3191           23,
3192           element_ts_80, element_tc_80,
3193           sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3194           sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3195         },
3196         { 81,
3197           ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3198            (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3199           ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
3200            (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3201           23,
3202           element_ts_81, element_tc_81,
3203           sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3204           sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3205         },
3206         { 85,
3207           ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3208            (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3209           ((1 << ALPROTO_DCERPC) |
3210            (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3211           23,
3212           element_ts_85, element_tc_85,
3213           sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3214           sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
3215         },
3216         { 90,
3217           ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3218           ((1 << ALPROTO_FTP) |
3219            (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3220           23,
3221           element_ts_90, element_tc_90,
3222           sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3223           sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
3224         },
3225         { 0,
3226           ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3227           ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3228           23,
3229           element_ts_0, element_tc_0,
3230           sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3231           sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
3232         }
3233     };
3234 
3235     AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3236         { 85,
3237             (1 << ALPROTO_IMAP),
3238             (1 << ALPROTO_IMAP),
3239             23,
3240             element_ts_85_udp, element_tc_85_udp,
3241             sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3242             sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3243             },
3244         };
3245 
3246     AppLayerProtoDetectPPTestDataIPProto ip_proto[] = {
3247         { IPPROTO_TCP,
3248           ports_tcp,
3249           sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3250         },
3251         { IPPROTO_UDP,
3252           ports_udp,
3253           sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3254         },
3255     };
3256 
3257 
3258     if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3259                                       sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3260         goto end;
3261     }
3262     result = 1;
3263 
3264  end:
3265     AppLayerProtoDetectDeSetup();
3266     AppLayerProtoDetectUnittestCtxRestore();
3267     return result;
3268 }
3269 
3270 
3271 /** \test test if the engine detect the proto and match with it */
AppLayerProtoDetectTest16(void)3272 static int AppLayerProtoDetectTest16(void)
3273 {
3274     int result = 0;
3275     Flow *f = NULL;
3276     HtpState *http_state = NULL;
3277     uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3278         "User-Agent: Mozilla/1.0\r\n"
3279         "Cookie: hellocatch\r\n\r\n";
3280     uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3281     TcpSession ssn;
3282     Packet *p = NULL;
3283     Signature *s = NULL;
3284     ThreadVars tv;
3285     DetectEngineThreadCtx *det_ctx = NULL;
3286     DetectEngineCtx *de_ctx = NULL;
3287     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3288 
3289     memset(&tv, 0, sizeof(ThreadVars));
3290     memset(&ssn, 0, sizeof(TcpSession));
3291 
3292     p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3293     if (p == NULL) {
3294         printf("packet setup failed: ");
3295         goto end;
3296     }
3297 
3298     f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3299     if (f == NULL) {
3300         printf("flow setup failed: ");
3301         goto end;
3302     }
3303     f->protoctx = &ssn;
3304     f->proto = IPPROTO_TCP;
3305     p->flow = f;
3306 
3307     p->flowflags |= FLOW_PKT_TOSERVER;
3308     p->flowflags |= FLOW_PKT_ESTABLISHED;
3309     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
3310 
3311     f->alproto = ALPROTO_HTTP;
3312 
3313     StreamTcpInitConfig(TRUE);
3314 
3315     de_ctx = DetectEngineCtxInit();
3316     if (de_ctx == NULL) {
3317         goto end;
3318     }
3319     de_ctx->flags |= DE_QUIET;
3320 
3321     s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3322                                    "(msg:\"Test content option\"; "
3323                                    "sid:1;)");
3324     if (s == NULL) {
3325         goto end;
3326     }
3327 
3328     SigGroupBuild(de_ctx);
3329     DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3330 
3331     FLOWLOCK_WRLOCK(f);
3332     int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3333                                 STREAM_TOSERVER, http_buf1, http_buf1_len);
3334     if (r != 0) {
3335         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3336         FLOWLOCK_UNLOCK(f);
3337         goto end;
3338     }
3339     FLOWLOCK_UNLOCK(f);
3340 
3341     http_state = f->alstate;
3342     if (http_state == NULL) {
3343         printf("no http state: ");
3344         goto end;
3345     }
3346 
3347     /* do detect */
3348     SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3349 
3350     if (!PacketAlertCheck(p, 1)) {
3351         printf("sig 1 didn't alert, but it should: ");
3352         goto end;
3353     }
3354     result = 1;
3355  end:
3356     if (alp_tctx != NULL)
3357         AppLayerParserThreadCtxFree(alp_tctx);
3358     if (det_ctx != NULL)
3359         DetectEngineThreadCtxDeinit(&tv, det_ctx);
3360     if (de_ctx != NULL)
3361         SigGroupCleanup(de_ctx);
3362     if (de_ctx != NULL)
3363         DetectEngineCtxFree(de_ctx);
3364 
3365     StreamTcpFreeConfig(TRUE);
3366 
3367     UTHFreePackets(&p, 1);
3368     UTHFreeFlow(f);
3369     return result;
3370 }
3371 
3372 /** \test test if the engine detect the proto on a non standar port
3373  * and match with it */
AppLayerProtoDetectTest17(void)3374 static int AppLayerProtoDetectTest17(void)
3375 {
3376     int result = 0;
3377     Flow *f = NULL;
3378     HtpState *http_state = NULL;
3379     uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3380         "User-Agent: Mozilla/1.0\r\n"
3381         "Cookie: hellocatch\r\n\r\n";
3382     uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3383     TcpSession ssn;
3384     Packet *p = NULL;
3385     Signature *s = NULL;
3386     ThreadVars tv;
3387     DetectEngineThreadCtx *det_ctx = NULL;
3388     DetectEngineCtx *de_ctx = NULL;
3389     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3390 
3391     memset(&tv, 0, sizeof(ThreadVars));
3392     memset(&ssn, 0, sizeof(TcpSession));
3393 
3394     p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3395 
3396     f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3397     if (f == NULL)
3398         goto end;
3399     f->protoctx = &ssn;
3400     f->proto = IPPROTO_TCP;
3401     p->flow = f;
3402     p->flowflags |= FLOW_PKT_TOSERVER;
3403     p->flowflags |= FLOW_PKT_ESTABLISHED;
3404     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
3405     f->alproto = ALPROTO_HTTP;
3406 
3407     StreamTcpInitConfig(TRUE);
3408 
3409     de_ctx = DetectEngineCtxInit();
3410     if (de_ctx == NULL) {
3411         goto end;
3412     }
3413     de_ctx->flags |= DE_QUIET;
3414 
3415     s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3416                                    "(msg:\"http over non standar port\"; "
3417                                    "sid:1;)");
3418     if (s == NULL) {
3419         goto end;
3420     }
3421 
3422     SigGroupBuild(de_ctx);
3423     DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3424 
3425     FLOWLOCK_WRLOCK(f);
3426     int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3427                                 STREAM_TOSERVER, http_buf1, http_buf1_len);
3428     if (r != 0) {
3429         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3430         FLOWLOCK_UNLOCK(f);
3431         goto end;
3432     }
3433     FLOWLOCK_UNLOCK(f);
3434 
3435     http_state = f->alstate;
3436     if (http_state == NULL) {
3437         printf("no http state: ");
3438         goto end;
3439     }
3440 
3441     /* do detect */
3442     SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3443 
3444     if (!PacketAlertCheck(p, 1)) {
3445         printf("sig 1 didn't alert, but it should: ");
3446         goto end;
3447     }
3448 
3449     result = 1;
3450 
3451  end:
3452     if (alp_tctx != NULL)
3453         AppLayerParserThreadCtxFree(alp_tctx);
3454     if (det_ctx != NULL)
3455         DetectEngineThreadCtxDeinit(&tv, det_ctx);
3456     if (de_ctx != NULL)
3457         SigGroupCleanup(de_ctx);
3458     if (de_ctx != NULL)
3459         DetectEngineCtxFree(de_ctx);
3460 
3461     StreamTcpFreeConfig(TRUE);
3462 
3463     UTHFreePackets(&p, 1);
3464     UTHFreeFlow(f);
3465     return result;
3466 }
3467 
3468 /** \test test if the engine detect the proto and doesn't match
3469  * because the sig expects another proto (ex ftp)*/
AppLayerProtoDetectTest18(void)3470 static int AppLayerProtoDetectTest18(void)
3471 {
3472     int result = 0;
3473     Flow *f = NULL;
3474     HtpState *http_state = NULL;
3475     uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3476         "User-Agent: Mozilla/1.0\r\n"
3477         "Cookie: hellocatch\r\n\r\n";
3478     uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3479     TcpSession ssn;
3480     Packet *p = NULL;
3481     Signature *s = NULL;
3482     ThreadVars tv;
3483     DetectEngineThreadCtx *det_ctx = NULL;
3484     DetectEngineCtx *de_ctx = NULL;
3485     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3486 
3487     memset(&tv, 0, sizeof(ThreadVars));
3488     memset(&ssn, 0, sizeof(TcpSession));
3489 
3490     p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3491 
3492     f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3493     if (f == NULL)
3494         goto end;
3495     f->protoctx = &ssn;
3496     f->proto = IPPROTO_TCP;
3497     p->flow = f;
3498     p->flowflags |= FLOW_PKT_TOSERVER;
3499     p->flowflags |= FLOW_PKT_ESTABLISHED;
3500     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
3501     f->alproto = ALPROTO_HTTP;
3502 
3503     StreamTcpInitConfig(TRUE);
3504 
3505     de_ctx = DetectEngineCtxInit();
3506     if (de_ctx == NULL) {
3507         goto end;
3508     }
3509     de_ctx->flags |= DE_QUIET;
3510 
3511     s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3512                                    "(msg:\"Test content option\"; "
3513                                    "sid:1;)");
3514     if (s == NULL) {
3515         goto end;
3516     }
3517 
3518     SigGroupBuild(de_ctx);
3519     DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3520 
3521     FLOWLOCK_WRLOCK(f);
3522     int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3523                                 STREAM_TOSERVER, http_buf1, http_buf1_len);
3524     if (r != 0) {
3525         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3526         FLOWLOCK_UNLOCK(f);
3527         goto end;
3528     }
3529     FLOWLOCK_UNLOCK(f);
3530 
3531     http_state = f->alstate;
3532     if (http_state == NULL) {
3533         printf("no http state: ");
3534         goto end;
3535     }
3536 
3537     /* do detect */
3538     SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3539 
3540     if (PacketAlertCheck(p, 1)) {
3541         printf("sig 1 alerted, but it should not (it's not ftp): ");
3542         goto end;
3543     }
3544 
3545     result = 1;
3546  end:
3547     if (alp_tctx != NULL)
3548         AppLayerParserThreadCtxFree(alp_tctx);
3549     if (det_ctx != NULL)
3550         DetectEngineThreadCtxDeinit(&tv, det_ctx);
3551     if (de_ctx != NULL)
3552         SigGroupCleanup(de_ctx);
3553     if (de_ctx != NULL)
3554         DetectEngineCtxFree(de_ctx);
3555 
3556     StreamTcpFreeConfig(TRUE);
3557 
3558     UTHFreePackets(&p, 1);
3559     UTHFreeFlow(f);
3560     return result;
3561 }
3562 
3563 /** \test test if the engine detect the proto and doesn't match
3564  * because the packet has another proto (ex ftp) */
AppLayerProtoDetectTest19(void)3565 static int AppLayerProtoDetectTest19(void)
3566 {
3567     int result = 0;
3568     Flow *f = NULL;
3569     uint8_t http_buf1[] = "MPUT one\r\n";
3570     uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3571     TcpSession ssn;
3572     Packet *p = NULL;
3573     Signature *s = NULL;
3574     ThreadVars tv;
3575     DetectEngineThreadCtx *det_ctx = NULL;
3576     DetectEngineCtx *de_ctx = NULL;
3577     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3578 
3579     memset(&tv, 0, sizeof(ThreadVars));
3580     memset(&ssn, 0, sizeof(TcpSession));
3581 
3582     p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3583 
3584     f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3585     if (f == NULL)
3586         goto end;
3587     f->protoctx = &ssn;
3588     f->proto = IPPROTO_TCP;
3589     p->flow = f;
3590     p->flowflags |= FLOW_PKT_TOSERVER;
3591     p->flowflags |= FLOW_PKT_ESTABLISHED;
3592     p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
3593     f->alproto = ALPROTO_FTP;
3594 
3595     StreamTcpInitConfig(TRUE);
3596 
3597     de_ctx = DetectEngineCtxInit();
3598     if (de_ctx == NULL) {
3599         goto end;
3600     }
3601     de_ctx->flags |= DE_QUIET;
3602 
3603     s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3604                                    "(msg:\"http over non standar port\"; "
3605                                    "sid:1;)");
3606     if (s == NULL) {
3607         goto end;
3608     }
3609 
3610     SigGroupBuild(de_ctx);
3611     DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3612 
3613     FLOWLOCK_WRLOCK(f);
3614     int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3615                                 STREAM_TOSERVER, http_buf1, http_buf1_len);
3616     if (r != 0) {
3617         printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3618         FLOWLOCK_UNLOCK(f);
3619         goto end;
3620     }
3621     FLOWLOCK_UNLOCK(f);
3622 
3623     /* do detect */
3624     SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3625 
3626     if (PacketAlertCheck(p, 1)) {
3627         printf("sig 1 alerted, but it should not (it's ftp): ");
3628         goto end;
3629     }
3630 
3631     result = 1;
3632 
3633  end:
3634     if (alp_tctx != NULL)
3635         AppLayerParserThreadCtxFree(alp_tctx);
3636     if (det_ctx != NULL)
3637         DetectEngineThreadCtxDeinit(&tv, det_ctx);
3638     if (de_ctx != NULL)
3639         SigGroupCleanup(de_ctx);
3640     if (de_ctx != NULL)
3641         DetectEngineCtxFree(de_ctx);
3642 
3643     StreamTcpFreeConfig(TRUE);
3644     UTHFreePackets(&p, 1);
3645     UTHFreeFlow(f);
3646     return result;
3647 }
3648 
AppLayerProtoDetectUnittestsRegister(void)3649 void AppLayerProtoDetectUnittestsRegister(void)
3650 {
3651     SCEnter();
3652 
3653     UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3654     UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3655     UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3656     UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3657     UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3658     UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3659     UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3660     UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3661     UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3662     UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3663     UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3664     UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3665     UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3666     UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3667     UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3668     UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3669     UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3670     UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3671     UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3672 
3673     SCReturn;
3674 }
3675 
3676 #endif /* UNITTESTS */
3677