1 /* Copyright (C) 2007-2014 Open Information Security Foundation
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
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.
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
21 * \author Victor Julien <victor@inliniac.net>
22 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
25 #include "suricata-common.h"
29 #include "threadvars.h"
30 #include "tm-threads.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"
40 #include "util-print.h"
41 #include "util-pool.h"
42 #include "util-unittest.h"
43 #include "util-unittest-helper.h"
44 #include "util-validate.h"
47 #include "flow-util.h"
48 #include "flow-private.h"
50 #include "stream-tcp-private.h"
51 #include "stream-tcp-reassemble.h"
52 #include "stream-tcp.h"
55 #include "app-layer.h"
56 #include "app-layer-protos.h"
57 #include "app-layer-parser.h"
58 #include "app-layer-detect-proto.h"
59 #include "app-layer-expectation.h"
62 #include "util-memcmp.h"
64 #include "util-debug.h"
65 #include "util-validate.h"
69 typedef struct AppLayerProtoDetectProbingParserElement_
{
71 /* \todo don't really need it. See if you can get rid of it */
73 /* \todo calculate at runtime and get rid of this var */
74 uint32_t alproto_mask
;
75 /* the min length of data that has to be supplied to invoke the parser */
77 /* the max length of data after which this parser won't be invoked */
80 /* the to_server probing parser function */
81 ProbingParserFPtr ProbingParserTs
;
83 /* the to_client probing parser function */
84 ProbingParserFPtr ProbingParserTc
;
86 struct AppLayerProtoDetectProbingParserElement_
*next
;
87 } AppLayerProtoDetectProbingParserElement
;
89 typedef struct AppLayerProtoDetectProbingParserPort_
{
90 /* the port no for which probing parser(s) are invoked */
93 uint32_t alproto_mask
;
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
;
99 AppLayerProtoDetectProbingParserElement
*dp
;
100 AppLayerProtoDetectProbingParserElement
*sp
;
102 struct AppLayerProtoDetectProbingParserPort_
*next
;
103 } AppLayerProtoDetectProbingParserPort
;
105 typedef struct AppLayerProtoDetectProbingParser_
{
107 AppLayerProtoDetectProbingParserPort
*port
;
109 struct AppLayerProtoDetectProbingParser_
*next
;
110 } AppLayerProtoDetectProbingParser
;
112 typedef struct AppLayerProtoDetectPMSignature_
{
114 uint8_t direction
; /**< direction for midstream */
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
;
124 typedef struct AppLayerProtoDetectPMCtx_
{
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
132 AppLayerProtoDetectPMSignature
**map
;
133 AppLayerProtoDetectPMSignature
*head
;
135 /* \todo we don't need this except at setup time. Get rid of it. */
138 } AppLayerProtoDetectPMCtx
;
140 typedef struct AppLayerProtoDetectCtxIpproto_
{
141 /* 0 - toserver, 1 - toclient */
142 AppLayerProtoDetectPMCtx ctx_pm
[2];
143 } AppLayerProtoDetectCtxIpproto
;
146 * \brief The app layer protocol detection context.
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
];
154 /* Global SPM thread context prototype. */
155 SpmGlobalThreadCtx
*spm_global_thread_ctx
;
157 AppLayerProtoDetectProbingParser
*ctx_pp
;
159 /* Indicates the protocols that have registered themselves
160 * for protocol detection. This table is independent of the
162 const char *alproto_names
[ALPROTO_MAX
];
163 } AppLayerProtoDetectCtx
;
165 typedef struct AppLayerProtoDetectAliases_
{
166 const char *proto_name
;
167 const char *proto_alias
;
168 struct AppLayerProtoDetectAliases_
*next
;
169 } AppLayerProtoDetectAliases
;
172 * \brief The app layer protocol detection thread context.
174 struct AppLayerProtoDetectThreadCtx_
{
175 PrefilterRuleStore pmq
;
176 /* The value 2 is for direction(0 - toserver, 1 - toclient). */
177 MpmThreadCtx mpm_tctx
[FLOW_PROTO_DEFAULT
][2];
178 SpmThreadCtx
*spm_thread_ctx
;
181 /* The global app layer proto detection context. */
182 static AppLayerProtoDetectCtx alpd_ctx
;
183 static AppLayerProtoDetectAliases
*alpda_ctx
= NULL
;
185 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto
,
188 /***** Static Internal Calls: Protocol Retrieval *****/
191 * \brief Handle SPM search for Signature
192 * \param buflen full size of the input buffer
193 * \param searchlen pattern matching portion of buffer */
194 static AppProto
AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature
*s
,
195 AppLayerProtoDetectThreadCtx
*tctx
, Flow
*f
, uint8_t flags
, const uint8_t *buf
,
196 uint32_t buflen
, uint16_t searchlen
, bool *rflow
)
200 if (s
->cd
->offset
> searchlen
) {
201 SCLogDebug("s->co->offset (%"PRIu16
") > searchlen (%"PRIu16
")",
202 s
->cd
->offset
, searchlen
);
203 SCReturnUInt(ALPROTO_UNKNOWN
);
205 if (s
->cd
->depth
> searchlen
) {
206 SCLogDebug("s->co->depth (%"PRIu16
") > searchlen (%"PRIu16
")",
207 s
->cd
->depth
, searchlen
);
208 SCReturnUInt(ALPROTO_UNKNOWN
);
211 const uint8_t *sbuf
= buf
+ s
->cd
->offset
;
212 uint16_t ssearchlen
= s
->cd
->depth
- s
->cd
->offset
;
213 SCLogDebug("s->co->offset (%"PRIu16
") s->cd->depth (%"PRIu16
")",
214 s
->cd
->offset
, s
->cd
->depth
);
216 uint8_t *found
= SpmScan(s
->cd
->spm_ctx
, tctx
->spm_thread_ctx
,
219 SCReturnUInt(ALPROTO_UNKNOWN
);
222 uint8_t direction
= (flags
& (STREAM_TOSERVER
| STREAM_TOCLIENT
));
223 SCLogDebug("matching, s->direction %s, our dir %s",
224 (s
->direction
& STREAM_TOSERVER
) ? "toserver" : "toclient",
225 (flags
& STREAM_TOSERVER
) ? "toserver" : "toclient");
226 if (s
->PPFunc
== NULL
) {
227 if (direction
== s
->direction
) {
228 SCLogDebug("direction is correct");
230 SCLogDebug("direction is wrong, rflow = true");
233 /* validate using Probing Parser */
235 if (s
->pp_min_depth
> buflen
) {
236 SCLogDebug("PP can't be run yet as pp_min_depth %u > buflen %u",
237 s
->pp_min_depth
, buflen
);
238 SCReturnInt(ALPROTO_UNKNOWN
);
242 AppProto r
= s
->PPFunc(f
, flags
, buf
, buflen
, &rdir
);
243 if (r
== s
->alproto
) {
244 SCLogDebug("found %s/%u, rdir %02x reverse_flow? %s",
245 AppProtoToString(r
), r
, rdir
,
246 (rdir
&& direction
!= rdir
) ? "true" : "false");
247 *rflow
= (rdir
&& direction
!= rdir
);
248 SCReturnUInt(s
->alproto
);
249 } else if (r
== ALPROTO_FAILED
) {
250 SCReturnUInt(ALPROTO_FAILED
);
252 /* unknown: lets see if we will try again later */
253 if (s
->pp_max_depth
< buflen
) {
254 SCLogDebug("depth reached and answer inconclusive: fail");
255 SCReturnUInt(ALPROTO_FAILED
);
257 SCReturnUInt(ALPROTO_UNKNOWN
);
260 SCReturnUInt(s
->alproto
);
264 * \retval 0 no matches
265 * \retval -1 no matches, mpm depth reached
267 static inline int PMGetProtoInspect(AppLayerProtoDetectThreadCtx
*tctx
,
268 AppLayerProtoDetectPMCtx
*pm_ctx
, MpmThreadCtx
*mpm_tctx
, Flow
*f
, const uint8_t *buf
,
269 uint32_t buflen
, uint8_t flags
, AppProto
*pm_results
, bool *rflow
)
273 // maxdepth is u16, so minimum is u16
274 uint16_t searchlen
= (uint16_t)MIN(buflen
, pm_ctx
->mpm_ctx
.maxdepth
);
275 SCLogDebug("searchlen %u buflen %u", searchlen
, buflen
);
277 /* do the mpm search */
278 uint32_t search_cnt
= mpm_table
[pm_ctx
->mpm_ctx
.mpm_type
].Search(
279 &pm_ctx
->mpm_ctx
, mpm_tctx
, &tctx
->pmq
,
281 if (search_cnt
== 0) {
282 if (buflen
>= pm_ctx
->mpm_ctx
.maxdepth
)
287 /* alproto bit field */
288 uint8_t pm_results_bf
[(ALPROTO_MAX
/ 8) + 1];
289 memset(pm_results_bf
, 0, sizeof(pm_results_bf
));
291 /* loop through unique pattern id's. Can't use search_cnt here,
292 * as that contains all matches, tctx->pmq.pattern_id_array_cnt
293 * contains only *unique* matches. */
294 for (uint32_t cnt
= 0; cnt
< tctx
->pmq
.rule_id_array_cnt
; cnt
++) {
295 const AppLayerProtoDetectPMSignature
*s
= pm_ctx
->map
[tctx
->pmq
.rule_id_array
[cnt
]];
297 AppProto proto
= AppLayerProtoDetectPMMatchSignature(
298 s
, tctx
, f
, flags
, buf
, buflen
, searchlen
, rflow
);
300 /* store each unique proto once */
301 if (AppProtoIsValid(proto
) &&
302 !(pm_results_bf
[proto
/ 8] & (1 << (proto
% 8))) )
304 pm_results
[pm_matches
++] = proto
;
305 pm_results_bf
[proto
/ 8] |= 1 << (proto
% 8);
310 if (pm_matches
== 0 && buflen
>= pm_ctx
->pp_max_len
) {
313 PmqReset(&tctx
->pmq
);
318 * \brief Run Pattern Sigs against buffer
319 * \param direction direction for the patterns
320 * \param pm_results[out] AppProto array of size ALPROTO_MAX */
321 static AppProto
AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx
*tctx
, Flow
*f
,
322 const uint8_t *buf
, uint32_t buflen
, uint8_t flags
, AppProto
*pm_results
, bool *rflow
)
326 pm_results
[0] = ALPROTO_UNKNOWN
;
328 AppLayerProtoDetectPMCtx
*pm_ctx
;
329 MpmThreadCtx
*mpm_tctx
;
332 if (f
->protomap
>= FLOW_PROTO_DEFAULT
) {
333 pm_results
[0] = ALPROTO_FAILED
;
337 if (flags
& STREAM_TOSERVER
) {
338 pm_ctx
= &alpd_ctx
.ctx_ipp
[f
->protomap
].ctx_pm
[0];
339 mpm_tctx
= &tctx
->mpm_tctx
[f
->protomap
][0];
341 pm_ctx
= &alpd_ctx
.ctx_ipp
[f
->protomap
].ctx_pm
[1];
342 mpm_tctx
= &tctx
->mpm_tctx
[f
->protomap
][1];
344 if (likely(pm_ctx
->mpm_ctx
.pattern_cnt
> 0)) {
345 m
= PMGetProtoInspect(tctx
, pm_ctx
, mpm_tctx
, f
, buf
, buflen
, flags
, pm_results
, rflow
);
347 /* pattern found, yay */
349 FLOW_SET_PM_DONE(f
, flags
);
350 SCReturnUInt((uint16_t)m
);
352 /* handle non-found in non-midstream case */
353 } else if (!stream_config
.midstream
) {
354 /* we can give up if mpm gave no results and its search depth
357 FLOW_SET_PM_DONE(f
, flags
);
362 SCReturnUInt((uint16_t)m
);
364 /* handle non-found in midstream case */
366 if (flags
& STREAM_TOSERVER
) {
367 pm_ctx
= &alpd_ctx
.ctx_ipp
[f
->protomap
].ctx_pm
[1];
368 mpm_tctx
= &tctx
->mpm_tctx
[f
->protomap
][1];
370 pm_ctx
= &alpd_ctx
.ctx_ipp
[f
->protomap
].ctx_pm
[0];
371 mpm_tctx
= &tctx
->mpm_tctx
[f
->protomap
][0];
373 SCLogDebug("no matches and in midstream mode, lets try the "
374 "*patterns for the other side");
377 if (likely(pm_ctx
->mpm_ctx
.pattern_cnt
> 0)) {
378 om
= PMGetProtoInspect(
379 tctx
, pm_ctx
, mpm_tctx
, f
, buf
, buflen
, flags
, pm_results
, rflow
);
383 FLOW_SET_PM_DONE(f
, flags
);
384 SCReturnUInt((uint16_t)om
);
386 /* both sides failed */
387 } else if (om
< 0 && m
&& m
< 0) {
388 FLOW_SET_PM_DONE(f
, flags
);
391 /* one side still uncertain */
392 } else if (om
== 0 || m
== 0) {
399 static AppLayerProtoDetectProbingParserElement
*AppLayerProtoDetectGetProbingParser(
400 AppLayerProtoDetectProbingParser
*pp
, uint8_t ipproto
, AppProto alproto
)
402 AppLayerProtoDetectProbingParserElement
*pp_elem
= NULL
;
403 AppLayerProtoDetectProbingParserPort
*pp_port
= NULL
;
406 if (pp
->ipproto
== ipproto
)
414 while (pp_port
!= NULL
) {
415 if (pp_port
->dp
!= NULL
&& pp_port
->dp
->alproto
== alproto
) {
416 pp_elem
= pp_port
->dp
;
419 if (pp_port
->sp
!= NULL
&& pp_port
->sp
->alproto
== alproto
) {
420 pp_elem
= pp_port
->sp
;
423 pp_port
= pp_port
->next
;
426 SCReturnPtr(pp_elem
, "AppLayerProtoDetectProbingParserElement *");
429 static AppLayerProtoDetectProbingParserPort
*AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser
*pp
,
433 AppLayerProtoDetectProbingParserPort
*pp_port
= NULL
;
436 if (pp
->ipproto
== ipproto
)
446 while (pp_port
!= NULL
) {
447 if (pp_port
->port
== port
|| pp_port
->port
== 0) {
450 pp_port
= pp_port
->next
;
454 SCReturnPtr(pp_port
, "AppLayerProtoDetectProbingParserPort *");
459 * \brief Call the probing expectation to see if there is some for this flow.
462 static AppProto
AppLayerProtoDetectPEGetProto(Flow
*f
, uint8_t ipproto
, uint8_t flags
)
464 AppProto alproto
= ALPROTO_UNKNOWN
;
466 SCLogDebug("expectation check for %p (dir %d)", f
, flags
);
467 FLOW_SET_PE_DONE(f
, flags
);
469 alproto
= AppLayerExpectationHandle(f
, flags
);
474 static inline AppProto
PPGetProto(const AppLayerProtoDetectProbingParserElement
*pe
, Flow
*f
,
475 uint8_t flags
, const uint8_t *buf
, uint32_t buflen
, uint32_t *alproto_masks
, uint8_t *rdir
)
478 if ((buflen
< pe
->min_depth
) ||
479 (alproto_masks
[0] & pe
->alproto_mask
)) {
484 AppProto alproto
= ALPROTO_UNKNOWN
;
485 if (flags
& STREAM_TOSERVER
&& pe
->ProbingParserTs
!= NULL
) {
486 alproto
= pe
->ProbingParserTs(f
, flags
, buf
, buflen
, rdir
);
487 } else if (flags
& STREAM_TOCLIENT
&& pe
->ProbingParserTc
!= NULL
) {
488 alproto
= pe
->ProbingParserTc(f
, flags
, buf
, buflen
, rdir
);
490 if (AppProtoIsValid(alproto
)) {
491 SCReturnUInt(alproto
);
493 if (alproto
== ALPROTO_FAILED
||
494 (pe
->max_depth
!= 0 && buflen
> pe
->max_depth
)) {
495 alproto_masks
[0] |= pe
->alproto_mask
;
500 SCReturnUInt(ALPROTO_UNKNOWN
);
504 * \brief Call the probing parser if it exists for this flow.
506 * First we check the flow's dp as it's most likely to match. If that didn't
507 * lead to a PP, we try the sp.
510 static AppProto
AppLayerProtoDetectPPGetProto(Flow
*f
, const uint8_t *buf
, uint32_t buflen
,
511 uint8_t ipproto
, const uint8_t flags
, bool *reverse_flow
)
513 const AppLayerProtoDetectProbingParserPort
*pp_port_dp
= NULL
;
514 const AppLayerProtoDetectProbingParserPort
*pp_port_sp
= NULL
;
515 const AppLayerProtoDetectProbingParserElement
*pe0
= NULL
;
516 const AppLayerProtoDetectProbingParserElement
*pe1
= NULL
;
517 const AppLayerProtoDetectProbingParserElement
*pe2
= NULL
;
518 AppProto alproto
= ALPROTO_UNKNOWN
;
519 uint32_t *alproto_masks
;
521 uint8_t idir
= (flags
& (STREAM_TOSERVER
| STREAM_TOCLIENT
));
523 uint16_t dp
= f
->protodetect_dp
? f
->protodetect_dp
: FLOW_GET_DP(f
);
524 uint16_t sp
= FLOW_GET_SP(f
);
525 bool probe_is_found
= false;
529 SWAP_VARS(uint16_t, dp
, sp
); /* look up parsers in rev dir */
531 SCLogDebug("%u->%u %s", sp
, dp
,
532 (dir
== STREAM_TOSERVER
) ? "toserver" : "toclient");
534 if (dir
== STREAM_TOSERVER
) {
535 /* first try the destination port */
536 pp_port_dp
= AppLayerProtoDetectGetProbingParsers(alpd_ctx
.ctx_pp
, ipproto
, dp
);
537 alproto_masks
= &f
->probing_parser_toserver_alproto_masks
;
538 if (pp_port_dp
!= NULL
) {
539 SCLogDebug("toserver - Probing parser found for destination port %"PRIu16
, dp
);
541 /* found based on destination port, so use dp registration */
542 pe1
= pp_port_dp
->dp
;
544 SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16
, dp
);
547 pp_port_sp
= AppLayerProtoDetectGetProbingParsers(alpd_ctx
.ctx_pp
, ipproto
, sp
);
548 if (pp_port_sp
!= NULL
) {
549 SCLogDebug("toserver - Probing parser found for source port %"PRIu16
, sp
);
551 /* found based on source port, so use sp registration */
552 pe2
= pp_port_sp
->sp
;
554 SCLogDebug("toserver - No probing parser registered for source port %"PRIu16
, sp
);
557 /* first try the destination port */
558 pp_port_dp
= AppLayerProtoDetectGetProbingParsers(alpd_ctx
.ctx_pp
, ipproto
, dp
);
559 alproto_masks
= &f
->probing_parser_toclient_alproto_masks
;
560 if (pp_port_dp
!= NULL
) {
561 SCLogDebug("toclient - Probing parser found for destination port %"PRIu16
, dp
);
563 /* found based on destination port, so use dp registration */
564 pe1
= pp_port_dp
->dp
;
566 SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16
, dp
);
569 pp_port_sp
= AppLayerProtoDetectGetProbingParsers(alpd_ctx
.ctx_pp
, ipproto
, sp
);
570 if (pp_port_sp
!= NULL
) {
571 SCLogDebug("toclient - Probing parser found for source port %"PRIu16
, sp
);
573 pe2
= pp_port_sp
->sp
;
575 SCLogDebug("toclient - No probing parser registered for source port %"PRIu16
, sp
);
579 if (dir
== STREAM_TOSERVER
&& f
->alproto_tc
!= ALPROTO_UNKNOWN
) {
580 pe0
= AppLayerProtoDetectGetProbingParser(alpd_ctx
.ctx_pp
, ipproto
, f
->alproto_tc
);
581 } else if (dir
== STREAM_TOCLIENT
&& f
->alproto_ts
!= ALPROTO_UNKNOWN
) {
582 pe0
= AppLayerProtoDetectGetProbingParser(alpd_ctx
.ctx_pp
, ipproto
, f
->alproto_ts
);
585 if (pe1
== NULL
&& pe2
== NULL
&& pe0
== NULL
) {
586 SCLogDebug("%s - No probing parsers found for either port",
587 (dir
== STREAM_TOSERVER
) ? "toserver":"toclient");
590 probe_is_found
= true;
593 /* run the parser(s): always call with original direction */
595 alproto
= PPGetProto(pe0
, f
, flags
, buf
, buflen
, alproto_masks
, &rdir
);
596 if (AppProtoIsValid(alproto
))
598 alproto
= PPGetProto(pe1
, f
, flags
, buf
, buflen
, alproto_masks
, &rdir
);
599 if (AppProtoIsValid(alproto
))
601 alproto
= PPGetProto(pe2
, f
, flags
, buf
, buflen
, alproto_masks
, &rdir
);
602 if (AppProtoIsValid(alproto
))
605 /* get the mask we need for this direction */
607 if (pp_port_dp
&& pp_port_sp
)
608 mask
= pp_port_dp
->alproto_mask
|pp_port_sp
->alproto_mask
;
610 mask
= pp_port_dp
->alproto_mask
;
612 mask
= pp_port_sp
->alproto_mask
;
614 if (alproto_masks
[0] == mask
) {
615 FLOW_SET_PP_DONE(f
, dir
);
616 SCLogDebug("%s, mask is now %08x, needed %08x, so done",
617 (dir
== STREAM_TOSERVER
) ? "toserver":"toclient",
618 alproto_masks
[0], mask
);
620 SCLogDebug("%s, mask is now %08x, need %08x",
621 (dir
== STREAM_TOSERVER
) ? "toserver":"toclient",
622 alproto_masks
[0], mask
);
627 if (stream_config
.midstream
&& idir
== dir
) {
628 if (idir
== STREAM_TOSERVER
) {
629 dir
= STREAM_TOCLIENT
;
631 dir
= STREAM_TOSERVER
;
633 SCLogDebug("no match + midstream, retry the other direction %s",
634 (dir
== STREAM_TOSERVER
) ? "toserver" : "toclient");
635 goto again_midstream
;
636 } else if (!probe_is_found
) {
637 FLOW_SET_PP_DONE(f
, idir
);
641 if (AppProtoIsValid(alproto
) && rdir
!= 0 && rdir
!= idir
) {
642 SCLogDebug("PP found %u, is reverse flow", alproto
);
643 *reverse_flow
= true;
646 SCLogDebug("%s, mask is now %08x",
647 (idir
== STREAM_TOSERVER
) ? "toserver":"toclient", alproto_masks
[0]);
648 SCReturnUInt(alproto
);
651 /***** Static Internal Calls: PP registration *****/
653 static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto
,
658 const AppLayerProtoDetectProbingParser
*pp
;
659 const AppLayerProtoDetectProbingParserPort
*pp_port
;
660 const AppLayerProtoDetectProbingParserElement
*pp_pe
;
662 for (pp
= alpd_ctx
.ctx_pp
; pp
!= NULL
; pp
= pp
->next
) {
663 for (pp_port
= pp
->port
; pp_port
!= NULL
; pp_port
= pp_port
->next
) {
664 for (pp_pe
= pp_port
->dp
; pp_pe
!= NULL
; pp_pe
= pp_pe
->next
) {
665 if (alproto
== pp_pe
->alproto
)
666 ipprotos
[pp
->ipproto
/ 8] |= 1 << (pp
->ipproto
% 8);
668 for (pp_pe
= pp_port
->sp
; pp_pe
!= NULL
; pp_pe
= pp_pe
->next
) {
669 if (alproto
== pp_pe
->alproto
)
670 ipprotos
[pp
->ipproto
/ 8] |= 1 << (pp
->ipproto
% 8);
678 static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto
)
682 if (!(alproto
> ALPROTO_UNKNOWN
&& alproto
< ALPROTO_FAILED
)) {
683 FatalError(SC_ERR_ALPARSER
, "Unknown protocol detected - %u", alproto
);
686 SCReturnUInt(1UL << (uint32_t)alproto
);
689 static AppLayerProtoDetectProbingParserElement
*AppLayerProtoDetectProbingParserElementAlloc(void)
693 AppLayerProtoDetectProbingParserElement
*p
= SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement
));
694 if (unlikely(p
== NULL
)) {
697 memset(p
, 0, sizeof(AppLayerProtoDetectProbingParserElement
));
699 SCReturnPtr(p
, "AppLayerProtoDetectProbingParserElement");
703 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement
*p
)
710 static AppLayerProtoDetectProbingParserPort
*AppLayerProtoDetectProbingParserPortAlloc(void)
714 AppLayerProtoDetectProbingParserPort
*p
= SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort
));
715 if (unlikely(p
== NULL
)) {
718 memset(p
, 0, sizeof(AppLayerProtoDetectProbingParserPort
));
720 SCReturnPtr(p
, "AppLayerProtoDetectProbingParserPort");
723 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort
*p
)
727 AppLayerProtoDetectProbingParserElement
*e
;
731 AppLayerProtoDetectProbingParserElement
*e_next
= e
->next
;
732 AppLayerProtoDetectProbingParserElementFree(e
);
738 AppLayerProtoDetectProbingParserElement
*e_next
= e
->next
;
739 AppLayerProtoDetectProbingParserElementFree(e
);
748 static AppLayerProtoDetectProbingParser
*AppLayerProtoDetectProbingParserAlloc(void)
752 AppLayerProtoDetectProbingParser
*p
= SCMalloc(sizeof(AppLayerProtoDetectProbingParser
));
753 if (unlikely(p
== NULL
)) {
756 memset(p
, 0, sizeof(AppLayerProtoDetectProbingParser
));
758 SCReturnPtr(p
, "AppLayerProtoDetectProbingParser");
761 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser
*p
)
765 AppLayerProtoDetectProbingParserPort
*pt
= p
->port
;
767 AppLayerProtoDetectProbingParserPort
*pt_next
= pt
->next
;
768 AppLayerProtoDetectProbingParserPortFree(pt
);
777 static AppLayerProtoDetectProbingParserElement
*
778 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto
,
783 AppLayerProtoDetectProbingParserElement
*pe
= AppLayerProtoDetectProbingParserElementAlloc();
785 pe
->alproto
= alproto
;
787 pe
->alproto_mask
= AppLayerProtoDetectProbingParserGetMask(alproto
);
788 pe
->min_depth
= min_depth
;
789 pe
->max_depth
= max_depth
;
792 if (max_depth
!= 0 && min_depth
>= max_depth
) {
793 SCLogError(SC_ERR_ALPARSER
, "Invalid arguments sent to "
794 "register the probing parser. min_depth >= max_depth");
797 if (alproto
<= ALPROTO_UNKNOWN
|| alproto
>= ALPROTO_MAX
) {
798 SCLogError(SC_ERR_ALPARSER
, "Invalid arguments sent to register "
799 "the probing parser. Invalid alproto - %d", alproto
);
803 SCReturnPtr(pe
, "AppLayerProtoDetectProbingParserElement");
805 AppLayerProtoDetectProbingParserElementFree(pe
);
806 SCReturnPtr(NULL
, "AppLayerProtoDetectProbingParserElement");
809 static AppLayerProtoDetectProbingParserElement
*
810 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement
*pe
)
814 AppLayerProtoDetectProbingParserElement
*new_pe
= AppLayerProtoDetectProbingParserElementAlloc();
816 new_pe
->alproto
= pe
->alproto
;
817 new_pe
->port
= pe
->port
;
818 new_pe
->alproto_mask
= pe
->alproto_mask
;
819 new_pe
->min_depth
= pe
->min_depth
;
820 new_pe
->max_depth
= pe
->max_depth
;
821 new_pe
->ProbingParserTs
= pe
->ProbingParserTs
;
822 new_pe
->ProbingParserTc
= pe
->ProbingParserTc
;
825 SCReturnPtr(new_pe
, "AppLayerProtoDetectProbingParserElement");
829 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser
*pp
)
833 AppLayerProtoDetectProbingParserPort
*pp_port
= NULL
;
834 AppLayerProtoDetectProbingParserElement
*pp_pe
= NULL
;
836 printf("\nProtocol Detection Configuration\n");
838 for ( ; pp
!= NULL
; pp
= pp
->next
) {
839 /* print ip protocol */
840 if (pp
->ipproto
== IPPROTO_TCP
)
841 printf("IPProto: TCP\n");
842 else if (pp
->ipproto
== IPPROTO_UDP
)
843 printf("IPProto: UDP\n");
845 printf("IPProto: %"PRIu8
"\n", pp
->ipproto
);
848 for ( ; pp_port
!= NULL
; pp_port
= pp_port
->next
) {
849 if (pp_port
->dp
!= NULL
) {
850 printf(" Port: %"PRIu16
"\n", pp_port
->port
);
852 printf(" Destination port: (max-depth: %"PRIu16
", "
853 "mask - %"PRIu32
")\n",
854 pp_port
->dp_max_depth
,
855 pp_port
->alproto_mask
);
857 for ( ; pp_pe
!= NULL
; pp_pe
= pp_pe
->next
) {
859 if (pp_pe
->alproto
== ALPROTO_HTTP1
)
860 printf(" alproto: ALPROTO_HTTP1\n");
861 else if (pp_pe
->alproto
== ALPROTO_FTP
)
862 printf(" alproto: ALPROTO_FTP\n");
863 else if (pp_pe
->alproto
== ALPROTO_FTPDATA
)
864 printf(" alproto: ALPROTO_FTPDATA\n");
865 else if (pp_pe
->alproto
== ALPROTO_SMTP
)
866 printf(" alproto: ALPROTO_SMTP\n");
867 else if (pp_pe
->alproto
== ALPROTO_TLS
)
868 printf(" alproto: ALPROTO_TLS\n");
869 else if (pp_pe
->alproto
== ALPROTO_SSH
)
870 printf(" alproto: ALPROTO_SSH\n");
871 else if (pp_pe
->alproto
== ALPROTO_IMAP
)
872 printf(" alproto: ALPROTO_IMAP\n");
873 else if (pp_pe
->alproto
== ALPROTO_JABBER
)
874 printf(" alproto: ALPROTO_JABBER\n");
875 else if (pp_pe
->alproto
== ALPROTO_SMB
)
876 printf(" alproto: ALPROTO_SMB\n");
877 else if (pp_pe
->alproto
== ALPROTO_DCERPC
)
878 printf(" alproto: ALPROTO_DCERPC\n");
879 else if (pp_pe
->alproto
== ALPROTO_IRC
)
880 printf(" alproto: ALPROTO_IRC\n");
881 else if (pp_pe
->alproto
== ALPROTO_DNS
)
882 printf(" alproto: ALPROTO_DNS\n");
883 else if (pp_pe
->alproto
== ALPROTO_MODBUS
)
884 printf(" alproto: ALPROTO_MODBUS\n");
885 else if (pp_pe
->alproto
== ALPROTO_ENIP
)
886 printf(" alproto: ALPROTO_ENIP\n");
887 else if (pp_pe
->alproto
== ALPROTO_NFS
)
888 printf(" alproto: ALPROTO_NFS\n");
889 else if (pp_pe
->alproto
== ALPROTO_NTP
)
890 printf(" alproto: ALPROTO_NTP\n");
891 else if (pp_pe
->alproto
== ALPROTO_TFTP
)
892 printf(" alproto: ALPROTO_TFTP\n");
893 else if (pp_pe
->alproto
== ALPROTO_IKE
)
894 printf(" alproto: ALPROTO_IKE\n");
895 else if (pp_pe
->alproto
== ALPROTO_KRB5
)
896 printf(" alproto: ALPROTO_KRB5\n");
897 else if (pp_pe
->alproto
== ALPROTO_DHCP
)
898 printf(" alproto: ALPROTO_DHCP\n");
899 else if (pp_pe
->alproto
== ALPROTO_SNMP
)
900 printf(" alproto: ALPROTO_SNMP\n");
901 else if (pp_pe
->alproto
== ALPROTO_SIP
)
902 printf(" alproto: ALPROTO_SIP\n");
903 else if (pp_pe
->alproto
== ALPROTO_TEMPLATE_RUST
)
904 printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
905 else if (pp_pe
->alproto
== ALPROTO_RFB
)
906 printf(" alproto: ALPROTO_RFB\n");
907 else if (pp_pe
->alproto
== ALPROTO_MQTT
)
908 printf(" alproto: ALPROTO_MQTT\n");
909 else if (pp_pe
->alproto
== ALPROTO_TEMPLATE
)
910 printf(" alproto: ALPROTO_TEMPLATE\n");
911 else if (pp_pe
->alproto
== ALPROTO_DNP3
)
912 printf(" alproto: ALPROTO_DNP3\n");
914 printf("impossible\n");
916 printf(" port: %"PRIu16
"\n", pp_pe
->port
);
917 printf(" mask: %"PRIu32
"\n", pp_pe
->alproto_mask
);
918 printf(" min_depth: %"PRIu32
"\n", pp_pe
->min_depth
);
919 printf(" max_depth: %"PRIu32
"\n", pp_pe
->max_depth
);
925 if (pp_port
->sp
== NULL
) {
929 printf(" Source port: (max-depth: %"PRIu16
", "
930 "mask - %"PRIu32
")\n",
931 pp_port
->sp_max_depth
,
932 pp_port
->alproto_mask
);
934 for ( ; pp_pe
!= NULL
; pp_pe
= pp_pe
->next
) {
936 if (pp_pe
->alproto
== ALPROTO_HTTP1
)
937 printf(" alproto: ALPROTO_HTTP1\n");
938 else if (pp_pe
->alproto
== ALPROTO_FTP
)
939 printf(" alproto: ALPROTO_FTP\n");
940 else if (pp_pe
->alproto
== ALPROTO_FTPDATA
)
941 printf(" alproto: ALPROTO_FTPDATA\n");
942 else if (pp_pe
->alproto
== ALPROTO_SMTP
)
943 printf(" alproto: ALPROTO_SMTP\n");
944 else if (pp_pe
->alproto
== ALPROTO_TLS
)
945 printf(" alproto: ALPROTO_TLS\n");
946 else if (pp_pe
->alproto
== ALPROTO_SSH
)
947 printf(" alproto: ALPROTO_SSH\n");
948 else if (pp_pe
->alproto
== ALPROTO_IMAP
)
949 printf(" alproto: ALPROTO_IMAP\n");
950 else if (pp_pe
->alproto
== ALPROTO_JABBER
)
951 printf(" alproto: ALPROTO_JABBER\n");
952 else if (pp_pe
->alproto
== ALPROTO_SMB
)
953 printf(" alproto: ALPROTO_SMB\n");
954 else if (pp_pe
->alproto
== ALPROTO_DCERPC
)
955 printf(" alproto: ALPROTO_DCERPC\n");
956 else if (pp_pe
->alproto
== ALPROTO_IRC
)
957 printf(" alproto: ALPROTO_IRC\n");
958 else if (pp_pe
->alproto
== ALPROTO_DNS
)
959 printf(" alproto: ALPROTO_DNS\n");
960 else if (pp_pe
->alproto
== ALPROTO_MODBUS
)
961 printf(" alproto: ALPROTO_MODBUS\n");
962 else if (pp_pe
->alproto
== ALPROTO_ENIP
)
963 printf(" alproto: ALPROTO_ENIP\n");
964 else if (pp_pe
->alproto
== ALPROTO_NFS
)
965 printf(" alproto: ALPROTO_NFS\n");
966 else if (pp_pe
->alproto
== ALPROTO_NTP
)
967 printf(" alproto: ALPROTO_NTP\n");
968 else if (pp_pe
->alproto
== ALPROTO_TFTP
)
969 printf(" alproto: ALPROTO_TFTP\n");
970 else if (pp_pe
->alproto
== ALPROTO_IKE
)
971 printf(" alproto: ALPROTO_IKE\n");
972 else if (pp_pe
->alproto
== ALPROTO_KRB5
)
973 printf(" alproto: ALPROTO_KRB5\n");
974 else if (pp_pe
->alproto
== ALPROTO_DHCP
)
975 printf(" alproto: ALPROTO_DHCP\n");
976 else if (pp_pe
->alproto
== ALPROTO_SNMP
)
977 printf(" alproto: ALPROTO_SNMP\n");
978 else if (pp_pe
->alproto
== ALPROTO_SIP
)
979 printf(" alproto: ALPROTO_SIP\n");
980 else if (pp_pe
->alproto
== ALPROTO_TEMPLATE_RUST
)
981 printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
982 else if (pp_pe
->alproto
== ALPROTO_RFB
)
983 printf(" alproto: ALPROTO_RFB\n");
984 else if (pp_pe
->alproto
== ALPROTO_MQTT
)
985 printf(" alproto: ALPROTO_MQTT\n");
986 else if (pp_pe
->alproto
== ALPROTO_TEMPLATE
)
987 printf(" alproto: ALPROTO_TEMPLATE\n");
988 else if (pp_pe
->alproto
== ALPROTO_DNP3
)
989 printf(" alproto: ALPROTO_DNP3\n");
991 printf("impossible\n");
993 printf(" port: %"PRIu16
"\n", pp_pe
->port
);
994 printf(" mask: %"PRIu32
"\n", pp_pe
->alproto_mask
);
995 printf(" min_depth: %"PRIu32
"\n", pp_pe
->min_depth
);
996 printf(" max_depth: %"PRIu32
"\n", pp_pe
->max_depth
);
1007 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement
**head_pe
,
1008 AppLayerProtoDetectProbingParserElement
*new_pe
)
1012 if (*head_pe
== NULL
) {
1017 if ((*head_pe
)->port
== 0) {
1018 if (new_pe
->port
!= 0) {
1019 new_pe
->next
= *head_pe
;
1022 AppLayerProtoDetectProbingParserElement
*temp_pe
= *head_pe
;
1023 while (temp_pe
->next
!= NULL
)
1024 temp_pe
= temp_pe
->next
;
1025 temp_pe
->next
= new_pe
;
1028 AppLayerProtoDetectProbingParserElement
*temp_pe
= *head_pe
;
1029 if (new_pe
->port
== 0) {
1030 while (temp_pe
->next
!= NULL
)
1031 temp_pe
= temp_pe
->next
;
1032 temp_pe
->next
= new_pe
;
1034 while (temp_pe
->next
!= NULL
&& temp_pe
->next
->port
!= 0)
1035 temp_pe
= temp_pe
->next
;
1036 new_pe
->next
= temp_pe
->next
;
1037 temp_pe
->next
= new_pe
;
1046 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser
**head_pp
,
1047 AppLayerProtoDetectProbingParser
*new_pp
)
1051 if (*head_pp
== NULL
) {
1056 AppLayerProtoDetectProbingParser
*temp_pp
= *head_pp
;
1057 while (temp_pp
->next
!= NULL
)
1058 temp_pp
= temp_pp
->next
;
1059 temp_pp
->next
= new_pp
;
1065 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort
**head_port
,
1066 AppLayerProtoDetectProbingParserPort
*new_port
)
1070 if (*head_port
== NULL
) {
1071 *head_port
= new_port
;
1075 if ((*head_port
)->port
== 0) {
1076 new_port
->next
= *head_port
;
1077 *head_port
= new_port
;
1079 AppLayerProtoDetectProbingParserPort
*temp_port
= *head_port
;
1080 while (temp_port
->next
!= NULL
&& temp_port
->next
->port
!= 0) {
1081 temp_port
= temp_port
->next
;
1083 new_port
->next
= temp_port
->next
;
1084 temp_port
->next
= new_port
;
1091 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser
**pp
,
1095 uint16_t min_depth
, uint16_t max_depth
,
1097 ProbingParserFPtr ProbingParser1
,
1098 ProbingParserFPtr ProbingParser2
)
1102 /* get the top level ipproto pp */
1103 AppLayerProtoDetectProbingParser
*curr_pp
= *pp
;
1104 while (curr_pp
!= NULL
) {
1105 if (curr_pp
->ipproto
== ipproto
)
1107 curr_pp
= curr_pp
->next
;
1109 if (curr_pp
== NULL
) {
1110 AppLayerProtoDetectProbingParser
*new_pp
= AppLayerProtoDetectProbingParserAlloc();
1111 new_pp
->ipproto
= ipproto
;
1112 AppLayerProtoDetectProbingParserAppend(pp
, new_pp
);
1116 /* get the top level port pp */
1117 AppLayerProtoDetectProbingParserPort
*curr_port
= curr_pp
->port
;
1118 while (curr_port
!= NULL
) {
1119 if (curr_port
->port
== port
)
1121 curr_port
= curr_port
->next
;
1123 if (curr_port
== NULL
) {
1124 AppLayerProtoDetectProbingParserPort
*new_port
= AppLayerProtoDetectProbingParserPortAlloc();
1125 new_port
->port
= port
;
1126 AppLayerProtoDetectProbingParserPortAppend(&curr_pp
->port
, new_port
);
1127 curr_port
= new_port
;
1128 if (direction
& STREAM_TOSERVER
) {
1129 curr_port
->dp_max_depth
= max_depth
;
1131 curr_port
->sp_max_depth
= max_depth
;
1134 AppLayerProtoDetectProbingParserPort
*zero_port
;
1136 zero_port
= curr_pp
->port
;
1137 while (zero_port
!= NULL
&& zero_port
->port
!= 0) {
1138 zero_port
= zero_port
->next
;
1140 if (zero_port
!= NULL
) {
1141 AppLayerProtoDetectProbingParserElement
*zero_pe
;
1143 zero_pe
= zero_port
->dp
;
1144 for ( ; zero_pe
!= NULL
; zero_pe
= zero_pe
->next
) {
1145 if (curr_port
->dp
== NULL
)
1146 curr_port
->dp_max_depth
= zero_pe
->max_depth
;
1147 if (zero_pe
->max_depth
== 0)
1148 curr_port
->dp_max_depth
= zero_pe
->max_depth
;
1149 if (curr_port
->dp_max_depth
!= 0 &&
1150 curr_port
->dp_max_depth
< zero_pe
->max_depth
) {
1151 curr_port
->dp_max_depth
= zero_pe
->max_depth
;
1154 AppLayerProtoDetectProbingParserElement
*dup_pe
=
1155 AppLayerProtoDetectProbingParserElementDuplicate(zero_pe
);
1156 AppLayerProtoDetectProbingParserElementAppend(&curr_port
->dp
, dup_pe
);
1157 curr_port
->alproto_mask
|= dup_pe
->alproto_mask
;
1160 zero_pe
= zero_port
->sp
;
1161 for ( ; zero_pe
!= NULL
; zero_pe
= zero_pe
->next
) {
1162 if (curr_port
->sp
== NULL
)
1163 curr_port
->sp_max_depth
= zero_pe
->max_depth
;
1164 if (zero_pe
->max_depth
== 0)
1165 curr_port
->sp_max_depth
= zero_pe
->max_depth
;
1166 if (curr_port
->sp_max_depth
!= 0 &&
1167 curr_port
->sp_max_depth
< zero_pe
->max_depth
) {
1168 curr_port
->sp_max_depth
= zero_pe
->max_depth
;
1171 AppLayerProtoDetectProbingParserElement
*dup_pe
=
1172 AppLayerProtoDetectProbingParserElementDuplicate(zero_pe
);
1173 AppLayerProtoDetectProbingParserElementAppend(&curr_port
->sp
, dup_pe
);
1174 curr_port
->alproto_mask
|= dup_pe
->alproto_mask
;
1176 } /* if (zero_port != NULL) */
1177 } /* if (curr_port == NULL) */
1179 /* insert the pe_pp */
1180 AppLayerProtoDetectProbingParserElement
*curr_pe
;
1181 if (direction
& STREAM_TOSERVER
)
1182 curr_pe
= curr_port
->dp
;
1184 curr_pe
= curr_port
->sp
;
1185 while (curr_pe
!= NULL
) {
1186 if (curr_pe
->alproto
== alproto
) {
1187 SCLogError(SC_ERR_ALPARSER
, "Duplicate pp registered - "
1188 "ipproto - %"PRIu8
" Port - %"PRIu16
" "
1189 "App Protocol - NULL, App Protocol(ID) - "
1190 "%"PRIu16
" min_depth - %"PRIu16
" "
1191 "max_dept - %"PRIu16
".",
1192 ipproto
, port
, alproto
,
1193 min_depth
, max_depth
);
1196 curr_pe
= curr_pe
->next
;
1198 /* Get a new parser element */
1199 AppLayerProtoDetectProbingParserElement
*new_pe
=
1200 AppLayerProtoDetectProbingParserElementCreate(alproto
,
1202 min_depth
, max_depth
);
1206 AppLayerProtoDetectProbingParserElement
**head_pe
;
1207 if (direction
& STREAM_TOSERVER
) {
1208 curr_pe
->ProbingParserTs
= ProbingParser1
;
1209 curr_pe
->ProbingParserTc
= ProbingParser2
;
1210 if (curr_port
->dp
== NULL
)
1211 curr_port
->dp_max_depth
= new_pe
->max_depth
;
1212 if (new_pe
->max_depth
== 0)
1213 curr_port
->dp_max_depth
= new_pe
->max_depth
;
1214 if (curr_port
->dp_max_depth
!= 0 &&
1215 curr_port
->dp_max_depth
< new_pe
->max_depth
) {
1216 curr_port
->dp_max_depth
= new_pe
->max_depth
;
1218 curr_port
->alproto_mask
|= new_pe
->alproto_mask
;
1219 head_pe
= &curr_port
->dp
;
1221 curr_pe
->ProbingParserTs
= ProbingParser2
;
1222 curr_pe
->ProbingParserTc
= ProbingParser1
;
1223 if (curr_port
->sp
== NULL
)
1224 curr_port
->sp_max_depth
= new_pe
->max_depth
;
1225 if (new_pe
->max_depth
== 0)
1226 curr_port
->sp_max_depth
= new_pe
->max_depth
;
1227 if (curr_port
->sp_max_depth
!= 0 &&
1228 curr_port
->sp_max_depth
< new_pe
->max_depth
) {
1229 curr_port
->sp_max_depth
= new_pe
->max_depth
;
1231 curr_port
->alproto_mask
|= new_pe
->alproto_mask
;
1232 head_pe
= &curr_port
->sp
;
1234 AppLayerProtoDetectProbingParserElementAppend(head_pe
, new_pe
);
1236 if (curr_port
->port
== 0) {
1237 AppLayerProtoDetectProbingParserPort
*temp_port
= curr_pp
->port
;
1238 while (temp_port
!= NULL
&& temp_port
->port
!= 0) {
1239 if (direction
& STREAM_TOSERVER
) {
1240 if (temp_port
->dp
== NULL
)
1241 temp_port
->dp_max_depth
= curr_pe
->max_depth
;
1242 if (curr_pe
->max_depth
== 0)
1243 temp_port
->dp_max_depth
= curr_pe
->max_depth
;
1244 if (temp_port
->dp_max_depth
!= 0 &&
1245 temp_port
->dp_max_depth
< curr_pe
->max_depth
) {
1246 temp_port
->dp_max_depth
= curr_pe
->max_depth
;
1248 AppLayerProtoDetectProbingParserElementAppend(&temp_port
->dp
,
1249 AppLayerProtoDetectProbingParserElementDuplicate(curr_pe
));
1250 temp_port
->alproto_mask
|= curr_pe
->alproto_mask
;
1252 if (temp_port
->sp
== NULL
)
1253 temp_port
->sp_max_depth
= curr_pe
->max_depth
;
1254 if (curr_pe
->max_depth
== 0)
1255 temp_port
->sp_max_depth
= curr_pe
->max_depth
;
1256 if (temp_port
->sp_max_depth
!= 0 &&
1257 temp_port
->sp_max_depth
< curr_pe
->max_depth
) {
1258 temp_port
->sp_max_depth
= curr_pe
->max_depth
;
1260 AppLayerProtoDetectProbingParserElementAppend(&temp_port
->sp
,
1261 AppLayerProtoDetectProbingParserElementDuplicate(curr_pe
));
1262 temp_port
->alproto_mask
|= curr_pe
->alproto_mask
;
1264 temp_port
= temp_port
->next
;
1272 /***** Static Internal Calls: PM registration *****/
1274 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto
,
1279 for (uint8_t i
= 0; i
< FLOW_PROTO_DEFAULT
; i
++) {
1280 uint8_t ipproto
= FlowGetReverseProtoMapping(i
);
1281 for (int j
= 0; j
< 2; j
++) {
1282 AppLayerProtoDetectPMCtx
*pm_ctx
= &alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
];
1284 for (SigIntId x
= 0; x
< pm_ctx
->max_sig_id
; x
++) {
1285 const AppLayerProtoDetectPMSignature
*s
= pm_ctx
->map
[x
];
1286 if (s
->alproto
== alproto
)
1287 ipprotos
[ipproto
/ 8] |= 1 << (ipproto
% 8);
1295 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx
*ctx
)
1299 typedef struct TempContainer_
{
1301 uint16_t content_len
;
1305 AppLayerProtoDetectPMSignature
*s
= NULL
;
1306 uint32_t struct_total_size
= 0;
1307 uint32_t content_total_size
= 0;
1308 /* array hash buffer */
1309 uint8_t *ahb
= NULL
;
1310 uint8_t *content
= NULL
;
1311 uint16_t content_len
= 0;
1312 PatIntId max_id
= 0;
1313 TempContainer
*struct_offset
= NULL
;
1314 uint8_t *content_offset
= NULL
;
1317 if (ctx
->head
== NULL
)
1320 for (s
= ctx
->head
; s
!= NULL
; s
= s
->next
) {
1321 struct_total_size
+= sizeof(TempContainer
);
1322 content_total_size
+= s
->cd
->content_len
;
1326 ahb
= SCMalloc(sizeof(uint8_t) * (struct_total_size
+ content_total_size
));
1327 if (unlikely(ahb
== NULL
))
1330 struct_offset
= (TempContainer
*)ahb
;
1331 content_offset
= ahb
+ struct_total_size
;
1332 for (s
= ctx
->head
; s
!= NULL
; s
= s
->next
) {
1333 TempContainer
*tcdup
= (TempContainer
*)ahb
;
1334 content
= s
->cd
->content
;
1335 content_len
= s
->cd
->content_len
;
1337 for (; tcdup
!= struct_offset
; tcdup
++) {
1338 if (tcdup
->content_len
!= content_len
||
1339 SCMemcmp(tcdup
->content
, content
, tcdup
->content_len
) != 0)
1346 if (tcdup
!= struct_offset
) {
1347 s
->cd
->id
= tcdup
->id
;
1351 struct_offset
->content_len
= content_len
;
1352 struct_offset
->content
= content_offset
;
1353 content_offset
+= content_len
;
1354 memcpy(struct_offset
->content
, content
, content_len
);
1355 struct_offset
->id
= max_id
++;
1356 s
->cd
->id
= struct_offset
->id
;
1361 ctx
->max_pat_id
= max_id
;
1372 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx
*ctx
)
1377 AppLayerProtoDetectPMSignature
*s
, *next_s
;
1381 ctx
->map
= SCMalloc(ctx
->max_sig_id
* sizeof(AppLayerProtoDetectPMSignature
*));
1382 if (ctx
->map
== NULL
)
1384 memset(ctx
->map
, 0, ctx
->max_sig_id
* sizeof(AppLayerProtoDetectPMSignature
*));
1386 /* add an array indexed by rule id to look up the sig */
1387 for (s
= ctx
->head
; s
!= NULL
; ) {
1390 SCLogDebug("s->id %u offset %u depth %u",
1391 s
->id
, s
->cd
->offset
, s
->cd
->depth
);
1393 if (s
->cd
->flags
& DETECT_CONTENT_NOCASE
) {
1394 mpm_ret
= MpmAddPatternCI(&ctx
->mpm_ctx
,
1395 s
->cd
->content
, s
->cd
->content_len
,
1396 s
->cd
->offset
, s
->cd
->depth
, s
->cd
->id
, s
->id
, 0);
1400 mpm_ret
= MpmAddPatternCS(&ctx
->mpm_ctx
,
1401 s
->cd
->content
, s
->cd
->content_len
,
1402 s
->cd
->offset
, s
->cd
->depth
, s
->cd
->id
, s
->id
, 0);
1407 ctx
->map
[s
->id
] = s
;
1420 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx
*ctx
)
1425 MpmCtx
*mpm_ctx
= &ctx
->mpm_ctx
;
1427 if (mpm_table
[mpm_ctx
->mpm_type
].Prepare(mpm_ctx
) < 0)
1437 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature
*sig
)
1443 DetectContentFree(NULL
, sig
->cd
);
1448 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx
*ctx
, DetectContentData
*cd
,
1449 AppProto alproto
, uint8_t direction
,
1450 ProbingParserFPtr PPFunc
,
1451 uint16_t pp_min_depth
, uint16_t pp_max_depth
)
1455 AppLayerProtoDetectPMSignature
*s
= SCCalloc(1, sizeof(*s
));
1456 if (unlikely(s
== NULL
))
1459 s
->alproto
= alproto
;
1460 s
->direction
= direction
;
1463 s
->pp_min_depth
= pp_min_depth
;
1464 s
->pp_max_depth
= pp_max_depth
;
1466 /* prepend to the list */
1467 s
->next
= ctx
->head
;
1473 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto
, AppProto alproto
,
1474 const char *pattern
,
1475 uint16_t depth
, uint16_t offset
,
1478 ProbingParserFPtr PPFunc
,
1479 uint16_t pp_min_depth
, uint16_t pp_max_depth
)
1483 AppLayerProtoDetectCtxIpproto
*ctx_ipp
= &alpd_ctx
.ctx_ipp
[FlowGetProtoMapping(ipproto
)];
1484 AppLayerProtoDetectPMCtx
*ctx_pm
= NULL
;
1487 DetectContentData
*cd
= DetectContentParseEncloseQuotes(
1488 alpd_ctx
.spm_global_thread_ctx
, pattern
);
1492 cd
->offset
= offset
;
1494 /* Rebuild as nocase */
1495 SpmDestroyCtx(cd
->spm_ctx
);
1496 cd
->spm_ctx
= SpmInitCtx(cd
->content
, cd
->content_len
, 1,
1497 alpd_ctx
.spm_global_thread_ctx
);
1498 if (cd
->spm_ctx
== NULL
) {
1501 cd
->flags
|= DETECT_CONTENT_NOCASE
;
1503 if (depth
< cd
->content_len
)
1506 if (direction
& STREAM_TOSERVER
)
1507 ctx_pm
= (AppLayerProtoDetectPMCtx
*)&ctx_ipp
->ctx_pm
[0];
1509 ctx_pm
= (AppLayerProtoDetectPMCtx
*)&ctx_ipp
->ctx_pm
[1];
1511 if (pp_max_depth
> ctx_pm
->pp_max_len
)
1512 ctx_pm
->pp_max_len
= pp_max_depth
;
1513 if (depth
< ctx_pm
->min_len
)
1514 ctx_pm
->min_len
= depth
;
1516 /* Finally turn it into a signature and add to the ctx. */
1517 AppLayerProtoDetectPMAddSignature(ctx_pm
, cd
, alproto
, direction
,
1518 PPFunc
, pp_min_depth
, pp_max_depth
);
1522 DetectContentFree(NULL
, cd
);
1528 /***** Protocol Retrieval *****/
1530 AppProto
AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx
*tctx
, Flow
*f
,
1531 const uint8_t *buf
, uint32_t buflen
, uint8_t ipproto
, uint8_t flags
, bool *reverse_flow
)
1534 SCLogDebug("buflen %u for %s direction", buflen
,
1535 (flags
& STREAM_TOSERVER
) ? "toserver" : "toclient");
1537 AppProto alproto
= ALPROTO_UNKNOWN
;
1538 AppProto pm_alproto
= ALPROTO_UNKNOWN
;
1540 if (!FLOW_IS_PM_DONE(f
, flags
)) {
1541 AppProto pm_results
[ALPROTO_MAX
];
1542 uint16_t pm_matches
= AppLayerProtoDetectPMGetProto(
1543 tctx
, f
, buf
, buflen
, flags
, pm_results
, reverse_flow
);
1544 if (pm_matches
> 0) {
1545 DEBUG_VALIDATE_BUG_ON(pm_matches
> 1);
1546 alproto
= pm_results
[0];
1548 // rerun probing parser for other direction if it is unknown
1549 uint8_t reverse_dir
= (flags
& STREAM_TOSERVER
) ? STREAM_TOCLIENT
: STREAM_TOSERVER
;
1550 if (FLOW_IS_PP_DONE(f
, reverse_dir
)) {
1551 AppProto rev_alproto
= (flags
& STREAM_TOSERVER
) ? f
->alproto_tc
: f
->alproto_ts
;
1552 if (rev_alproto
== ALPROTO_UNKNOWN
) {
1553 FLOW_RESET_PP_DONE(f
, reverse_dir
);
1557 /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1558 * to avoid misdetecting DNS as DCERPC. */
1559 if (!(ipproto
== IPPROTO_UDP
&& alproto
== ALPROTO_DCERPC
))
1562 pm_alproto
= alproto
;
1568 if (!FLOW_IS_PP_DONE(f
, flags
)) {
1570 alproto
= AppLayerProtoDetectPPGetProto(f
, buf
, buflen
, ipproto
, flags
, &rflow
);
1571 if (AppProtoIsValid(alproto
)) {
1573 *reverse_flow
= true;
1579 /* Look if flow can be found in expectation list */
1580 if (!FLOW_IS_PE_DONE(f
, flags
)) {
1581 alproto
= AppLayerProtoDetectPEGetProto(f
, ipproto
, flags
);
1585 if (!AppProtoIsValid(alproto
))
1586 alproto
= pm_alproto
;
1588 SCReturnUInt(alproto
);
1591 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser
*pp
)
1595 AppLayerProtoDetectProbingParser
*tmp_pp
= NULL
;
1600 while (pp
!= NULL
) {
1602 AppLayerProtoDetectProbingParserFree(pp
);
1610 static void AppLayerProtoDetectFreeAliases(void)
1614 AppLayerProtoDetectAliases
*cur_alias
= alpda_ctx
;
1615 if (cur_alias
== NULL
)
1618 AppLayerProtoDetectAliases
*next_alias
= NULL
;
1619 while (cur_alias
!= NULL
) {
1620 next_alias
= cur_alias
->next
;
1622 cur_alias
= next_alias
;
1631 /***** State Preparation *****/
1633 int AppLayerProtoDetectPrepareState(void)
1637 AppLayerProtoDetectPMCtx
*ctx_pm
;
1641 for (i
= 0; i
< FLOW_PROTO_DEFAULT
; i
++) {
1642 for (j
= 0; j
< 2; j
++) {
1643 ctx_pm
= &alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
];
1645 if (AppLayerProtoDetectPMSetContentIDs(ctx_pm
) < 0)
1648 if (ctx_pm
->max_sig_id
== 0)
1651 if (AppLayerProtoDetectPMMapSignatures(ctx_pm
) < 0)
1653 if (AppLayerProtoDetectPMPrepareMpm(ctx_pm
) < 0)
1659 if (SCLogDebugEnabled()) {
1660 AppLayerProtoDetectPrintProbingParsers(alpd_ctx
.ctx_pp
);
1671 /***** PP registration *****/
1673 /** \brief register parser at a port
1675 * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1677 void AppLayerProtoDetectPPRegister(uint8_t ipproto
,
1678 const char *portstr
,
1680 uint16_t min_depth
, uint16_t max_depth
,
1682 ProbingParserFPtr ProbingParser1
,
1683 ProbingParserFPtr ProbingParser2
)
1687 DetectPort
*head
= NULL
;
1688 DetectPortParse(NULL
,&head
, portstr
);
1689 DetectPort
*temp_dp
= head
;
1690 while (temp_dp
!= NULL
) {
1691 uint16_t port
= temp_dp
->port
;
1692 if (port
== 0 && temp_dp
->port2
!= 0)
1694 for ( ; port
<= temp_dp
->port2
; port
++) {
1695 AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx
.ctx_pp
,
1699 min_depth
, max_depth
,
1704 temp_dp
= temp_dp
->next
;
1706 DetectPortCleanupList(NULL
,head
);
1711 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name
,
1713 const char *alproto_name
,
1715 uint16_t min_depth
, uint16_t max_depth
,
1716 ProbingParserFPtr ProbingParserTs
,
1717 ProbingParserFPtr ProbingParserTc
)
1724 ConfNode
*port_node
= NULL
;
1727 r
= snprintf(param
, sizeof(param
), "%s%s%s", "app-layer.protocols.",
1728 alproto_name
, ".detection-ports");
1730 FatalError(SC_ERR_FATAL
, "snprintf failure.");
1731 } else if (r
> (int)sizeof(param
)) {
1732 FatalError(SC_ERR_FATAL
, "buffer not big enough to write param.");
1734 node
= ConfGetNode(param
);
1736 SCLogDebug("Entry for %s not found.", param
);
1737 r
= snprintf(param
, sizeof(param
), "%s%s%s%s%s", "app-layer.protocols.",
1738 alproto_name
, ".", ipproto_name
, ".detection-ports");
1740 FatalError(SC_ERR_FATAL
, "snprintf failure.");
1741 } else if (r
> (int)sizeof(param
)) {
1742 FatalError(SC_ERR_FATAL
, "buffer not big enough to write param.");
1744 node
= ConfGetNode(param
);
1749 /* detect by destination port of the flow (e.g. port 53 for DNS) */
1750 port_node
= ConfNodeLookupChild(node
, "dp");
1751 if (port_node
== NULL
)
1752 port_node
= ConfNodeLookupChild(node
, "toserver");
1754 if (port_node
!= NULL
&& port_node
->val
!= NULL
) {
1755 AppLayerProtoDetectPPRegister(ipproto
,
1758 min_depth
, max_depth
,
1759 STREAM_TOSERVER
, /* to indicate dp */
1760 ProbingParserTs
, ProbingParserTc
);
1763 /* detect by source port of flow */
1764 port_node
= ConfNodeLookupChild(node
, "sp");
1765 if (port_node
== NULL
)
1766 port_node
= ConfNodeLookupChild(node
, "toclient");
1768 if (port_node
!= NULL
&& port_node
->val
!= NULL
) {
1769 AppLayerProtoDetectPPRegister(ipproto
,
1772 min_depth
, max_depth
,
1773 STREAM_TOCLIENT
, /* to indicate sp */
1774 ProbingParserTc
, ProbingParserTs
);
1780 SCReturnInt(config
);
1783 /***** PM registration *****/
1785 int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto
, AppProto alproto
,
1786 const char *pattern
,
1787 uint16_t depth
, uint16_t offset
,
1791 int r
= AppLayerProtoDetectPMRegisterPattern(ipproto
, alproto
,
1792 pattern
, depth
, offset
,
1793 direction
, 1 /* case-sensitive */,
1798 int AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto
, AppProto alproto
,
1799 const char *pattern
, uint16_t depth
, uint16_t offset
,
1801 ProbingParserFPtr PPFunc
,
1802 uint16_t pp_min_depth
, uint16_t pp_max_depth
)
1805 int r
= AppLayerProtoDetectPMRegisterPattern(ipproto
, alproto
,
1806 pattern
, depth
, offset
,
1807 direction
, 1 /* case-sensitive */,
1808 PPFunc
, pp_min_depth
, pp_max_depth
);
1812 int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto
, AppProto alproto
,
1813 const char *pattern
,
1814 uint16_t depth
, uint16_t offset
,
1818 int r
= AppLayerProtoDetectPMRegisterPattern(ipproto
, alproto
,
1819 pattern
, depth
, offset
,
1820 direction
, 0 /* !case-sensitive */,
1825 /***** Setup/General Registration *****/
1827 int AppLayerProtoDetectSetup(void)
1833 memset(&alpd_ctx
, 0, sizeof(alpd_ctx
));
1835 uint16_t spm_matcher
= SinglePatternMatchDefaultMatcher();
1836 uint16_t mpm_matcher
= PatternMatchDefaultMatcher();
1838 alpd_ctx
.spm_global_thread_ctx
= SpmInitGlobalThreadCtx(spm_matcher
);
1839 if (alpd_ctx
.spm_global_thread_ctx
== NULL
) {
1840 FatalError(SC_ERR_FATAL
, "Unable to alloc SpmGlobalThreadCtx.");
1843 for (i
= 0; i
< FLOW_PROTO_DEFAULT
; i
++) {
1844 for (j
= 0; j
< 2; j
++) {
1845 MpmInitCtx(&alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].mpm_ctx
, mpm_matcher
);
1849 AppLayerExpectationSetup();
1855 * \todo incomplete. Need more work.
1857 int AppLayerProtoDetectDeSetup(void)
1861 int ipproto_map
= 0;
1864 AppLayerProtoDetectPMCtx
*pm_ctx
= NULL
;
1865 AppLayerProtoDetectPMSignature
*sig
= NULL
;
1867 for (ipproto_map
= 0; ipproto_map
< FLOW_PROTO_DEFAULT
; ipproto_map
++) {
1868 for (dir
= 0; dir
< 2; dir
++) {
1869 pm_ctx
= &alpd_ctx
.ctx_ipp
[ipproto_map
].ctx_pm
[dir
];
1870 mpm_table
[pm_ctx
->mpm_ctx
.mpm_type
].DestroyCtx(&pm_ctx
->mpm_ctx
);
1871 for (id
= 0; id
< pm_ctx
->max_sig_id
; id
++) {
1872 sig
= pm_ctx
->map
[id
];
1873 AppLayerProtoDetectPMFreeSignature(sig
);
1875 SCFree(pm_ctx
->map
);
1880 SpmDestroyGlobalThreadCtx(alpd_ctx
.spm_global_thread_ctx
);
1882 AppLayerProtoDetectFreeAliases();
1884 AppLayerProtoDetectFreeProbingParsers(alpd_ctx
.ctx_pp
);
1889 void AppLayerProtoDetectRegisterProtocol(AppProto alproto
, const char *alproto_name
)
1893 if (alpd_ctx
.alproto_names
[alproto
] == NULL
)
1894 alpd_ctx
.alproto_names
[alproto
] = alproto_name
;
1899 void AppLayerProtoDetectRegisterAlias(const char *proto_name
, const char *proto_alias
)
1903 AppLayerProtoDetectAliases
*new_alias
= SCMalloc(sizeof(AppLayerProtoDetectAliases
));
1904 if (unlikely(new_alias
== NULL
)) {
1908 new_alias
->proto_name
= proto_name
;
1909 new_alias
->proto_alias
= proto_alias
;
1910 new_alias
->next
= NULL
;
1912 if (alpda_ctx
== NULL
) {
1913 alpda_ctx
= new_alias
;
1915 AppLayerProtoDetectAliases
*cur_alias
= alpda_ctx
;
1916 while (cur_alias
->next
!= NULL
) {
1917 cur_alias
= cur_alias
->next
;
1919 cur_alias
->next
= new_alias
;
1925 /** \brief request applayer to wrap up this protocol and rerun protocol
1928 * When this is called, the old session is reset unconditionally. A
1929 * 'detect/log' flush packet is generated for both direction before
1930 * the reset, so allow for final detection and logging.
1932 * \param f flow to act on
1933 * \param dp destination port to use in protocol detection. Set to 443
1934 * for start tls, set to the HTTP uri port for CONNECT and
1935 * set to 0 to not use it.
1936 * \param expect_proto expected protocol. AppLayer event will be set if
1937 * detected protocol differs from this.
1939 void AppLayerRequestProtocolChange(Flow
*f
, uint16_t dp
, AppProto expect_proto
)
1941 FlowSetChangeProtoFlag(f
);
1942 f
->protodetect_dp
= dp
;
1943 f
->alproto_expect
= expect_proto
;
1944 DEBUG_VALIDATE_BUG_ON(f
->alproto
== ALPROTO_UNKNOWN
);
1945 f
->alproto_orig
= f
->alproto
;
1946 // If one side is unknown yet, set it to the other known side
1947 if (f
->alproto_ts
== ALPROTO_UNKNOWN
) {
1948 f
->alproto_ts
= f
->alproto
;
1950 if (f
->alproto_tc
== ALPROTO_UNKNOWN
) {
1951 f
->alproto_tc
= f
->alproto
;
1955 /** \brief request applayer to wrap up this protocol and rerun protocol
1956 * detection with expectation of TLS. Used by STARTTLS.
1958 * Sets detection port to 443 to make port based TLS detection work for
1959 * SMTP, FTP etc as well.
1961 * \param f flow to act on
1963 void AppLayerRequestProtocolTLSUpgrade(Flow
*f
)
1965 AppLayerRequestProtocolChange(f
, 443, ALPROTO_TLS
);
1968 void AppLayerProtoDetectReset(Flow
*f
)
1970 FLOW_RESET_PM_DONE(f
, STREAM_TOSERVER
);
1971 FLOW_RESET_PM_DONE(f
, STREAM_TOCLIENT
);
1972 FLOW_RESET_PP_DONE(f
, STREAM_TOSERVER
);
1973 FLOW_RESET_PP_DONE(f
, STREAM_TOCLIENT
);
1974 FLOW_RESET_PE_DONE(f
, STREAM_TOSERVER
);
1975 FLOW_RESET_PE_DONE(f
, STREAM_TOCLIENT
);
1976 f
->probing_parser_toserver_alproto_masks
= 0;
1977 f
->probing_parser_toclient_alproto_masks
= 0;
1979 // Does not free the structures for the parser
1980 // keeps f->alstate for new state creation
1982 f
->alproto
= ALPROTO_UNKNOWN
;
1983 f
->alproto_ts
= ALPROTO_UNKNOWN
;
1984 f
->alproto_tc
= ALPROTO_UNKNOWN
;
1987 int AppLayerProtoDetectConfProtoDetectionEnabledDefault(
1988 const char *ipproto
, const char *alproto
, bool default_enabled
)
1992 BUG_ON(ipproto
== NULL
|| alproto
== NULL
);
1999 if (RunmodeIsUnittests())
2002 r
= snprintf(param
, sizeof(param
), "%s%s%s", "app-layer.protocols.",
2003 alproto
, ".enabled");
2005 FatalError(SC_ERR_FATAL
, "snprintf failure.");
2006 } else if (r
> (int)sizeof(param
)) {
2007 FatalError(SC_ERR_FATAL
, "buffer not big enough to write param.");
2010 node
= ConfGetNode(param
);
2012 SCLogDebug("Entry for %s not found.", param
);
2013 r
= snprintf(param
, sizeof(param
), "%s%s%s%s%s", "app-layer.protocols.",
2014 alproto
, ".", ipproto
, ".enabled");
2016 FatalError(SC_ERR_FATAL
, "snprintf failure.");
2017 } else if (r
> (int)sizeof(param
)) {
2018 FatalError(SC_ERR_FATAL
, "buffer not big enough to write param.");
2021 node
= ConfGetNode(param
);
2023 SCLogDebug("Entry for %s not found.", param
);
2024 if (default_enabled
) {
2033 if (ConfValIsTrue(node
->val
)) {
2035 } else if (ConfValIsFalse(node
->val
)) {
2037 } else if (strcasecmp(node
->val
, "detection-only") == 0) {
2042 /* Invalid or null value. */
2043 SCLogError(SC_ERR_FATAL
, "Invalid value found for %s.", param
);
2049 SCReturnInt(enabled
);
2052 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto
, const char *alproto
)
2054 return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto
, alproto
, true);
2057 AppLayerProtoDetectThreadCtx
*AppLayerProtoDetectGetCtxThread(void)
2061 AppLayerProtoDetectThreadCtx
*alpd_tctx
= NULL
;
2063 MpmThreadCtx
*mpm_tctx
;
2065 PatIntId max_pat_id
= 0;
2067 for (i
= 0; i
< FLOW_PROTO_DEFAULT
; i
++) {
2068 for (j
= 0; j
< 2; j
++) {
2069 if (max_pat_id
== 0) {
2070 max_pat_id
= alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].max_pat_id
;
2072 } else if (alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].max_pat_id
&&
2073 max_pat_id
< alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].max_pat_id
)
2075 max_pat_id
= alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].max_pat_id
;
2080 alpd_tctx
= SCMalloc(sizeof(*alpd_tctx
));
2081 if (alpd_tctx
== NULL
)
2083 memset(alpd_tctx
, 0, sizeof(*alpd_tctx
));
2085 /* Get the max pat id for all the mpm ctxs. */
2086 if (PmqSetup(&alpd_tctx
->pmq
) < 0)
2089 for (i
= 0; i
< FLOW_PROTO_DEFAULT
; i
++) {
2090 for (j
= 0; j
< 2; j
++) {
2091 mpm_ctx
= &alpd_ctx
.ctx_ipp
[i
].ctx_pm
[j
].mpm_ctx
;
2092 mpm_tctx
= &alpd_tctx
->mpm_tctx
[i
][j
];
2093 mpm_table
[mpm_ctx
->mpm_type
].InitThreadCtx(mpm_ctx
, mpm_tctx
);
2097 alpd_tctx
->spm_thread_ctx
= SpmMakeThreadCtx(alpd_ctx
.spm_global_thread_ctx
);
2098 if (alpd_tctx
->spm_thread_ctx
== NULL
) {
2104 if (alpd_tctx
!= NULL
)
2105 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2108 SCReturnPtr(alpd_tctx
, "AppLayerProtoDetectThreadCtx");
2111 void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx
*alpd_tctx
)
2116 MpmThreadCtx
*mpm_tctx
;
2117 int ipproto_map
, dir
;
2119 for (ipproto_map
= 0; ipproto_map
< FLOW_PROTO_DEFAULT
; ipproto_map
++) {
2120 for (dir
= 0; dir
< 2; dir
++) {
2121 mpm_ctx
= &alpd_ctx
.ctx_ipp
[ipproto_map
].ctx_pm
[dir
].mpm_ctx
;
2122 mpm_tctx
= &alpd_tctx
->mpm_tctx
[ipproto_map
][dir
];
2123 mpm_table
[mpm_ctx
->mpm_type
].DestroyThreadCtx(mpm_ctx
, mpm_tctx
);
2126 PmqFree(&alpd_tctx
->pmq
);
2127 if (alpd_tctx
->spm_thread_ctx
!= NULL
) {
2128 SpmDestroyThreadCtx(alpd_tctx
->spm_thread_ctx
);
2135 /***** Utility *****/
2137 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto
, uint8_t *ipprotos
)
2141 // Custom case for only signature-only protocol so far
2142 if (alproto
== ALPROTO_HTTP
) {
2143 AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP1
, ipprotos
);
2144 AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP2
, ipprotos
);
2146 AppLayerProtoDetectPMGetIpprotos(alproto
, ipprotos
);
2147 AppLayerProtoDetectPPGetIpprotos(alproto
, ipprotos
);
2148 AppLayerProtoDetectPEGetIpprotos(alproto
, ipprotos
);
2154 AppProto
AppLayerProtoDetectGetProtoByName(const char *alproto_name
)
2158 AppLayerProtoDetectAliases
*cur_alias
= alpda_ctx
;
2159 while (cur_alias
!= NULL
) {
2160 if (strcasecmp(alproto_name
, cur_alias
->proto_alias
) == 0) {
2161 alproto_name
= cur_alias
->proto_name
;
2164 cur_alias
= cur_alias
->next
;
2168 AppProto b
= StringToAppProto(alproto_name
);
2169 for (a
= 0; a
< ALPROTO_MAX
; a
++) {
2170 if (alpd_ctx
.alproto_names
[a
] != NULL
&& AppProtoEquals(b
, a
)) {
2171 // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2172 SCReturnCT(b
, "AppProto");
2176 SCReturnCT(ALPROTO_UNKNOWN
, "AppProto");
2179 const char *AppLayerProtoDetectGetProtoName(AppProto alproto
)
2181 return alpd_ctx
.alproto_names
[alproto
];
2184 void AppLayerProtoDetectSupportedAppProtocols(AppProto
*alprotos
)
2188 memset(alprotos
, 0, ALPROTO_MAX
* sizeof(AppProto
));
2192 for (alproto
= 0; alproto
!= ALPROTO_MAX
; alproto
++) {
2193 if (alpd_ctx
.alproto_names
[alproto
] != NULL
)
2194 alprotos
[alproto
] = 1;
2200 uint8_t expectation_proto
[ALPROTO_MAX
];
2202 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto
,
2205 if (expectation_proto
[alproto
] == IPPROTO_TCP
) {
2206 ipprotos
[IPPROTO_TCP
/ 8] |= 1 << (IPPROTO_TCP
% 8);
2208 if (expectation_proto
[alproto
] == IPPROTO_UDP
) {
2209 ipprotos
[IPPROTO_UDP
/ 8] |= 1 << (IPPROTO_UDP
% 8);
2213 void AppLayerRegisterExpectationProto(uint8_t proto
, AppProto alproto
)
2215 if (expectation_proto
[alproto
]) {
2216 if (proto
!= expectation_proto
[alproto
]) {
2217 SCLogError(SC_ERR_NOT_SUPPORTED
,
2218 "Expectation on 2 IP protocols are not supported");
2221 expectation_proto
[alproto
] = proto
;
2224 /***** Unittests *****/
2228 #include "app-layer-htp.h"
2230 static AppLayerProtoDetectCtx alpd_ctx_ut
;
2232 void AppLayerProtoDetectUnittestCtxBackup(void)
2235 alpd_ctx_ut
= alpd_ctx
;
2236 memset(&alpd_ctx
, 0, sizeof(alpd_ctx
));
2240 void AppLayerProtoDetectUnittestCtxRestore(void)
2243 alpd_ctx
= alpd_ctx_ut
;
2244 memset(&alpd_ctx_ut
, 0, sizeof(alpd_ctx_ut
));
2248 static int AppLayerProtoDetectTest01(void)
2250 AppLayerProtoDetectUnittestCtxBackup();
2251 AppLayerProtoDetectSetup();
2253 const char *buf
= "HTTP";
2254 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2256 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOSERVER
);
2258 AppLayerProtoDetectPrepareState();
2259 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 1);
2260 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2262 AppLayerProtoDetectDeSetup();
2263 AppLayerProtoDetectUnittestCtxRestore();
2267 static int AppLayerProtoDetectTest02(void)
2269 AppLayerProtoDetectUnittestCtxBackup();
2270 AppLayerProtoDetectSetup();
2272 const char *buf
= "HTTP";
2273 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2275 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_FTP
, buf
, 4, 0, STREAM_TOCLIENT
);
2277 AppLayerProtoDetectPrepareState();
2278 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2279 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 2);
2281 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2282 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2284 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_FTP
);
2285 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[1]->alproto
!= ALPROTO_HTTP1
);
2287 AppLayerProtoDetectDeSetup();
2288 AppLayerProtoDetectUnittestCtxRestore();
2292 static int AppLayerProtoDetectTest03(void)
2294 AppLayerProtoDetectUnittestCtxBackup();
2295 AppLayerProtoDetectSetup();
2297 uint8_t l7data
[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2298 AppProto pm_results
[ALPROTO_MAX
];
2299 memset(pm_results
, 0, sizeof(pm_results
));
2301 memset(&f
, 0x00, sizeof(f
));
2302 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2305 const char *buf
= "HTTP";
2306 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2308 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_FTP
, buf
, 4, 0, STREAM_TOCLIENT
);
2310 AppLayerProtoDetectPrepareState();
2311 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2312 * it sets internal structures which depends on the above function. */
2313 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2314 FAIL_IF_NULL(alpd_tctx
);
2316 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2317 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 2);
2318 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2319 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2320 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_FTP
);
2321 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[1]->alproto
!= ALPROTO_HTTP1
);
2324 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2325 &f
, l7data
, sizeof(l7data
),
2327 pm_results
, &rflow
);
2329 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2331 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2332 AppLayerProtoDetectDeSetup();
2333 AppLayerProtoDetectUnittestCtxRestore();
2337 static int AppLayerProtoDetectTest04(void)
2339 AppLayerProtoDetectUnittestCtxBackup();
2340 AppLayerProtoDetectSetup();
2342 uint8_t l7data
[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2344 memset(&f
, 0x00, sizeof(f
));
2345 AppProto pm_results
[ALPROTO_MAX
];
2346 memset(pm_results
, 0, sizeof(pm_results
));
2347 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2349 const char *buf
= "200 ";
2350 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 13, 0, STREAM_TOCLIENT
);
2352 AppLayerProtoDetectPrepareState();
2353 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2354 * it sets internal structures which depends on the above function. */
2355 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2356 FAIL_IF_NULL(alpd_tctx
);
2358 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2359 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2360 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2361 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2362 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_HTTP1
);
2365 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2366 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2369 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2371 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2372 AppLayerProtoDetectDeSetup();
2373 AppLayerProtoDetectUnittestCtxRestore();
2377 static int AppLayerProtoDetectTest05(void)
2379 AppLayerProtoDetectUnittestCtxBackup();
2380 AppLayerProtoDetectSetup();
2382 uint8_t l7data
[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2383 AppProto pm_results
[ALPROTO_MAX
];
2384 memset(pm_results
, 0, sizeof(pm_results
));
2386 memset(&f
, 0x00, sizeof(f
));
2387 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2389 const char *buf
= "HTTP";
2390 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2392 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_FTP
, buf
, 4, 0, STREAM_TOCLIENT
);
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 FAIL_IF_NULL(alpd_tctx
);
2400 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2401 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 2);
2402 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2403 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2404 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_FTP
);
2405 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[1]->alproto
!= ALPROTO_HTTP1
);
2408 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2409 &f
, l7data
, sizeof(l7data
),
2413 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2415 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2416 AppLayerProtoDetectDeSetup();
2417 AppLayerProtoDetectUnittestCtxRestore();
2421 static int AppLayerProtoDetectTest06(void)
2423 AppLayerProtoDetectUnittestCtxBackup();
2424 AppLayerProtoDetectSetup();
2426 uint8_t l7data
[] = "220 Welcome to the OISF FTP server\r\n";
2427 AppProto pm_results
[ALPROTO_MAX
];
2428 memset(pm_results
, 0, sizeof(pm_results
));
2430 memset(&f
, 0x00, sizeof(f
));
2431 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2433 const char *buf
= "HTTP";
2434 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2436 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_FTP
, buf
, 4, 0, STREAM_TOCLIENT
);
2438 AppLayerProtoDetectPrepareState();
2439 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2440 * it sets internal structures which depends on the above function. */
2441 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2442 FAIL_IF_NULL(alpd_tctx
);
2444 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2445 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 2);
2446 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2447 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2448 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_FTP
);
2449 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[1]->alproto
!= ALPROTO_HTTP1
);
2452 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2453 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2456 FAIL_IF(pm_results
[0] != ALPROTO_FTP
);
2458 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2459 AppLayerProtoDetectDeSetup();
2460 AppLayerProtoDetectUnittestCtxRestore();
2464 static int AppLayerProtoDetectTest07(void)
2466 AppLayerProtoDetectUnittestCtxBackup();
2467 AppLayerProtoDetectSetup();
2469 uint8_t l7data
[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2471 memset(&f
, 0x00, sizeof(f
));
2472 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2473 AppProto pm_results
[ALPROTO_MAX
];
2474 memset(pm_results
, 0, sizeof(pm_results
));
2476 const char *buf
= "HTTP";
2477 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_HTTP1
, buf
, 4, 0, STREAM_TOCLIENT
);
2479 AppLayerProtoDetectPrepareState();
2480 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2481 * it sets internal structures which depends on the above function. */
2482 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2484 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2485 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2486 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2487 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2488 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_HTTP1
);
2491 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2492 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2496 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2497 AppLayerProtoDetectDeSetup();
2498 AppLayerProtoDetectUnittestCtxRestore();
2502 static int AppLayerProtoDetectTest08(void)
2504 AppLayerProtoDetectUnittestCtxBackup();
2505 AppLayerProtoDetectSetup();
2507 uint8_t l7data
[] = {
2508 0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2509 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2512 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2513 0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2514 0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2515 0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2516 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2517 0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2518 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2519 0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2520 0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2521 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2522 0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2523 0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2524 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2527 AppProto pm_results
[ALPROTO_MAX
];
2528 memset(pm_results
, 0, sizeof(pm_results
));
2530 memset(&f
, 0x00, sizeof(f
));
2531 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2533 const char *buf
= "|ff|SMB";
2534 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_SMB
, buf
, 8, 4, STREAM_TOCLIENT
);
2536 AppLayerProtoDetectPrepareState();
2537 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2538 * it sets internal structures which depends on the above function. */
2539 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2540 FAIL_IF_NULL(alpd_tctx
);
2542 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2543 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2544 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2545 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2546 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_SMB
);
2549 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2550 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2553 FAIL_IF(pm_results
[0] != ALPROTO_SMB
);
2555 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2556 AppLayerProtoDetectDeSetup();
2557 AppLayerProtoDetectUnittestCtxRestore();
2561 static int AppLayerProtoDetectTest09(void)
2563 AppLayerProtoDetectUnittestCtxBackup();
2564 AppLayerProtoDetectSetup();
2566 uint8_t l7data
[] = {
2567 0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2568 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2569 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2575 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2582 AppProto pm_results
[ALPROTO_MAX
];
2583 memset(pm_results
, 0, sizeof(pm_results
));
2585 memset(&f
, 0x00, sizeof(f
));
2586 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2588 const char *buf
= "|fe|SMB";
2589 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_SMB
, buf
, 8, 4, STREAM_TOCLIENT
);
2591 AppLayerProtoDetectPrepareState();
2592 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2593 * it sets internal structures which depends on the above function. */
2594 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2595 FAIL_IF_NULL(alpd_tctx
);
2597 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2598 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2599 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2600 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2601 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_SMB
);
2604 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2605 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2608 FAIL_IF(pm_results
[0] != ALPROTO_SMB
);
2610 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2611 AppLayerProtoDetectDeSetup();
2612 AppLayerProtoDetectUnittestCtxRestore();
2616 static int AppLayerProtoDetectTest10(void)
2618 AppLayerProtoDetectUnittestCtxBackup();
2619 AppLayerProtoDetectSetup();
2621 uint8_t l7data
[] = {
2622 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2623 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2624 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2625 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2626 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2627 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2628 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2629 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2630 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2632 AppProto pm_results
[ALPROTO_MAX
];
2633 memset(pm_results
, 0, sizeof(pm_results
));
2635 memset(&f
, 0x00, sizeof(f
));
2636 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2638 const char *buf
= "|05 00|";
2639 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP
, ALPROTO_DCERPC
, buf
, 4, 0, STREAM_TOCLIENT
);
2641 AppLayerProtoDetectPrepareState();
2642 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2643 * it sets internal structures which depends on the above function. */
2644 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2645 FAIL_IF_NULL(alpd_tctx
);
2647 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 0);
2648 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2649 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
);
2650 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2651 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_DCERPC
);
2654 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2655 &f
, l7data
, sizeof(l7data
), STREAM_TOCLIENT
,
2658 FAIL_IF(pm_results
[0] != ALPROTO_DCERPC
);
2660 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2661 AppLayerProtoDetectDeSetup();
2662 AppLayerProtoDetectUnittestCtxRestore();
2667 * \test Why we still get http for connect... obviously because
2668 * we also match on the reply, duh
2670 static int AppLayerProtoDetectTest11(void)
2672 AppLayerProtoDetectUnittestCtxBackup();
2673 AppLayerProtoDetectSetup();
2675 uint8_t l7data
[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2676 uint8_t l7data_resp
[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2677 AppProto pm_results
[ALPROTO_MAX
];
2678 memset(pm_results
, 0, sizeof(pm_results
));
2680 memset(&f
, 0x00, sizeof(f
));
2681 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2683 AppLayerProtoDetectPMRegisterPatternCS(
2684 IPPROTO_TCP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOSERVER
);
2685 AppLayerProtoDetectPMRegisterPatternCS(
2686 IPPROTO_TCP
, ALPROTO_HTTP1
, "GET", 3, 0, STREAM_TOSERVER
);
2687 AppLayerProtoDetectPMRegisterPatternCS(
2688 IPPROTO_TCP
, ALPROTO_HTTP1
, "PUT", 3, 0, STREAM_TOSERVER
);
2689 AppLayerProtoDetectPMRegisterPatternCS(
2690 IPPROTO_TCP
, ALPROTO_HTTP1
, "POST", 4, 0, STREAM_TOSERVER
);
2691 AppLayerProtoDetectPMRegisterPatternCS(
2692 IPPROTO_TCP
, ALPROTO_HTTP1
, "TRACE", 5, 0, STREAM_TOSERVER
);
2693 AppLayerProtoDetectPMRegisterPatternCS(
2694 IPPROTO_TCP
, ALPROTO_HTTP1
, "OPTIONS", 7, 0, STREAM_TOSERVER
);
2695 AppLayerProtoDetectPMRegisterPatternCS(
2696 IPPROTO_TCP
, ALPROTO_HTTP1
, "CONNECT", 7, 0, STREAM_TOSERVER
);
2697 AppLayerProtoDetectPMRegisterPatternCS(
2698 IPPROTO_TCP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOCLIENT
);
2700 AppLayerProtoDetectPrepareState();
2701 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2702 * it sets internal structures which depends on the above function. */
2703 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2704 FAIL_IF_NULL(alpd_tctx
);
2706 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 7);
2707 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].max_pat_id
!= 1);
2708 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
== NULL
);
2709 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
== NULL
);
2711 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[0]->alproto
!= ALPROTO_HTTP1
);
2712 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[1]->alproto
!= ALPROTO_HTTP1
);
2713 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[2]->alproto
!= ALPROTO_HTTP1
);
2714 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[3]->alproto
!= ALPROTO_HTTP1
);
2715 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[4]->alproto
!= ALPROTO_HTTP1
);
2716 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[5]->alproto
!= ALPROTO_HTTP1
);
2717 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[6]->alproto
!= ALPROTO_HTTP1
);
2718 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_HTTP1
);
2721 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2722 &f
, l7data
, sizeof(l7data
), STREAM_TOSERVER
,
2725 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2727 memset(pm_results
, 0, sizeof(pm_results
));
2728 cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2729 &f
, l7data_resp
, sizeof(l7data_resp
), STREAM_TOCLIENT
,
2732 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2734 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2735 AppLayerProtoDetectDeSetup();
2736 AppLayerProtoDetectUnittestCtxRestore();
2741 * \test AlpProtoSignature test
2743 static int AppLayerProtoDetectTest12(void)
2745 AppLayerProtoDetectUnittestCtxBackup();
2746 AppLayerProtoDetectSetup();
2750 AppLayerProtoDetectPMRegisterPatternCS(
2751 IPPROTO_TCP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOSERVER
);
2752 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].head
== NULL
||
2753 alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
!= NULL
)
2755 printf("failure 1\n");
2759 AppLayerProtoDetectPrepareState();
2760 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].max_pat_id
!= 1) {
2761 printf("failure 2\n");
2764 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].head
!= NULL
||
2765 alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
== NULL
)
2767 printf("failure 3\n");
2770 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[0]->alproto
!= ALPROTO_HTTP1
) {
2771 printf("failure 4\n");
2774 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[0]->cd
->id
!= 0) {
2775 printf("failure 5\n");
2778 if (alpd_ctx
.ctx_ipp
[FLOW_PROTO_TCP
].ctx_pm
[0].map
[0]->next
!= NULL
) {
2779 printf("failure 6\n");
2786 AppLayerProtoDetectDeSetup();
2787 AppLayerProtoDetectUnittestCtxRestore();
2792 * \test What about if we add some sigs only for udp but call for tcp?
2793 * It should not detect any proto
2795 static int AppLayerProtoDetectTest13(void)
2797 AppLayerProtoDetectUnittestCtxBackup();
2798 AppLayerProtoDetectSetup();
2800 uint8_t l7data
[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2801 uint8_t l7data_resp
[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2802 AppProto pm_results
[ALPROTO_MAX
];
2805 memset(&f
, 0x00, sizeof(f
));
2806 f
.protomap
= FlowGetProtoMapping(IPPROTO_TCP
);
2808 AppLayerProtoDetectPMRegisterPatternCS(
2809 IPPROTO_UDP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOSERVER
);
2810 AppLayerProtoDetectPMRegisterPatternCS(
2811 IPPROTO_UDP
, ALPROTO_HTTP1
, "GET", 3, 0, STREAM_TOSERVER
);
2812 AppLayerProtoDetectPMRegisterPatternCS(
2813 IPPROTO_UDP
, ALPROTO_HTTP1
, "PUT", 3, 0, STREAM_TOSERVER
);
2814 AppLayerProtoDetectPMRegisterPatternCS(
2815 IPPROTO_UDP
, ALPROTO_HTTP1
, "POST", 4, 0, STREAM_TOSERVER
);
2816 AppLayerProtoDetectPMRegisterPatternCS(
2817 IPPROTO_UDP
, ALPROTO_HTTP1
, "TRACE", 5, 0, STREAM_TOSERVER
);
2818 AppLayerProtoDetectPMRegisterPatternCS(
2819 IPPROTO_UDP
, ALPROTO_HTTP1
, "OPTIONS", 7, 0, STREAM_TOSERVER
);
2820 AppLayerProtoDetectPMRegisterPatternCS(
2821 IPPROTO_UDP
, ALPROTO_HTTP1
, "CONNECT", 7, 0, STREAM_TOSERVER
);
2822 AppLayerProtoDetectPMRegisterPatternCS(
2823 IPPROTO_UDP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOCLIENT
);
2825 AppLayerProtoDetectPrepareState();
2826 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2827 * it sets internal structures which depends on the above function. */
2828 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2830 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].max_pat_id
!= 7);
2831 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[1].max_pat_id
!= 1);
2833 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[0]->alproto
!= ALPROTO_HTTP1
);
2834 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[1]->alproto
!= ALPROTO_HTTP1
);
2835 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[2]->alproto
!= ALPROTO_HTTP1
);
2836 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[3]->alproto
!= ALPROTO_HTTP1
);
2837 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[4]->alproto
!= ALPROTO_HTTP1
);
2838 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[5]->alproto
!= ALPROTO_HTTP1
);
2839 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[6]->alproto
!= ALPROTO_HTTP1
);
2840 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_HTTP1
);
2842 memset(pm_results
, 0, sizeof(pm_results
));
2844 uint32_t cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2845 &f
, l7data
, sizeof(l7data
), STREAM_TOSERVER
,
2849 memset(pm_results
, 0, sizeof(pm_results
));
2850 cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2851 &f
, l7data_resp
, sizeof(l7data_resp
), STREAM_TOCLIENT
,
2855 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2856 AppLayerProtoDetectDeSetup();
2857 AppLayerProtoDetectUnittestCtxRestore();
2862 * \test What about if we add some sigs only for udp calling it for UDP?
2863 * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2864 * to ensure that TCP/UDP differences work correctly.
2866 static int AppLayerProtoDetectTest14(void)
2868 AppLayerProtoDetectUnittestCtxBackup();
2869 AppLayerProtoDetectSetup();
2871 uint8_t l7data
[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2872 uint8_t l7data_resp
[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2873 AppProto pm_results
[ALPROTO_MAX
];
2876 memset(&f
, 0x00, sizeof(f
));
2877 f
.protomap
= FlowGetProtoMapping(IPPROTO_UDP
);
2879 AppLayerProtoDetectPMRegisterPatternCS(
2880 IPPROTO_UDP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOSERVER
);
2881 AppLayerProtoDetectPMRegisterPatternCS(
2882 IPPROTO_UDP
, ALPROTO_HTTP1
, "GET", 3, 0, STREAM_TOSERVER
);
2883 AppLayerProtoDetectPMRegisterPatternCS(
2884 IPPROTO_UDP
, ALPROTO_HTTP1
, "PUT", 3, 0, STREAM_TOSERVER
);
2885 AppLayerProtoDetectPMRegisterPatternCS(
2886 IPPROTO_UDP
, ALPROTO_HTTP1
, "POST", 4, 0, STREAM_TOSERVER
);
2887 AppLayerProtoDetectPMRegisterPatternCS(
2888 IPPROTO_UDP
, ALPROTO_HTTP1
, "TRACE", 5, 0, STREAM_TOSERVER
);
2889 AppLayerProtoDetectPMRegisterPatternCS(
2890 IPPROTO_UDP
, ALPROTO_HTTP1
, "OPTIONS", 7, 0, STREAM_TOSERVER
);
2891 AppLayerProtoDetectPMRegisterPatternCS(
2892 IPPROTO_UDP
, ALPROTO_HTTP1
, "CONNECT", 7, 0, STREAM_TOSERVER
);
2893 AppLayerProtoDetectPMRegisterPatternCS(
2894 IPPROTO_UDP
, ALPROTO_HTTP1
, "HTTP", 4, 0, STREAM_TOCLIENT
);
2896 AppLayerProtoDetectPrepareState();
2897 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2898 * it sets internal structures which depends on the above function. */
2899 AppLayerProtoDetectThreadCtx
*alpd_tctx
= AppLayerProtoDetectGetCtxThread();
2900 FAIL_IF_NULL(alpd_tctx
);
2902 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].max_pat_id
!= 7);
2903 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[1].max_pat_id
!= 1);
2905 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[0]->alproto
!= ALPROTO_HTTP1
);
2906 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[1]->alproto
!= ALPROTO_HTTP1
);
2907 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[2]->alproto
!= ALPROTO_HTTP1
);
2908 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[3]->alproto
!= ALPROTO_HTTP1
);
2909 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[4]->alproto
!= ALPROTO_HTTP1
);
2910 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[5]->alproto
!= ALPROTO_HTTP1
);
2911 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[0].map
[6]->alproto
!= ALPROTO_HTTP1
);
2912 FAIL_IF(alpd_ctx
.ctx_ipp
[FLOW_PROTO_UDP
].ctx_pm
[1].map
[0]->alproto
!= ALPROTO_HTTP1
);
2914 memset(pm_results
, 0, sizeof(pm_results
));
2916 cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2917 &f
, l7data
, sizeof(l7data
), STREAM_TOSERVER
,
2920 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2922 memset(pm_results
, 0, sizeof(pm_results
));
2923 cnt
= AppLayerProtoDetectPMGetProto(alpd_tctx
,
2924 &f
, l7data_resp
, sizeof(l7data_resp
), STREAM_TOCLIENT
,
2927 FAIL_IF(pm_results
[0] != ALPROTO_HTTP1
);
2929 AppLayerProtoDetectDestroyCtxThread(alpd_tctx
);
2930 AppLayerProtoDetectDeSetup();
2931 AppLayerProtoDetectUnittestCtxRestore();
2935 typedef struct AppLayerProtoDetectPPTestDataElement_
{
2936 const char *alproto_name
;
2939 uint32_t alproto_mask
;
2942 } AppLayerProtoDetectPPTestDataElement
;
2944 typedef struct AppLayerProtoDetectPPTestDataPort_
{
2946 uint32_t alproto_mask
;
2947 uint16_t dp_max_depth
;
2948 uint16_t sp_max_depth
;
2950 AppLayerProtoDetectPPTestDataElement
*toserver_element
;
2951 AppLayerProtoDetectPPTestDataElement
*toclient_element
;
2952 int ts_no_of_element
;
2953 int tc_no_of_element
;
2954 } AppLayerProtoDetectPPTestDataPort
;
2957 typedef struct AppLayerProtoDetectPPTestDataIPProto_
{
2960 AppLayerProtoDetectPPTestDataPort
*port
;
2962 } AppLayerProtoDetectPPTestDataIPProto
;
2964 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser
*pp
,
2965 AppLayerProtoDetectPPTestDataIPProto
*ip_proto
,
2969 int i
= -1, j
= -1 , k
= -1;
2973 for (i
= 0; i
< no_of_ip_proto
; i
++, pp
= pp
->next
) {
2974 if (pp
->ipproto
!= ip_proto
[i
].ipproto
)
2977 AppLayerProtoDetectProbingParserPort
*pp_port
= pp
->port
;
2978 for (k
= 0; k
< ip_proto
[i
].no_of_port
; k
++, pp_port
= pp_port
->next
) {
2979 if (pp_port
->port
!= ip_proto
[i
].port
[k
].port
)
2981 if (pp_port
->alproto_mask
!= ip_proto
[i
].port
[k
].alproto_mask
)
2983 if (pp_port
->alproto_mask
!= ip_proto
[i
].port
[k
].alproto_mask
)
2985 if (pp_port
->dp_max_depth
!= ip_proto
[i
].port
[k
].dp_max_depth
)
2987 if (pp_port
->sp_max_depth
!= ip_proto
[i
].port
[k
].sp_max_depth
)
2990 AppLayerProtoDetectProbingParserElement
*pp_element
= pp_port
->dp
;
2994 for (j
= 0 ; j
< ip_proto
[i
].port
[k
].ts_no_of_element
;
2995 j
++, pp_element
= pp_element
->next
) {
2997 if (pp_element
->alproto
!= ip_proto
[i
].port
[k
].toserver_element
[j
].alproto
) {
3000 if (pp_element
->port
!= ip_proto
[i
].port
[k
].toserver_element
[j
].port
) {
3003 if (pp_element
->alproto_mask
!= ip_proto
[i
].port
[k
].toserver_element
[j
].alproto_mask
) {
3006 if (pp_element
->min_depth
!= ip_proto
[i
].port
[k
].toserver_element
[j
].min_depth
) {
3009 if (pp_element
->max_depth
!= ip_proto
[i
].port
[k
].toserver_element
[j
].max_depth
) {
3013 if (pp_element
!= NULL
)
3016 pp_element
= pp_port
->sp
;
3020 for (j
= 0 ; j
< ip_proto
[i
].port
[k
].tc_no_of_element
; j
++, pp_element
= pp_element
->next
) {
3021 if (pp_element
->alproto
!= ip_proto
[i
].port
[k
].toclient_element
[j
].alproto
) {
3024 if (pp_element
->port
!= ip_proto
[i
].port
[k
].toclient_element
[j
].port
) {
3027 if (pp_element
->alproto_mask
!= ip_proto
[i
].port
[k
].toclient_element
[j
].alproto_mask
) {
3030 if (pp_element
->min_depth
!= ip_proto
[i
].port
[k
].toclient_element
[j
].min_depth
) {
3033 if (pp_element
->max_depth
!= ip_proto
[i
].port
[k
].toclient_element
[j
].max_depth
) {
3037 if (pp_element
!= NULL
)
3040 if (pp_port
!= NULL
)
3049 printf("i = %d, k = %d, j = %d(%s)\n", i
, k
, j
, (dir
== 0) ? "ts" : "tc");
3054 static uint16_t ProbingParserDummyForTesting(Flow
*f
, uint8_t direction
,
3055 const uint8_t *input
,
3056 uint32_t input_len
, uint8_t *rdir
)
3061 static int AppLayerProtoDetectTest15(void)
3063 AppLayerProtoDetectUnittestCtxBackup();
3064 AppLayerProtoDetectSetup();
3068 AppLayerProtoDetectPPRegister(IPPROTO_TCP
, "80", ALPROTO_HTTP1
, 5, 8, STREAM_TOSERVER
,
3069 ProbingParserDummyForTesting
, NULL
);
3070 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3075 ProbingParserDummyForTesting
, NULL
);
3076 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3081 ProbingParserDummyForTesting
, NULL
);
3083 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3088 ProbingParserDummyForTesting
, NULL
);
3089 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3094 ProbingParserDummyForTesting
, NULL
);
3095 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3100 ProbingParserDummyForTesting
, NULL
);
3101 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3106 ProbingParserDummyForTesting
, NULL
);
3108 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3113 ProbingParserDummyForTesting
, NULL
);
3114 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3119 ProbingParserDummyForTesting
, NULL
);
3122 AppLayerProtoDetectPPRegister(IPPROTO_UDP
,
3127 ProbingParserDummyForTesting
, NULL
);
3130 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3135 ProbingParserDummyForTesting
, NULL
);
3136 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3141 ProbingParserDummyForTesting
, NULL
);
3143 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3148 ProbingParserDummyForTesting
, NULL
);
3149 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3154 ProbingParserDummyForTesting
, NULL
);
3155 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3160 ProbingParserDummyForTesting
, NULL
);
3161 AppLayerProtoDetectPPRegister(IPPROTO_TCP
, "80", ALPROTO_HTTP1
, 5, 8, STREAM_TOCLIENT
,
3162 ProbingParserDummyForTesting
, NULL
);
3163 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3168 ProbingParserDummyForTesting
, NULL
);
3169 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3174 ProbingParserDummyForTesting
, NULL
);
3175 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3180 ProbingParserDummyForTesting
, NULL
);
3181 AppLayerProtoDetectPPRegister(IPPROTO_UDP
,
3186 ProbingParserDummyForTesting
, NULL
);
3187 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3192 ProbingParserDummyForTesting
, NULL
);
3193 AppLayerProtoDetectPPRegister(IPPROTO_TCP
,
3198 ProbingParserDummyForTesting
, NULL
);
3200 AppLayerProtoDetectPPTestDataElement element_ts_80
[] = {
3201 { "http", ALPROTO_HTTP1
, 80, 1 << ALPROTO_HTTP1
, 5, 8 },
3202 { "smb", ALPROTO_SMB
, 80, 1 << ALPROTO_SMB
, 5, 6 },
3203 { "ftp", ALPROTO_FTP
, 80, 1 << ALPROTO_FTP
, 7, 10 },
3204 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 0 },
3205 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3206 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 25 },
3207 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3209 AppLayerProtoDetectPPTestDataElement element_tc_80
[] = { { "http", ALPROTO_HTTP1
, 80,
3210 1 << ALPROTO_HTTP1
, 5, 8 },
3211 { "smb", ALPROTO_SMB
, 80, 1 << ALPROTO_SMB
, 5, 6 },
3212 { "ftp", ALPROTO_FTP
, 80, 1 << ALPROTO_FTP
, 7, 10 },
3213 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3214 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 14 },
3215 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3216 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 17 } };
3218 AppLayerProtoDetectPPTestDataElement element_ts_81
[] = {
3219 { "dcerpc", ALPROTO_DCERPC
, 81, 1 << ALPROTO_DCERPC
, 9, 10 },
3220 { "ftp", ALPROTO_FTP
, 81, 1 << ALPROTO_FTP
, 7, 15 },
3221 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 0 },
3222 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3223 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 25 },
3224 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3226 AppLayerProtoDetectPPTestDataElement element_tc_81
[] = {
3227 { "ftp", ALPROTO_FTP
, 81, 1 << ALPROTO_FTP
, 7, 15 },
3228 { "dcerpc", ALPROTO_DCERPC
, 81, 1 << ALPROTO_DCERPC
, 9, 10 },
3229 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3230 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 14 },
3231 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3232 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 17 }
3235 AppLayerProtoDetectPPTestDataElement element_ts_85
[] = {
3236 { "dcerpc", ALPROTO_DCERPC
, 85, 1 << ALPROTO_DCERPC
, 9, 10 },
3237 { "ftp", ALPROTO_FTP
, 85, 1 << ALPROTO_FTP
, 7, 15 },
3238 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 0 },
3239 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3240 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 25 },
3241 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3243 AppLayerProtoDetectPPTestDataElement element_tc_85
[] = {
3244 { "dcerpc", ALPROTO_DCERPC
, 85, 1 << ALPROTO_DCERPC
, 9, 10 },
3245 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3246 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 14 },
3247 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3248 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 17 }
3251 AppLayerProtoDetectPPTestDataElement element_ts_90
[] = {
3252 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 0 },
3253 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3254 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 25 },
3255 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3257 AppLayerProtoDetectPPTestDataElement element_tc_90
[] = {
3258 { "ftp", ALPROTO_FTP
, 90, 1 << ALPROTO_FTP
, 7, 15 },
3259 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3260 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 14 },
3261 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3262 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 17 }
3265 AppLayerProtoDetectPPTestDataElement element_ts_0
[] = {
3266 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 0 },
3267 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3268 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 25 },
3269 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3271 AppLayerProtoDetectPPTestDataElement element_tc_0
[] = {
3272 { "jabber", ALPROTO_JABBER
, 0, 1 << ALPROTO_JABBER
, 12, 23 },
3273 { "irc", ALPROTO_IRC
, 0, 1 << ALPROTO_IRC
, 12, 14 },
3274 { "tls", ALPROTO_TLS
, 0, 1 << ALPROTO_TLS
, 12, 18 },
3275 { "smtp", ALPROTO_SMTP
, 0, 1 << ALPROTO_SMTP
, 12, 17 }
3279 AppLayerProtoDetectPPTestDataElement element_ts_85_udp
[] = {
3280 { "imap", ALPROTO_IMAP
, 85, 1 << ALPROTO_IMAP
, 12, 23 },
3282 AppLayerProtoDetectPPTestDataElement element_tc_85_udp
[] = {
3283 { "imap", ALPROTO_IMAP
, 85, 1 << ALPROTO_IMAP
, 12, 23 },
3286 AppLayerProtoDetectPPTestDataPort ports_tcp
[] = {
3289 ((1 << ALPROTO_HTTP1
) | (1 << ALPROTO_SMB
) | (1 << ALPROTO_FTP
) |
3290 (1 << ALPROTO_SMTP
) | (1 << ALPROTO_TLS
) | (1 << ALPROTO_IRC
) |
3291 (1 << ALPROTO_JABBER
)),
3292 ((1 << ALPROTO_HTTP1
) | (1 << ALPROTO_SMB
) | (1 << ALPROTO_FTP
) |
3293 (1 << ALPROTO_JABBER
) | (1 << ALPROTO_IRC
) | (1 << ALPROTO_TLS
) |
3294 (1 << ALPROTO_SMTP
)),
3298 sizeof(element_ts_80
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3299 sizeof(element_tc_80
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3303 ((1 << ALPROTO_DCERPC
) | (1 << ALPROTO_FTP
) | (1 << ALPROTO_SMTP
) |
3304 (1 << ALPROTO_TLS
) | (1 << ALPROTO_IRC
) | (1 << ALPROTO_JABBER
)),
3305 ((1 << ALPROTO_FTP
) | (1 << ALPROTO_DCERPC
) | (1 << ALPROTO_JABBER
) |
3306 (1 << ALPROTO_IRC
) | (1 << ALPROTO_TLS
) | (1 << ALPROTO_SMTP
)),
3310 sizeof(element_ts_81
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3311 sizeof(element_tc_81
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3314 ((1 << ALPROTO_DCERPC
) | (1 << ALPROTO_FTP
) | (1 << ALPROTO_SMTP
) |
3315 (1 << ALPROTO_TLS
) | (1 << ALPROTO_IRC
) | (1 << ALPROTO_JABBER
)),
3316 ((1 << ALPROTO_DCERPC
) | (1 << ALPROTO_JABBER
) | (1 << ALPROTO_IRC
) |
3317 (1 << ALPROTO_TLS
) | (1 << ALPROTO_SMTP
)),
3318 23, element_ts_85
, element_tc_85
,
3319 sizeof(element_ts_85
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3320 sizeof(element_tc_85
) / sizeof(AppLayerProtoDetectPPTestDataElement
) },
3322 ((1 << ALPROTO_SMTP
) | (1 << ALPROTO_TLS
) | (1 << ALPROTO_IRC
) |
3323 (1 << ALPROTO_JABBER
)),
3324 ((1 << ALPROTO_FTP
) | (1 << ALPROTO_JABBER
) | (1 << ALPROTO_IRC
) |
3325 (1 << ALPROTO_TLS
) | (1 << ALPROTO_SMTP
)),
3326 23, element_ts_90
, element_tc_90
,
3327 sizeof(element_ts_90
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3328 sizeof(element_tc_90
) / sizeof(AppLayerProtoDetectPPTestDataElement
) },
3330 ((1 << ALPROTO_SMTP
) | (1 << ALPROTO_TLS
) | (1 << ALPROTO_IRC
) |
3331 (1 << ALPROTO_JABBER
)),
3332 ((1 << ALPROTO_JABBER
) | (1 << ALPROTO_IRC
) | (1 << ALPROTO_TLS
) |
3333 (1 << ALPROTO_SMTP
)),
3334 23, element_ts_0
, element_tc_0
,
3335 sizeof(element_ts_0
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3336 sizeof(element_tc_0
) / sizeof(AppLayerProtoDetectPPTestDataElement
) }
3339 AppLayerProtoDetectPPTestDataPort ports_udp
[] = {
3341 (1 << ALPROTO_IMAP
),
3342 (1 << ALPROTO_IMAP
),
3344 element_ts_85_udp
, element_tc_85_udp
,
3345 sizeof(element_ts_85_udp
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3346 sizeof(element_tc_85_udp
) / sizeof(AppLayerProtoDetectPPTestDataElement
),
3350 AppLayerProtoDetectPPTestDataIPProto ip_proto
[] = {
3353 sizeof(ports_tcp
) / sizeof(AppLayerProtoDetectPPTestDataPort
),
3357 sizeof(ports_udp
) / sizeof(AppLayerProtoDetectPPTestDataPort
),
3362 if (AppLayerProtoDetectPPTestData(alpd_ctx
.ctx_pp
, ip_proto
,
3363 sizeof(ip_proto
) / sizeof(AppLayerProtoDetectPPTestDataIPProto
)) == 0) {
3369 AppLayerProtoDetectDeSetup();
3370 AppLayerProtoDetectUnittestCtxRestore();
3375 /** \test test if the engine detect the proto and match with it */
3376 static int AppLayerProtoDetectTest16(void)
3380 HtpState
*http_state
= NULL
;
3381 uint8_t http_buf1
[] = "POST /one HTTP/1.0\r\n"
3382 "User-Agent: Mozilla/1.0\r\n"
3383 "Cookie: hellocatch\r\n\r\n";
3384 uint32_t http_buf1_len
= sizeof(http_buf1
) - 1;
3387 Signature
*s
= NULL
;
3389 DetectEngineThreadCtx
*det_ctx
= NULL
;
3390 DetectEngineCtx
*de_ctx
= NULL
;
3391 AppLayerParserThreadCtx
*alp_tctx
= AppLayerParserThreadCtxAlloc();
3393 memset(&tv
, 0, sizeof(ThreadVars
));
3394 memset(&ssn
, 0, sizeof(TcpSession
));
3396 p
= UTHBuildPacket(NULL
, 0, IPPROTO_TCP
);
3398 printf("packet setup failed: ");
3402 f
= UTHBuildFlow(AF_INET
, "1.1.1.1", "2.2.2.2", 1024, 80);
3404 printf("flow setup failed: ");
3408 f
->proto
= IPPROTO_TCP
;
3411 p
->flowflags
|= FLOW_PKT_TOSERVER
;
3412 p
->flowflags
|= FLOW_PKT_ESTABLISHED
;
3413 p
->flags
|= PKT_HAS_FLOW
|PKT_STREAM_EST
;
3415 f
->alproto
= ALPROTO_HTTP1
;
3417 StreamTcpInitConfig(true);
3419 de_ctx
= DetectEngineCtxInit();
3420 if (de_ctx
== NULL
) {
3423 de_ctx
->flags
|= DE_QUIET
;
3425 s
= de_ctx
->sig_list
= SigInit(de_ctx
, "alert http any any -> any any "
3426 "(msg:\"Test content option\"; "
3432 SigGroupBuild(de_ctx
);
3433 DetectEngineThreadCtxInit(&tv
, (void *)de_ctx
, (void *)&det_ctx
);
3436 int r
= AppLayerParserParse(
3437 NULL
, alp_tctx
, f
, ALPROTO_HTTP1
, STREAM_TOSERVER
, http_buf1
, http_buf1_len
);
3439 printf("toserver chunk 1 returned %" PRId32
", expected 0: ", r
);
3445 http_state
= f
->alstate
;
3446 if (http_state
== NULL
) {
3447 printf("no http state: ");
3452 SigMatchSignatures(&tv
, de_ctx
, det_ctx
, p
);
3454 if (!PacketAlertCheck(p
, 1)) {
3455 printf("sig 1 didn't alert, but it should: ");
3460 if (alp_tctx
!= NULL
)
3461 AppLayerParserThreadCtxFree(alp_tctx
);
3462 if (det_ctx
!= NULL
)
3463 DetectEngineThreadCtxDeinit(&tv
, det_ctx
);
3465 SigGroupCleanup(de_ctx
);
3467 DetectEngineCtxFree(de_ctx
);
3469 StreamTcpFreeConfig(true);
3471 UTHFreePackets(&p
, 1);
3476 /** \test test if the engine detect the proto on a non standar port
3477 * and match with it */
3478 static int AppLayerProtoDetectTest17(void)
3482 HtpState
*http_state
= NULL
;
3483 uint8_t http_buf1
[] = "POST /one HTTP/1.0\r\n"
3484 "User-Agent: Mozilla/1.0\r\n"
3485 "Cookie: hellocatch\r\n\r\n";
3486 uint32_t http_buf1_len
= sizeof(http_buf1
) - 1;
3489 Signature
*s
= NULL
;
3491 DetectEngineThreadCtx
*det_ctx
= NULL
;
3492 DetectEngineCtx
*de_ctx
= NULL
;
3493 AppLayerParserThreadCtx
*alp_tctx
= AppLayerParserThreadCtxAlloc();
3495 memset(&tv
, 0, sizeof(ThreadVars
));
3496 memset(&ssn
, 0, sizeof(TcpSession
));
3498 p
= UTHBuildPacketSrcDstPorts(http_buf1
, http_buf1_len
, IPPROTO_TCP
, 12345, 88);
3500 f
= UTHBuildFlow(AF_INET
, "1.1.1.1", "2.2.2.2", 1024, 80);
3504 f
->proto
= IPPROTO_TCP
;
3506 p
->flowflags
|= FLOW_PKT_TOSERVER
;
3507 p
->flowflags
|= FLOW_PKT_ESTABLISHED
;
3508 p
->flags
|= PKT_HAS_FLOW
|PKT_STREAM_EST
;
3509 f
->alproto
= ALPROTO_HTTP1
;
3511 StreamTcpInitConfig(true);
3513 de_ctx
= DetectEngineCtxInit();
3514 if (de_ctx
== NULL
) {
3517 de_ctx
->flags
|= DE_QUIET
;
3519 s
= de_ctx
->sig_list
= SigInit(de_ctx
, "alert http any !80 -> any any "
3520 "(msg:\"http over non standar port\"; "
3526 SigGroupBuild(de_ctx
);
3527 DetectEngineThreadCtxInit(&tv
, (void *)de_ctx
, (void *)&det_ctx
);
3530 int r
= AppLayerParserParse(
3531 NULL
, alp_tctx
, f
, ALPROTO_HTTP1
, STREAM_TOSERVER
, http_buf1
, http_buf1_len
);
3533 printf("toserver chunk 1 returned %" PRId32
", expected 0: ", r
);
3539 http_state
= f
->alstate
;
3540 if (http_state
== NULL
) {
3541 printf("no http state: ");
3546 SigMatchSignatures(&tv
, de_ctx
, det_ctx
, p
);
3548 if (!PacketAlertCheck(p
, 1)) {
3549 printf("sig 1 didn't alert, but it should: ");
3556 if (alp_tctx
!= NULL
)
3557 AppLayerParserThreadCtxFree(alp_tctx
);
3558 if (det_ctx
!= NULL
)
3559 DetectEngineThreadCtxDeinit(&tv
, det_ctx
);
3561 SigGroupCleanup(de_ctx
);
3563 DetectEngineCtxFree(de_ctx
);
3565 StreamTcpFreeConfig(true);
3567 UTHFreePackets(&p
, 1);
3572 /** \test test if the engine detect the proto and doesn't match
3573 * because the sig expects another proto (ex ftp)*/
3574 static int AppLayerProtoDetectTest18(void)
3578 HtpState
*http_state
= NULL
;
3579 uint8_t http_buf1
[] = "POST /one HTTP/1.0\r\n"
3580 "User-Agent: Mozilla/1.0\r\n"
3581 "Cookie: hellocatch\r\n\r\n";
3582 uint32_t http_buf1_len
= sizeof(http_buf1
) - 1;
3585 Signature
*s
= NULL
;
3587 DetectEngineThreadCtx
*det_ctx
= NULL
;
3588 DetectEngineCtx
*de_ctx
= NULL
;
3589 AppLayerParserThreadCtx
*alp_tctx
= AppLayerParserThreadCtxAlloc();
3591 memset(&tv
, 0, sizeof(ThreadVars
));
3592 memset(&ssn
, 0, sizeof(TcpSession
));
3594 p
= UTHBuildPacket(http_buf1
, http_buf1_len
, IPPROTO_TCP
);
3596 f
= UTHBuildFlow(AF_INET
, "1.1.1.1", "2.2.2.2", 1024, 80);
3600 f
->proto
= IPPROTO_TCP
;
3602 p
->flowflags
|= FLOW_PKT_TOSERVER
;
3603 p
->flowflags
|= FLOW_PKT_ESTABLISHED
;
3604 p
->flags
|= PKT_HAS_FLOW
|PKT_STREAM_EST
;
3605 f
->alproto
= ALPROTO_HTTP1
;
3607 StreamTcpInitConfig(true);
3609 de_ctx
= DetectEngineCtxInit();
3610 if (de_ctx
== NULL
) {
3613 de_ctx
->flags
|= DE_QUIET
;
3615 s
= de_ctx
->sig_list
= SigInit(de_ctx
, "alert ftp any any -> any any "
3616 "(msg:\"Test content option\"; "
3622 SigGroupBuild(de_ctx
);
3623 DetectEngineThreadCtxInit(&tv
, (void *)de_ctx
, (void *)&det_ctx
);
3626 int r
= AppLayerParserParse(
3627 NULL
, alp_tctx
, f
, ALPROTO_HTTP1
, STREAM_TOSERVER
, http_buf1
, http_buf1_len
);
3629 printf("toserver chunk 1 returned %" PRId32
", expected 0: ", r
);
3635 http_state
= f
->alstate
;
3636 if (http_state
== NULL
) {
3637 printf("no http state: ");
3642 SigMatchSignatures(&tv
, de_ctx
, det_ctx
, p
);
3644 if (PacketAlertCheck(p
, 1)) {
3645 printf("sig 1 alerted, but it should not (it's not ftp): ");
3651 if (alp_tctx
!= NULL
)
3652 AppLayerParserThreadCtxFree(alp_tctx
);
3653 if (det_ctx
!= NULL
)
3654 DetectEngineThreadCtxDeinit(&tv
, det_ctx
);
3656 SigGroupCleanup(de_ctx
);
3658 DetectEngineCtxFree(de_ctx
);
3660 StreamTcpFreeConfig(true);
3662 UTHFreePackets(&p
, 1);
3667 /** \test test if the engine detect the proto and doesn't match
3668 * because the packet has another proto (ex ftp) */
3669 static int AppLayerProtoDetectTest19(void)
3673 uint8_t http_buf1
[] = "MPUT one\r\n";
3674 uint32_t http_buf1_len
= sizeof(http_buf1
) - 1;
3677 Signature
*s
= NULL
;
3679 DetectEngineThreadCtx
*det_ctx
= NULL
;
3680 DetectEngineCtx
*de_ctx
= NULL
;
3681 AppLayerParserThreadCtx
*alp_tctx
= AppLayerParserThreadCtxAlloc();
3683 memset(&tv
, 0, sizeof(ThreadVars
));
3684 memset(&ssn
, 0, sizeof(TcpSession
));
3686 p
= UTHBuildPacketSrcDstPorts(http_buf1
, http_buf1_len
, IPPROTO_TCP
, 12345, 88);
3688 f
= UTHBuildFlow(AF_INET
, "1.1.1.1", "2.2.2.2", 1024, 80);
3692 f
->proto
= IPPROTO_TCP
;
3694 p
->flowflags
|= FLOW_PKT_TOSERVER
;
3695 p
->flowflags
|= FLOW_PKT_ESTABLISHED
;
3696 p
->flags
|= PKT_HAS_FLOW
|PKT_STREAM_EST
;
3697 f
->alproto
= ALPROTO_FTP
;
3699 StreamTcpInitConfig(true);
3701 de_ctx
= DetectEngineCtxInit();
3702 if (de_ctx
== NULL
) {
3705 de_ctx
->flags
|= DE_QUIET
;
3707 s
= de_ctx
->sig_list
= SigInit(de_ctx
, "alert http any !80 -> any any "
3708 "(msg:\"http over non standar port\"; "
3714 SigGroupBuild(de_ctx
);
3715 DetectEngineThreadCtxInit(&tv
, (void *)de_ctx
, (void *)&det_ctx
);
3718 int r
= AppLayerParserParse(NULL
, alp_tctx
, f
, ALPROTO_FTP
,
3719 STREAM_TOSERVER
, http_buf1
, http_buf1_len
);
3721 printf("toserver chunk 1 returned %" PRId32
", expected 0: ", r
);
3728 SigMatchSignatures(&tv
, de_ctx
, det_ctx
, p
);
3730 if (PacketAlertCheck(p
, 1)) {
3731 printf("sig 1 alerted, but it should not (it's ftp): ");
3738 if (alp_tctx
!= NULL
)
3739 AppLayerParserThreadCtxFree(alp_tctx
);
3740 if (det_ctx
!= NULL
)
3741 DetectEngineThreadCtxDeinit(&tv
, det_ctx
);
3743 SigGroupCleanup(de_ctx
);
3745 DetectEngineCtxFree(de_ctx
);
3747 StreamTcpFreeConfig(true);
3748 UTHFreePackets(&p
, 1);
3753 void AppLayerProtoDetectUnittestsRegister(void)
3757 UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01
);
3758 UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02
);
3759 UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03
);
3760 UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04
);
3761 UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05
);
3762 UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06
);
3763 UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07
);
3764 UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08
);
3765 UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09
);
3766 UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10
);
3767 UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11
);
3768 UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12
);
3769 UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13
);
3770 UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14
);
3771 UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15
);
3772 UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16
);
3773 UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17
);
3774 UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18
);
3775 UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19
);
3780 #endif /* UNITTESTS */