]> git.ipfire.org Git - people/ms/suricata.git/blob - src/app-layer-detect-proto.c
protodetect: fix int warnings
[people/ms/suricata.git] / src / app-layer-detect-proto.c
1 /* Copyright (C) 2007-2014 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18 /**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23 */
24
25 #include "suricata-common.h"
26 #include "debug.h"
27 #include "decode.h"
28 #include "threads.h"
29 #include "threadvars.h"
30 #include "tm-threads.h"
31
32 #include "detect.h"
33 #include "detect-engine-port.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-content.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-state.h"
39
40 #include "util-print.h"
41 #include "util-pool.h"
42 #include "util-unittest.h"
43 #include "util-unittest-helper.h"
44 #include "util-validate.h"
45
46 #include "flow.h"
47 #include "flow-util.h"
48 #include "flow-private.h"
49
50 #include "stream-tcp-private.h"
51 #include "stream-tcp-reassemble.h"
52 #include "stream-tcp.h"
53 #include "stream.h"
54
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"
60
61 #include "conf.h"
62 #include "util-memcmp.h"
63 #include "util-spm.h"
64 #include "util-debug.h"
65 #include "util-validate.h"
66
67 #include "runmodes.h"
68
69 typedef struct AppLayerProtoDetectProbingParserElement_ {
70 AppProto alproto;
71 /* \todo don't really need it. See if you can get rid of it */
72 uint16_t port;
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 */
76 uint16_t min_depth;
77 /* the max length of data after which this parser won't be invoked */
78 uint16_t max_depth;
79
80 /* the to_server probing parser function */
81 ProbingParserFPtr ProbingParserTs;
82
83 /* the to_client probing parser function */
84 ProbingParserFPtr ProbingParserTc;
85
86 struct AppLayerProtoDetectProbingParserElement_ *next;
87 } AppLayerProtoDetectProbingParserElement;
88
89 typedef struct AppLayerProtoDetectProbingParserPort_ {
90 /* the port no for which probing parser(s) are invoked */
91 uint16_t port;
92
93 uint32_t alproto_mask;
94
95 /* the max depth for all the probing parsers registered for this port */
96 uint16_t dp_max_depth;
97 uint16_t sp_max_depth;
98
99 AppLayerProtoDetectProbingParserElement *dp;
100 AppLayerProtoDetectProbingParserElement *sp;
101
102 struct AppLayerProtoDetectProbingParserPort_ *next;
103 } AppLayerProtoDetectProbingParserPort;
104
105 typedef struct AppLayerProtoDetectProbingParser_ {
106 uint8_t ipproto;
107 AppLayerProtoDetectProbingParserPort *port;
108
109 struct AppLayerProtoDetectProbingParser_ *next;
110 } AppLayerProtoDetectProbingParser;
111
112 typedef struct AppLayerProtoDetectPMSignature_ {
113 AppProto alproto;
114 uint8_t direction; /**< direction for midstream */
115 SigIntId id;
116 /* \todo Change this into a non-pointer */
117 DetectContentData *cd;
118 uint16_t pp_min_depth;
119 uint16_t pp_max_depth;
120 ProbingParserFPtr PPFunc;
121 struct AppLayerProtoDetectPMSignature_ *next;
122 } AppLayerProtoDetectPMSignature;
123
124 typedef struct AppLayerProtoDetectPMCtx_ {
125 uint16_t pp_max_len;
126 uint16_t min_len;
127 MpmCtx mpm_ctx;
128
129 /** Mapping between pattern id and signature. As each signature has a
130 * unique pattern with a unique id, we can lookup the signature by
131 * the pattern id. */
132 AppLayerProtoDetectPMSignature **map;
133 AppLayerProtoDetectPMSignature *head;
134
135 /* \todo we don't need this except at setup time. Get rid of it. */
136 PatIntId max_pat_id;
137 SigIntId max_sig_id;
138 } AppLayerProtoDetectPMCtx;
139
140 typedef struct AppLayerProtoDetectCtxIpproto_ {
141 /* 0 - toserver, 1 - toclient */
142 AppLayerProtoDetectPMCtx ctx_pm[2];
143 } AppLayerProtoDetectCtxIpproto;
144
145 /**
146 * \brief The app layer protocol detection context.
147 */
148 typedef struct AppLayerProtoDetectCtx_ {
149 /* Context per ip_proto.
150 * \todo Modify ctx_ipp to hold for only tcp and udp. The rest can be
151 * implemented if needed. Waste of space otherwise. */
152 AppLayerProtoDetectCtxIpproto ctx_ipp[FLOW_PROTO_DEFAULT];
153
154 /* Global SPM thread context prototype. */
155 SpmGlobalThreadCtx *spm_global_thread_ctx;
156
157 AppLayerProtoDetectProbingParser *ctx_pp;
158
159 /* Indicates the protocols that have registered themselves
160 * for protocol detection. This table is independent of the
161 * ipproto. */
162 const char *alproto_names[ALPROTO_MAX];
163 } AppLayerProtoDetectCtx;
164
165 typedef struct AppLayerProtoDetectAliases_ {
166 const char *proto_name;
167 const char *proto_alias;
168 struct AppLayerProtoDetectAliases_ *next;
169 } AppLayerProtoDetectAliases;
170
171 /**
172 * \brief The app layer protocol detection thread context.
173 */
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;
179 };
180
181 /* The global app layer proto detection context. */
182 static AppLayerProtoDetectCtx alpd_ctx;
183 static AppLayerProtoDetectAliases *alpda_ctx = NULL;
184
185 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
186 uint8_t *ipprotos);
187
188 /***** Static Internal Calls: Protocol Retrieval *****/
189
190 /** \internal
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)
197 {
198 SCEnter();
199
200 if (s->cd->offset > searchlen) {
201 SCLogDebug("s->co->offset (%"PRIu16") > searchlen (%"PRIu16")",
202 s->cd->offset, searchlen);
203 SCReturnUInt(ALPROTO_UNKNOWN);
204 }
205 if (s->cd->depth > searchlen) {
206 SCLogDebug("s->co->depth (%"PRIu16") > searchlen (%"PRIu16")",
207 s->cd->depth, searchlen);
208 SCReturnUInt(ALPROTO_UNKNOWN);
209 }
210
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);
215
216 uint8_t *found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx,
217 sbuf, ssearchlen);
218 if (found == NULL) {
219 SCReturnUInt(ALPROTO_UNKNOWN);
220 }
221
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");
229 } else {
230 SCLogDebug("direction is wrong, rflow = true");
231 *rflow = true;
232 }
233 /* validate using Probing Parser */
234 } else {
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);
239 }
240
241 uint8_t rdir = 0;
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);
251 } else {
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);
256 }
257 SCReturnUInt(ALPROTO_UNKNOWN);
258 }
259 }
260 SCReturnUInt(s->alproto);
261 }
262
263 /**
264 * \retval 0 no matches
265 * \retval -1 no matches, mpm depth reached
266 */
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)
270 {
271 int pm_matches = 0;
272
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);
276
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,
280 buf, searchlen);
281 if (search_cnt == 0) {
282 if (buflen >= pm_ctx->mpm_ctx.maxdepth)
283 return -1;
284 return 0;
285 }
286
287 /* alproto bit field */
288 uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
289 memset(pm_results_bf, 0, sizeof(pm_results_bf));
290
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]];
296 while (s != NULL) {
297 AppProto proto = AppLayerProtoDetectPMMatchSignature(
298 s, tctx, f, flags, buf, buflen, searchlen, rflow);
299
300 /* store each unique proto once */
301 if (AppProtoIsValid(proto) &&
302 !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
303 {
304 pm_results[pm_matches++] = proto;
305 pm_results_bf[proto / 8] |= 1 << (proto % 8);
306 }
307 s = s->next;
308 }
309 }
310 if (pm_matches == 0 && buflen >= pm_ctx->pp_max_len) {
311 pm_matches = -2;
312 }
313 PmqReset(&tctx->pmq);
314 return pm_matches;
315 }
316
317 /** \internal
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)
323 {
324 SCEnter();
325
326 pm_results[0] = ALPROTO_UNKNOWN;
327
328 AppLayerProtoDetectPMCtx *pm_ctx;
329 MpmThreadCtx *mpm_tctx;
330 int m = -1;
331
332 if (f->protomap >= FLOW_PROTO_DEFAULT) {
333 pm_results[0] = ALPROTO_FAILED;
334 SCReturnUInt(1);
335 }
336
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];
340 } else {
341 pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
342 mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
343 }
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);
346 }
347 /* pattern found, yay */
348 if (m > 0) {
349 FLOW_SET_PM_DONE(f, flags);
350 SCReturnUInt((uint16_t)m);
351
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
355 * was reached. */
356 if (m < 0) {
357 FLOW_SET_PM_DONE(f, flags);
358 SCReturnUInt(0);
359 } else if (m == 0) {
360 SCReturnUInt(0);
361 }
362 SCReturnUInt((uint16_t)m);
363
364 /* handle non-found in midstream case */
365 } else if (m <= 0) {
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];
369 } else {
370 pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
371 mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
372 }
373 SCLogDebug("no matches and in midstream mode, lets try the "
374 "*patterns for the other side");
375
376 int om = -1;
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);
380 }
381 /* found! */
382 if (om > 0) {
383 FLOW_SET_PM_DONE(f, flags);
384 SCReturnUInt((uint16_t)om);
385
386 /* both sides failed */
387 } else if (om < 0 && m && m < 0) {
388 FLOW_SET_PM_DONE(f, flags);
389 SCReturnUInt(0);
390
391 /* one side still uncertain */
392 } else if (om == 0 || m == 0) {
393 SCReturnUInt(0);
394 }
395 }
396 SCReturnUInt(0);
397 }
398
399 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectGetProbingParser(
400 AppLayerProtoDetectProbingParser *pp, uint8_t ipproto, AppProto alproto)
401 {
402 AppLayerProtoDetectProbingParserElement *pp_elem = NULL;
403 AppLayerProtoDetectProbingParserPort *pp_port = NULL;
404
405 while (pp != NULL) {
406 if (pp->ipproto == ipproto)
407 break;
408 pp = pp->next;
409 }
410 if (pp == NULL)
411 return NULL;
412
413 pp_port = pp->port;
414 while (pp_port != NULL) {
415 if (pp_port->dp != NULL && pp_port->dp->alproto == alproto) {
416 pp_elem = pp_port->dp;
417 break;
418 }
419 if (pp_port->sp != NULL && pp_port->sp->alproto == alproto) {
420 pp_elem = pp_port->sp;
421 break;
422 }
423 pp_port = pp_port->next;
424 }
425
426 SCReturnPtr(pp_elem, "AppLayerProtoDetectProbingParserElement *");
427 }
428
429 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
430 uint8_t ipproto,
431 uint16_t port)
432 {
433 AppLayerProtoDetectProbingParserPort *pp_port = NULL;
434
435 while (pp != NULL) {
436 if (pp->ipproto == ipproto)
437 break;
438
439 pp = pp->next;
440 }
441
442 if (pp == NULL)
443 goto end;
444
445 pp_port = pp->port;
446 while (pp_port != NULL) {
447 if (pp_port->port == port || pp_port->port == 0) {
448 break;
449 }
450 pp_port = pp_port->next;
451 }
452
453 end:
454 SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
455 }
456
457
458 /**
459 * \brief Call the probing expectation to see if there is some for this flow.
460 *
461 */
462 static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto, uint8_t flags)
463 {
464 AppProto alproto = ALPROTO_UNKNOWN;
465
466 SCLogDebug("expectation check for %p (dir %d)", f, flags);
467 FLOW_SET_PE_DONE(f, flags);
468
469 alproto = AppLayerExpectationHandle(f, flags);
470
471 return alproto;
472 }
473
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)
476 {
477 while (pe != NULL) {
478 if ((buflen < pe->min_depth) ||
479 (alproto_masks[0] & pe->alproto_mask)) {
480 pe = pe->next;
481 continue;
482 }
483
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);
489 }
490 if (AppProtoIsValid(alproto)) {
491 SCReturnUInt(alproto);
492 }
493 if (alproto == ALPROTO_FAILED ||
494 (pe->max_depth != 0 && buflen > pe->max_depth)) {
495 alproto_masks[0] |= pe->alproto_mask;
496 }
497 pe = pe->next;
498 }
499
500 SCReturnUInt(ALPROTO_UNKNOWN);
501 }
502
503 /**
504 * \brief Call the probing parser if it exists for this flow.
505 *
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.
508 *
509 */
510 static AppProto AppLayerProtoDetectPPGetProto(Flow *f, const uint8_t *buf, uint32_t buflen,
511 uint8_t ipproto, const uint8_t flags, bool *reverse_flow)
512 {
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;
520 uint32_t mask = 0;
521 uint8_t idir = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
522 uint8_t dir = idir;
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;
526
527 again_midstream:
528 if (idir != dir) {
529 SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
530 }
531 SCLogDebug("%u->%u %s", sp, dp,
532 (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
533
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);
540
541 /* found based on destination port, so use dp registration */
542 pe1 = pp_port_dp->dp;
543 } else {
544 SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
545 }
546
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);
550
551 /* found based on source port, so use sp registration */
552 pe2 = pp_port_sp->sp;
553 } else {
554 SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
555 }
556 } else {
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);
562
563 /* found based on destination port, so use dp registration */
564 pe1 = pp_port_dp->dp;
565 } else {
566 SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
567 }
568
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);
572
573 pe2 = pp_port_sp->sp;
574 } else {
575 SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
576 }
577 }
578
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);
583 }
584
585 if (pe1 == NULL && pe2 == NULL && pe0 == NULL) {
586 SCLogDebug("%s - No probing parsers found for either port",
587 (dir == STREAM_TOSERVER) ? "toserver":"toclient");
588 goto noparsers;
589 } else {
590 probe_is_found = true;
591 }
592
593 /* run the parser(s): always call with original direction */
594 uint8_t rdir = 0;
595 alproto = PPGetProto(pe0, f, flags, buf, buflen, alproto_masks, &rdir);
596 if (AppProtoIsValid(alproto))
597 goto end;
598 alproto = PPGetProto(pe1, f, flags, buf, buflen, alproto_masks, &rdir);
599 if (AppProtoIsValid(alproto))
600 goto end;
601 alproto = PPGetProto(pe2, f, flags, buf, buflen, alproto_masks, &rdir);
602 if (AppProtoIsValid(alproto))
603 goto end;
604
605 /* get the mask we need for this direction */
606 if (dir == idir) {
607 if (pp_port_dp && pp_port_sp)
608 mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
609 else if (pp_port_dp)
610 mask = pp_port_dp->alproto_mask;
611 else if (pp_port_sp)
612 mask = pp_port_sp->alproto_mask;
613
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);
619 } else {
620 SCLogDebug("%s, mask is now %08x, need %08x",
621 (dir == STREAM_TOSERVER) ? "toserver":"toclient",
622 alproto_masks[0], mask);
623 }
624 }
625
626 noparsers:
627 if (stream_config.midstream && idir == dir) {
628 if (idir == STREAM_TOSERVER) {
629 dir = STREAM_TOCLIENT;
630 } else {
631 dir = STREAM_TOSERVER;
632 }
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);
638 }
639
640 end:
641 if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
642 SCLogDebug("PP found %u, is reverse flow", alproto);
643 *reverse_flow = true;
644 }
645
646 SCLogDebug("%s, mask is now %08x",
647 (idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
648 SCReturnUInt(alproto);
649 }
650
651 /***** Static Internal Calls: PP registration *****/
652
653 static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
654 uint8_t *ipprotos)
655 {
656 SCEnter();
657
658 const AppLayerProtoDetectProbingParser *pp;
659 const AppLayerProtoDetectProbingParserPort *pp_port;
660 const AppLayerProtoDetectProbingParserElement *pp_pe;
661
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);
667 }
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);
671 }
672 }
673 }
674
675 SCReturn;
676 }
677
678 static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
679 {
680 SCEnter();
681
682 if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
683 FatalError(SC_ERR_ALPARSER, "Unknown protocol detected - %u", alproto);
684 }
685
686 SCReturnUInt(1UL << (uint32_t)alproto);
687 }
688
689 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
690 {
691 SCEnter();
692
693 AppLayerProtoDetectProbingParserElement *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement));
694 if (unlikely(p == NULL)) {
695 exit(EXIT_FAILURE);
696 }
697 memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
698
699 SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
700 }
701
702
703 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
704 {
705 SCEnter();
706 SCFree(p);
707 SCReturn;
708 }
709
710 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
711 {
712 SCEnter();
713
714 AppLayerProtoDetectProbingParserPort *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort));
715 if (unlikely(p == NULL)) {
716 exit(EXIT_FAILURE);
717 }
718 memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
719
720 SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
721 }
722
723 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
724 {
725 SCEnter();
726
727 AppLayerProtoDetectProbingParserElement *e;
728
729 e = p->dp;
730 while (e != NULL) {
731 AppLayerProtoDetectProbingParserElement *e_next = e->next;
732 AppLayerProtoDetectProbingParserElementFree(e);
733 e = e_next;
734 }
735
736 e = p->sp;
737 while (e != NULL) {
738 AppLayerProtoDetectProbingParserElement *e_next = e->next;
739 AppLayerProtoDetectProbingParserElementFree(e);
740 e = e_next;
741 }
742
743 SCFree(p);
744
745 SCReturn;
746 }
747
748 static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
749 {
750 SCEnter();
751
752 AppLayerProtoDetectProbingParser *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParser));
753 if (unlikely(p == NULL)) {
754 exit(EXIT_FAILURE);
755 }
756 memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
757
758 SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
759 }
760
761 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
762 {
763 SCEnter();
764
765 AppLayerProtoDetectProbingParserPort *pt = p->port;
766 while (pt != NULL) {
767 AppLayerProtoDetectProbingParserPort *pt_next = pt->next;
768 AppLayerProtoDetectProbingParserPortFree(pt);
769 pt = pt_next;
770 }
771
772 SCFree(p);
773
774 SCReturn;
775 }
776
777 static AppLayerProtoDetectProbingParserElement *
778 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
779 uint16_t port,
780 uint16_t min_depth,
781 uint16_t max_depth)
782 {
783 AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
784
785 pe->alproto = alproto;
786 pe->port = port;
787 pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
788 pe->min_depth = min_depth;
789 pe->max_depth = max_depth;
790 pe->next = NULL;
791
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");
795 goto error;
796 }
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);
800 goto error;
801 }
802
803 SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
804 error:
805 AppLayerProtoDetectProbingParserElementFree(pe);
806 SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
807 }
808
809 static AppLayerProtoDetectProbingParserElement *
810 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
811 {
812 SCEnter();
813
814 AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
815
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;
823 new_pe->next = NULL;
824
825 SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
826 }
827
828 #ifdef DEBUG
829 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
830 {
831 SCEnter();
832
833 AppLayerProtoDetectProbingParserPort *pp_port = NULL;
834 AppLayerProtoDetectProbingParserElement *pp_pe = NULL;
835
836 printf("\nProtocol Detection Configuration\n");
837
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");
844 else
845 printf("IPProto: %"PRIu8"\n", pp->ipproto);
846
847 pp_port = pp->port;
848 for ( ; pp_port != NULL; pp_port = pp_port->next) {
849 if (pp_port->dp != NULL) {
850 printf(" Port: %"PRIu16 "\n", pp_port->port);
851
852 printf(" Destination port: (max-depth: %"PRIu16 ", "
853 "mask - %"PRIu32")\n",
854 pp_port->dp_max_depth,
855 pp_port->alproto_mask);
856 pp_pe = pp_port->dp;
857 for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
858
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");
913 else
914 printf("impossible\n");
915
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);
920
921 printf("\n");
922 }
923 }
924
925 if (pp_port->sp == NULL) {
926 continue;
927 }
928
929 printf(" Source port: (max-depth: %"PRIu16 ", "
930 "mask - %"PRIu32")\n",
931 pp_port->sp_max_depth,
932 pp_port->alproto_mask);
933 pp_pe = pp_port->sp;
934 for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
935
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");
990 else
991 printf("impossible\n");
992
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);
997
998 printf("\n");
999 }
1000 }
1001 }
1002
1003 SCReturn;
1004 }
1005 #endif
1006
1007 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
1008 AppLayerProtoDetectProbingParserElement *new_pe)
1009 {
1010 SCEnter();
1011
1012 if (*head_pe == NULL) {
1013 *head_pe = new_pe;
1014 goto end;
1015 }
1016
1017 if ((*head_pe)->port == 0) {
1018 if (new_pe->port != 0) {
1019 new_pe->next = *head_pe;
1020 *head_pe = new_pe;
1021 } else {
1022 AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
1023 while (temp_pe->next != NULL)
1024 temp_pe = temp_pe->next;
1025 temp_pe->next = new_pe;
1026 }
1027 } else {
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;
1033 } else {
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;
1038
1039 }
1040 }
1041
1042 end:
1043 SCReturn;
1044 }
1045
1046 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1047 AppLayerProtoDetectProbingParser *new_pp)
1048 {
1049 SCEnter();
1050
1051 if (*head_pp == NULL) {
1052 *head_pp = new_pp;
1053 goto end;
1054 }
1055
1056 AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1057 while (temp_pp->next != NULL)
1058 temp_pp = temp_pp->next;
1059 temp_pp->next = new_pp;
1060
1061 end:
1062 SCReturn;
1063 }
1064
1065 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1066 AppLayerProtoDetectProbingParserPort *new_port)
1067 {
1068 SCEnter();
1069
1070 if (*head_port == NULL) {
1071 *head_port = new_port;
1072 goto end;
1073 }
1074
1075 if ((*head_port)->port == 0) {
1076 new_port->next = *head_port;
1077 *head_port = new_port;
1078 } else {
1079 AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1080 while (temp_port->next != NULL && temp_port->next->port != 0) {
1081 temp_port = temp_port->next;
1082 }
1083 new_port->next = temp_port->next;
1084 temp_port->next = new_port;
1085 }
1086
1087 end:
1088 SCReturn;
1089 }
1090
1091 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1092 uint8_t ipproto,
1093 uint16_t port,
1094 AppProto alproto,
1095 uint16_t min_depth, uint16_t max_depth,
1096 uint8_t direction,
1097 ProbingParserFPtr ProbingParser1,
1098 ProbingParserFPtr ProbingParser2)
1099 {
1100 SCEnter();
1101
1102 /* get the top level ipproto pp */
1103 AppLayerProtoDetectProbingParser *curr_pp = *pp;
1104 while (curr_pp != NULL) {
1105 if (curr_pp->ipproto == ipproto)
1106 break;
1107 curr_pp = curr_pp->next;
1108 }
1109 if (curr_pp == NULL) {
1110 AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1111 new_pp->ipproto = ipproto;
1112 AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1113 curr_pp = new_pp;
1114 }
1115
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)
1120 break;
1121 curr_port = curr_port->next;
1122 }
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;
1130 } else {
1131 curr_port->sp_max_depth = max_depth;
1132 }
1133
1134 AppLayerProtoDetectProbingParserPort *zero_port;
1135
1136 zero_port = curr_pp->port;
1137 while (zero_port != NULL && zero_port->port != 0) {
1138 zero_port = zero_port->next;
1139 }
1140 if (zero_port != NULL) {
1141 AppLayerProtoDetectProbingParserElement *zero_pe;
1142
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;
1152 }
1153
1154 AppLayerProtoDetectProbingParserElement *dup_pe =
1155 AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1156 AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1157 curr_port->alproto_mask |= dup_pe->alproto_mask;
1158 }
1159
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;
1169 }
1170
1171 AppLayerProtoDetectProbingParserElement *dup_pe =
1172 AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1173 AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1174 curr_port->alproto_mask |= dup_pe->alproto_mask;
1175 }
1176 } /* if (zero_port != NULL) */
1177 } /* if (curr_port == NULL) */
1178
1179 /* insert the pe_pp */
1180 AppLayerProtoDetectProbingParserElement *curr_pe;
1181 if (direction & STREAM_TOSERVER)
1182 curr_pe = curr_port->dp;
1183 else
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);
1194 goto error;
1195 }
1196 curr_pe = curr_pe->next;
1197 }
1198 /* Get a new parser element */
1199 AppLayerProtoDetectProbingParserElement *new_pe =
1200 AppLayerProtoDetectProbingParserElementCreate(alproto,
1201 curr_port->port,
1202 min_depth, max_depth);
1203 if (new_pe == NULL)
1204 goto error;
1205 curr_pe = new_pe;
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;
1217 }
1218 curr_port->alproto_mask |= new_pe->alproto_mask;
1219 head_pe = &curr_port->dp;
1220 } else {
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;
1230 }
1231 curr_port->alproto_mask |= new_pe->alproto_mask;
1232 head_pe = &curr_port->sp;
1233 }
1234 AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1235
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;
1247 }
1248 AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1249 AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1250 temp_port->alproto_mask |= curr_pe->alproto_mask;
1251 } else {
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;
1259 }
1260 AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1261 AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1262 temp_port->alproto_mask |= curr_pe->alproto_mask;
1263 }
1264 temp_port = temp_port->next;
1265 } /* while */
1266 } /* if */
1267
1268 error:
1269 SCReturn;
1270 }
1271
1272 /***** Static Internal Calls: PM registration *****/
1273
1274 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1275 uint8_t *ipprotos)
1276 {
1277 SCEnter();
1278
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];
1283
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);
1288 }
1289 }
1290 }
1291
1292 SCReturn;
1293 }
1294
1295 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1296 {
1297 SCEnter();
1298
1299 typedef struct TempContainer_ {
1300 PatIntId id;
1301 uint16_t content_len;
1302 uint8_t *content;
1303 } TempContainer;
1304
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;
1315 int ret = 0;
1316
1317 if (ctx->head == NULL)
1318 goto end;
1319
1320 for (s = ctx->head; s != NULL; s = s->next) {
1321 struct_total_size += sizeof(TempContainer);
1322 content_total_size += s->cd->content_len;
1323 ctx->max_sig_id++;
1324 }
1325
1326 ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1327 if (unlikely(ahb == NULL))
1328 goto error;
1329
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;
1336
1337 for (; tcdup != struct_offset; tcdup++) {
1338 if (tcdup->content_len != content_len ||
1339 SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1340 {
1341 continue;
1342 }
1343 break;
1344 }
1345
1346 if (tcdup != struct_offset) {
1347 s->cd->id = tcdup->id;
1348 continue;
1349 }
1350
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;
1357
1358 struct_offset++;
1359 }
1360
1361 ctx->max_pat_id = max_id;
1362
1363 goto end;
1364 error:
1365 ret = -1;
1366 end:
1367 if (ahb != NULL)
1368 SCFree(ahb);
1369 SCReturnInt(ret);
1370 }
1371
1372 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1373 {
1374 SCEnter();
1375
1376 int ret = 0;
1377 AppLayerProtoDetectPMSignature *s, *next_s;
1378 int mpm_ret;
1379 SigIntId id = 0;
1380
1381 ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1382 if (ctx->map == NULL)
1383 goto error;
1384 memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1385
1386 /* add an array indexed by rule id to look up the sig */
1387 for (s = ctx->head; s != NULL; ) {
1388 next_s = s->next;
1389 s->id = id++;
1390 SCLogDebug("s->id %u offset %u depth %u",
1391 s->id, s->cd->offset, s->cd->depth);
1392
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);
1397 if (mpm_ret < 0)
1398 goto error;
1399 } else {
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);
1403 if (mpm_ret < 0)
1404 goto error;
1405 }
1406
1407 ctx->map[s->id] = s;
1408 s->next = NULL;
1409 s = next_s;
1410 }
1411 ctx->head = NULL;
1412
1413 goto end;
1414 error:
1415 ret = -1;
1416 end:
1417 SCReturnInt(ret);
1418 }
1419
1420 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1421 {
1422 SCEnter();
1423
1424 int ret = 0;
1425 MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1426
1427 if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1428 goto error;
1429
1430 goto end;
1431 error:
1432 ret = -1;
1433 end:
1434 SCReturnInt(ret);
1435 }
1436
1437 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1438 {
1439 SCEnter();
1440 if (sig == NULL)
1441 SCReturn;
1442 if (sig->cd)
1443 DetectContentFree(NULL, sig->cd);
1444 SCFree(sig);
1445 SCReturn;
1446 }
1447
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)
1452 {
1453 SCEnter();
1454
1455 AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1456 if (unlikely(s == NULL))
1457 SCReturnInt(-1);
1458
1459 s->alproto = alproto;
1460 s->direction = direction;
1461 s->cd = cd;
1462 s->PPFunc = PPFunc;
1463 s->pp_min_depth = pp_min_depth;
1464 s->pp_max_depth = pp_max_depth;
1465
1466 /* prepend to the list */
1467 s->next = ctx->head;
1468 ctx->head = s;
1469
1470 SCReturnInt(0);
1471 }
1472
1473 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1474 const char *pattern,
1475 uint16_t depth, uint16_t offset,
1476 uint8_t direction,
1477 uint8_t is_cs,
1478 ProbingParserFPtr PPFunc,
1479 uint16_t pp_min_depth, uint16_t pp_max_depth)
1480 {
1481 SCEnter();
1482
1483 AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1484 AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1485 int ret = 0;
1486
1487 DetectContentData *cd = DetectContentParseEncloseQuotes(
1488 alpd_ctx.spm_global_thread_ctx, pattern);
1489 if (cd == NULL)
1490 goto error;
1491 cd->depth = depth;
1492 cd->offset = offset;
1493 if (!is_cs) {
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) {
1499 goto error;
1500 }
1501 cd->flags |= DETECT_CONTENT_NOCASE;
1502 }
1503 if (depth < cd->content_len)
1504 goto error;
1505
1506 if (direction & STREAM_TOSERVER)
1507 ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1508 else
1509 ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1510
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;
1515
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);
1519
1520 goto end;
1521 error:
1522 DetectContentFree(NULL, cd);
1523 ret = -1;
1524 end:
1525 SCReturnInt(ret);
1526 }
1527
1528 /***** Protocol Retrieval *****/
1529
1530 AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f,
1531 const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t flags, bool *reverse_flow)
1532 {
1533 SCEnter();
1534 SCLogDebug("buflen %u for %s direction", buflen,
1535 (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1536
1537 AppProto alproto = ALPROTO_UNKNOWN;
1538 AppProto pm_alproto = ALPROTO_UNKNOWN;
1539
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];
1547
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);
1554 }
1555 }
1556
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))
1560 goto end;
1561
1562 pm_alproto = alproto;
1563
1564 /* fall through */
1565 }
1566 }
1567
1568 if (!FLOW_IS_PP_DONE(f, flags)) {
1569 bool rflow = false;
1570 alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1571 if (AppProtoIsValid(alproto)) {
1572 if (rflow) {
1573 *reverse_flow = true;
1574 }
1575 goto end;
1576 }
1577 }
1578
1579 /* Look if flow can be found in expectation list */
1580 if (!FLOW_IS_PE_DONE(f, flags)) {
1581 alproto = AppLayerProtoDetectPEGetProto(f, ipproto, flags);
1582 }
1583
1584 end:
1585 if (!AppProtoIsValid(alproto))
1586 alproto = pm_alproto;
1587
1588 SCReturnUInt(alproto);
1589 }
1590
1591 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1592 {
1593 SCEnter();
1594
1595 AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1596
1597 if (pp == NULL)
1598 goto end;
1599
1600 while (pp != NULL) {
1601 tmp_pp = pp->next;
1602 AppLayerProtoDetectProbingParserFree(pp);
1603 pp = tmp_pp;
1604 }
1605
1606 end:
1607 SCReturn;
1608 }
1609
1610 static void AppLayerProtoDetectFreeAliases(void)
1611 {
1612 SCEnter();
1613
1614 AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1615 if (cur_alias == NULL)
1616 goto end;
1617
1618 AppLayerProtoDetectAliases *next_alias = NULL;
1619 while (cur_alias != NULL) {
1620 next_alias = cur_alias->next;
1621 SCFree(cur_alias);
1622 cur_alias = next_alias;
1623 }
1624
1625 alpda_ctx = NULL;
1626
1627 end:
1628 SCReturn;
1629 }
1630
1631 /***** State Preparation *****/
1632
1633 int AppLayerProtoDetectPrepareState(void)
1634 {
1635 SCEnter();
1636
1637 AppLayerProtoDetectPMCtx *ctx_pm;
1638 int i, j;
1639 int ret = 0;
1640
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];
1644
1645 if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1646 goto error;
1647
1648 if (ctx_pm->max_sig_id == 0)
1649 continue;
1650
1651 if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1652 goto error;
1653 if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1654 goto error;
1655 }
1656 }
1657
1658 #ifdef DEBUG
1659 if (SCLogDebugEnabled()) {
1660 AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1661 }
1662 #endif
1663
1664 goto end;
1665 error:
1666 ret = -1;
1667 end:
1668 SCReturnInt(ret);
1669 }
1670
1671 /***** PP registration *****/
1672
1673 /** \brief register parser at a port
1674 *
1675 * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1676 */
1677 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1678 const char *portstr,
1679 AppProto alproto,
1680 uint16_t min_depth, uint16_t max_depth,
1681 uint8_t direction,
1682 ProbingParserFPtr ProbingParser1,
1683 ProbingParserFPtr ProbingParser2)
1684 {
1685 SCEnter();
1686
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)
1693 port++;
1694 for ( ; port <= temp_dp->port2; port++) {
1695 AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1696 ipproto,
1697 port,
1698 alproto,
1699 min_depth, max_depth,
1700 direction,
1701 ProbingParser1,
1702 ProbingParser2);
1703 }
1704 temp_dp = temp_dp->next;
1705 }
1706 DetectPortCleanupList(NULL,head);
1707
1708 SCReturn;
1709 }
1710
1711 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1712 uint8_t ipproto,
1713 const char *alproto_name,
1714 AppProto alproto,
1715 uint16_t min_depth, uint16_t max_depth,
1716 ProbingParserFPtr ProbingParserTs,
1717 ProbingParserFPtr ProbingParserTc)
1718 {
1719 SCEnter();
1720
1721 char param[100];
1722 int r;
1723 ConfNode *node;
1724 ConfNode *port_node = NULL;
1725 int config = 0;
1726
1727 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1728 alproto_name, ".detection-ports");
1729 if (r < 0) {
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.");
1733 }
1734 node = ConfGetNode(param);
1735 if (node == NULL) {
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");
1739 if (r < 0) {
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.");
1743 }
1744 node = ConfGetNode(param);
1745 if (node == NULL)
1746 goto end;
1747 }
1748
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");
1753
1754 if (port_node != NULL && port_node->val != NULL) {
1755 AppLayerProtoDetectPPRegister(ipproto,
1756 port_node->val,
1757 alproto,
1758 min_depth, max_depth,
1759 STREAM_TOSERVER, /* to indicate dp */
1760 ProbingParserTs, ProbingParserTc);
1761 }
1762
1763 /* detect by source port of flow */
1764 port_node = ConfNodeLookupChild(node, "sp");
1765 if (port_node == NULL)
1766 port_node = ConfNodeLookupChild(node, "toclient");
1767
1768 if (port_node != NULL && port_node->val != NULL) {
1769 AppLayerProtoDetectPPRegister(ipproto,
1770 port_node->val,
1771 alproto,
1772 min_depth, max_depth,
1773 STREAM_TOCLIENT, /* to indicate sp */
1774 ProbingParserTc, ProbingParserTs);
1775
1776 }
1777
1778 config = 1;
1779 end:
1780 SCReturnInt(config);
1781 }
1782
1783 /***** PM registration *****/
1784
1785 int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto,
1786 const char *pattern,
1787 uint16_t depth, uint16_t offset,
1788 uint8_t direction)
1789 {
1790 SCEnter();
1791 int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1792 pattern, depth, offset,
1793 direction, 1 /* case-sensitive */,
1794 NULL, 0, 0);
1795 SCReturnInt(r);
1796 }
1797
1798 int AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto, AppProto alproto,
1799 const char *pattern, uint16_t depth, uint16_t offset,
1800 uint8_t direction,
1801 ProbingParserFPtr PPFunc,
1802 uint16_t pp_min_depth, uint16_t pp_max_depth)
1803 {
1804 SCEnter();
1805 int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1806 pattern, depth, offset,
1807 direction, 1 /* case-sensitive */,
1808 PPFunc, pp_min_depth, pp_max_depth);
1809 SCReturnInt(r);
1810 }
1811
1812 int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto,
1813 const char *pattern,
1814 uint16_t depth, uint16_t offset,
1815 uint8_t direction)
1816 {
1817 SCEnter();
1818 int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1819 pattern, depth, offset,
1820 direction, 0 /* !case-sensitive */,
1821 NULL, 0, 0);
1822 SCReturnInt(r);
1823 }
1824
1825 /***** Setup/General Registration *****/
1826
1827 int AppLayerProtoDetectSetup(void)
1828 {
1829 SCEnter();
1830
1831 int i, j;
1832
1833 memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1834
1835 uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1836 uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1837
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.");
1841 }
1842
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);
1846 }
1847 }
1848
1849 AppLayerExpectationSetup();
1850
1851 SCReturnInt(0);
1852 }
1853
1854 /**
1855 * \todo incomplete. Need more work.
1856 */
1857 int AppLayerProtoDetectDeSetup(void)
1858 {
1859 SCEnter();
1860
1861 int ipproto_map = 0;
1862 int dir = 0;
1863 PatIntId id = 0;
1864 AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1865 AppLayerProtoDetectPMSignature *sig = NULL;
1866
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);
1874 }
1875 SCFree(pm_ctx->map);
1876 pm_ctx->map = NULL;
1877 }
1878 }
1879
1880 SpmDestroyGlobalThreadCtx(alpd_ctx.spm_global_thread_ctx);
1881
1882 AppLayerProtoDetectFreeAliases();
1883
1884 AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1885
1886 SCReturnInt(0);
1887 }
1888
1889 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1890 {
1891 SCEnter();
1892
1893 if (alpd_ctx.alproto_names[alproto] == NULL)
1894 alpd_ctx.alproto_names[alproto] = alproto_name;
1895
1896 SCReturn;
1897 }
1898
1899 void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
1900 {
1901 SCEnter();
1902
1903 AppLayerProtoDetectAliases *new_alias = SCMalloc(sizeof(AppLayerProtoDetectAliases));
1904 if (unlikely(new_alias == NULL)) {
1905 exit(EXIT_FAILURE);
1906 }
1907
1908 new_alias->proto_name = proto_name;
1909 new_alias->proto_alias = proto_alias;
1910 new_alias->next = NULL;
1911
1912 if (alpda_ctx == NULL) {
1913 alpda_ctx = new_alias;
1914 } else {
1915 AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1916 while (cur_alias->next != NULL) {
1917 cur_alias = cur_alias->next;
1918 }
1919 cur_alias->next = new_alias;
1920 }
1921
1922 SCReturn;
1923 }
1924
1925 /** \brief request applayer to wrap up this protocol and rerun protocol
1926 * detection.
1927 *
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.
1931 *
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.
1938 */
1939 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1940 {
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;
1949 }
1950 if (f->alproto_tc == ALPROTO_UNKNOWN) {
1951 f->alproto_tc = f->alproto;
1952 }
1953 }
1954
1955 /** \brief request applayer to wrap up this protocol and rerun protocol
1956 * detection with expectation of TLS. Used by STARTTLS.
1957 *
1958 * Sets detection port to 443 to make port based TLS detection work for
1959 * SMTP, FTP etc as well.
1960 *
1961 * \param f flow to act on
1962 */
1963 void AppLayerRequestProtocolTLSUpgrade(Flow *f)
1964 {
1965 AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
1966 }
1967
1968 void AppLayerProtoDetectReset(Flow *f)
1969 {
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;
1978
1979 // Does not free the structures for the parser
1980 // keeps f->alstate for new state creation
1981 f->alparser = NULL;
1982 f->alproto = ALPROTO_UNKNOWN;
1983 f->alproto_ts = ALPROTO_UNKNOWN;
1984 f->alproto_tc = ALPROTO_UNKNOWN;
1985 }
1986
1987 int AppLayerProtoDetectConfProtoDetectionEnabledDefault(
1988 const char *ipproto, const char *alproto, bool default_enabled)
1989 {
1990 SCEnter();
1991
1992 BUG_ON(ipproto == NULL || alproto == NULL);
1993
1994 int enabled = 1;
1995 char param[100];
1996 ConfNode *node;
1997 int r;
1998
1999 if (RunmodeIsUnittests())
2000 goto enabled;
2001
2002 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
2003 alproto, ".enabled");
2004 if (r < 0) {
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.");
2008 }
2009
2010 node = ConfGetNode(param);
2011 if (node == NULL) {
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");
2015 if (r < 0) {
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.");
2019 }
2020
2021 node = ConfGetNode(param);
2022 if (node == NULL) {
2023 SCLogDebug("Entry for %s not found.", param);
2024 if (default_enabled) {
2025 goto enabled;
2026 } else {
2027 goto disabled;
2028 }
2029 }
2030 }
2031
2032 if (node->val) {
2033 if (ConfValIsTrue(node->val)) {
2034 goto enabled;
2035 } else if (ConfValIsFalse(node->val)) {
2036 goto disabled;
2037 } else if (strcasecmp(node->val, "detection-only") == 0) {
2038 goto enabled;
2039 }
2040 }
2041
2042 /* Invalid or null value. */
2043 SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
2044 exit(EXIT_FAILURE);
2045
2046 disabled:
2047 enabled = 0;
2048 enabled:
2049 SCReturnInt(enabled);
2050 }
2051
2052 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
2053 {
2054 return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
2055 }
2056
2057 AppLayerProtoDetectThreadCtx *AppLayerProtoDetectGetCtxThread(void)
2058 {
2059 SCEnter();
2060
2061 AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
2062 MpmCtx *mpm_ctx;
2063 MpmThreadCtx *mpm_tctx;
2064 int i, j;
2065 PatIntId max_pat_id = 0;
2066
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;
2071
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)
2074 {
2075 max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2076 }
2077 }
2078 }
2079
2080 alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
2081 if (alpd_tctx == NULL)
2082 goto error;
2083 memset(alpd_tctx, 0, sizeof(*alpd_tctx));
2084
2085 /* Get the max pat id for all the mpm ctxs. */
2086 if (PmqSetup(&alpd_tctx->pmq) < 0)
2087 goto error;
2088
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);
2094 }
2095 }
2096
2097 alpd_tctx->spm_thread_ctx = SpmMakeThreadCtx(alpd_ctx.spm_global_thread_ctx);
2098 if (alpd_tctx->spm_thread_ctx == NULL) {
2099 goto error;
2100 }
2101
2102 goto end;
2103 error:
2104 if (alpd_tctx != NULL)
2105 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2106 alpd_tctx = NULL;
2107 end:
2108 SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2109 }
2110
2111 void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
2112 {
2113 SCEnter();
2114
2115 MpmCtx *mpm_ctx;
2116 MpmThreadCtx *mpm_tctx;
2117 int ipproto_map, dir;
2118
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);
2124 }
2125 }
2126 PmqFree(&alpd_tctx->pmq);
2127 if (alpd_tctx->spm_thread_ctx != NULL) {
2128 SpmDestroyThreadCtx(alpd_tctx->spm_thread_ctx);
2129 }
2130 SCFree(alpd_tctx);
2131
2132 SCReturn;
2133 }
2134
2135 /***** Utility *****/
2136
2137 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2138 {
2139 SCEnter();
2140
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);
2145 } else {
2146 AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2147 AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2148 AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2149 }
2150
2151 SCReturn;
2152 }
2153
2154 AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
2155 {
2156 SCEnter();
2157
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;
2162 }
2163
2164 cur_alias = cur_alias->next;
2165 }
2166
2167 AppProto a;
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");
2173 }
2174 }
2175
2176 SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2177 }
2178
2179 const char *AppLayerProtoDetectGetProtoName(AppProto alproto)
2180 {
2181 return alpd_ctx.alproto_names[alproto];
2182 }
2183
2184 void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
2185 {
2186 SCEnter();
2187
2188 memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2189
2190 int alproto;
2191
2192 for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2193 if (alpd_ctx.alproto_names[alproto] != NULL)
2194 alprotos[alproto] = 1;
2195 }
2196
2197 SCReturn;
2198 }
2199
2200 uint8_t expectation_proto[ALPROTO_MAX];
2201
2202 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2203 uint8_t *ipprotos)
2204 {
2205 if (expectation_proto[alproto] == IPPROTO_TCP) {
2206 ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2207 }
2208 if (expectation_proto[alproto] == IPPROTO_UDP) {
2209 ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2210 }
2211 }
2212
2213 void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
2214 {
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");
2219 }
2220 }
2221 expectation_proto[alproto] = proto;
2222 }
2223
2224 /***** Unittests *****/
2225
2226 #ifdef UNITTESTS
2227
2228 #include "app-layer-htp.h"
2229
2230 static AppLayerProtoDetectCtx alpd_ctx_ut;
2231
2232 void AppLayerProtoDetectUnittestCtxBackup(void)
2233 {
2234 SCEnter();
2235 alpd_ctx_ut = alpd_ctx;
2236 memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2237 SCReturn;
2238 }
2239
2240 void AppLayerProtoDetectUnittestCtxRestore(void)
2241 {
2242 SCEnter();
2243 alpd_ctx = alpd_ctx_ut;
2244 memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2245 SCReturn;
2246 }
2247
2248 static int AppLayerProtoDetectTest01(void)
2249 {
2250 AppLayerProtoDetectUnittestCtxBackup();
2251 AppLayerProtoDetectSetup();
2252
2253 const char *buf = "HTTP";
2254 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2255 buf = "GET";
2256 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2257
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);
2261
2262 AppLayerProtoDetectDeSetup();
2263 AppLayerProtoDetectUnittestCtxRestore();
2264 PASS;
2265 }
2266
2267 static int AppLayerProtoDetectTest02(void)
2268 {
2269 AppLayerProtoDetectUnittestCtxBackup();
2270 AppLayerProtoDetectSetup();
2271
2272 const char *buf = "HTTP";
2273 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2274 buf = "ftp";
2275 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2276
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);
2280
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);
2283
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);
2286
2287 AppLayerProtoDetectDeSetup();
2288 AppLayerProtoDetectUnittestCtxRestore();
2289 PASS;
2290 }
2291
2292 static int AppLayerProtoDetectTest03(void)
2293 {
2294 AppLayerProtoDetectUnittestCtxBackup();
2295 AppLayerProtoDetectSetup();
2296
2297 uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2298 AppProto pm_results[ALPROTO_MAX];
2299 memset(pm_results, 0, sizeof(pm_results));
2300 Flow f;
2301 memset(&f, 0x00, sizeof(f));
2302 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2303
2304
2305 const char *buf = "HTTP";
2306 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2307 buf = "220 ";
2308 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2309
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);
2315
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);
2322
2323 bool rflow = false;
2324 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2325 &f, l7data, sizeof(l7data),
2326 STREAM_TOCLIENT,
2327 pm_results, &rflow);
2328 FAIL_IF(cnt != 1);
2329 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2330
2331 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2332 AppLayerProtoDetectDeSetup();
2333 AppLayerProtoDetectUnittestCtxRestore();
2334 PASS;
2335 }
2336
2337 static int AppLayerProtoDetectTest04(void)
2338 {
2339 AppLayerProtoDetectUnittestCtxBackup();
2340 AppLayerProtoDetectSetup();
2341
2342 uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2343 Flow f;
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);
2348
2349 const char *buf = "200 ";
2350 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2351
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);
2357
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);
2363
2364 bool rdir = false;
2365 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2366 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2367 pm_results, &rdir);
2368 FAIL_IF(cnt != 1);
2369 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2370
2371 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2372 AppLayerProtoDetectDeSetup();
2373 AppLayerProtoDetectUnittestCtxRestore();
2374 PASS;
2375 }
2376
2377 static int AppLayerProtoDetectTest05(void)
2378 {
2379 AppLayerProtoDetectUnittestCtxBackup();
2380 AppLayerProtoDetectSetup();
2381
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));
2385 Flow f;
2386 memset(&f, 0x00, sizeof(f));
2387 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2388
2389 const char *buf = "HTTP";
2390 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2391 buf = "220 ";
2392 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2393
2394 AppLayerProtoDetectPrepareState();
2395 /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2396 * it sets internal structures which depends on the above function. */
2397 AppLayerProtoDetectThreadCtx *alpd_tctx = AppLayerProtoDetectGetCtxThread();
2398 FAIL_IF_NULL(alpd_tctx);
2399
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);
2406
2407 bool rdir = false;
2408 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2409 &f, l7data, sizeof(l7data),
2410 STREAM_TOCLIENT,
2411 pm_results, &rdir);
2412 FAIL_IF(cnt != 1);
2413 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2414
2415 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2416 AppLayerProtoDetectDeSetup();
2417 AppLayerProtoDetectUnittestCtxRestore();
2418 PASS;
2419 }
2420
2421 static int AppLayerProtoDetectTest06(void)
2422 {
2423 AppLayerProtoDetectUnittestCtxBackup();
2424 AppLayerProtoDetectSetup();
2425
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));
2429 Flow f;
2430 memset(&f, 0x00, sizeof(f));
2431 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2432
2433 const char *buf = "HTTP";
2434 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2435 buf = "220 ";
2436 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2437
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);
2443
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);
2450
2451 bool rdir = false;
2452 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2453 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2454 pm_results, &rdir);
2455 FAIL_IF(cnt != 1);
2456 FAIL_IF(pm_results[0] != ALPROTO_FTP);
2457
2458 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2459 AppLayerProtoDetectDeSetup();
2460 AppLayerProtoDetectUnittestCtxRestore();
2461 PASS;
2462 }
2463
2464 static int AppLayerProtoDetectTest07(void)
2465 {
2466 AppLayerProtoDetectUnittestCtxBackup();
2467 AppLayerProtoDetectSetup();
2468
2469 uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2470 Flow f;
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));
2475
2476 const char *buf = "HTTP";
2477 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2478
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();
2483
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);
2489
2490 bool rdir = false;
2491 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2492 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2493 pm_results, &rdir);
2494 FAIL_IF(cnt != 0);
2495
2496 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2497 AppLayerProtoDetectDeSetup();
2498 AppLayerProtoDetectUnittestCtxRestore();
2499 PASS;
2500 }
2501
2502 static int AppLayerProtoDetectTest08(void)
2503 {
2504 AppLayerProtoDetectUnittestCtxBackup();
2505 AppLayerProtoDetectSetup();
2506
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,
2525 0x00
2526 };
2527 AppProto pm_results[ALPROTO_MAX];
2528 memset(pm_results, 0, sizeof(pm_results));
2529 Flow f;
2530 memset(&f, 0x00, sizeof(f));
2531 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2532
2533 const char *buf = "|ff|SMB";
2534 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2535
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);
2541
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);
2547
2548 bool rdir = false;
2549 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2550 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2551 pm_results, &rdir);
2552 FAIL_IF(cnt != 1);
2553 FAIL_IF(pm_results[0] != ALPROTO_SMB);
2554
2555 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2556 AppLayerProtoDetectDeSetup();
2557 AppLayerProtoDetectUnittestCtxRestore();
2558 PASS;
2559 }
2560
2561 static int AppLayerProtoDetectTest09(void)
2562 {
2563 AppLayerProtoDetectUnittestCtxBackup();
2564 AppLayerProtoDetectSetup();
2565
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,
2580 0x00, 0x02, 0x02
2581 };
2582 AppProto pm_results[ALPROTO_MAX];
2583 memset(pm_results, 0, sizeof(pm_results));
2584 Flow f;
2585 memset(&f, 0x00, sizeof(f));
2586 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2587
2588 const char *buf = "|fe|SMB";
2589 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2590
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);
2596
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);
2602
2603 bool rdir = false;
2604 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2605 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2606 pm_results, &rdir);
2607 FAIL_IF(cnt != 1);
2608 FAIL_IF(pm_results[0] != ALPROTO_SMB);
2609
2610 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2611 AppLayerProtoDetectDeSetup();
2612 AppLayerProtoDetectUnittestCtxRestore();
2613 PASS;
2614 }
2615
2616 static int AppLayerProtoDetectTest10(void)
2617 {
2618 AppLayerProtoDetectUnittestCtxBackup();
2619 AppLayerProtoDetectSetup();
2620
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
2631 };
2632 AppProto pm_results[ALPROTO_MAX];
2633 memset(pm_results, 0, sizeof(pm_results));
2634 Flow f;
2635 memset(&f, 0x00, sizeof(f));
2636 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2637
2638 const char *buf = "|05 00|";
2639 AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2640
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);
2646
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);
2652
2653 bool rdir = false;
2654 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2655 &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2656 pm_results, &rdir);
2657 FAIL_IF(cnt != 1);
2658 FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2659
2660 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2661 AppLayerProtoDetectDeSetup();
2662 AppLayerProtoDetectUnittestCtxRestore();
2663 PASS;
2664 }
2665
2666 /**
2667 * \test Why we still get http for connect... obviously because
2668 * we also match on the reply, duh
2669 */
2670 static int AppLayerProtoDetectTest11(void)
2671 {
2672 AppLayerProtoDetectUnittestCtxBackup();
2673 AppLayerProtoDetectSetup();
2674
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));
2679 Flow f;
2680 memset(&f, 0x00, sizeof(f));
2681 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2682
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);
2699
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);
2705
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);
2710
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);
2719
2720 bool rdir = false;
2721 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2722 &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2723 pm_results, &rdir);
2724 FAIL_IF(cnt != 1);
2725 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2726
2727 memset(pm_results, 0, sizeof(pm_results));
2728 cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2729 &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2730 pm_results, &rdir);
2731 FAIL_IF(cnt != 1);
2732 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2733
2734 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2735 AppLayerProtoDetectDeSetup();
2736 AppLayerProtoDetectUnittestCtxRestore();
2737 PASS;
2738 }
2739
2740 /**
2741 * \test AlpProtoSignature test
2742 */
2743 static int AppLayerProtoDetectTest12(void)
2744 {
2745 AppLayerProtoDetectUnittestCtxBackup();
2746 AppLayerProtoDetectSetup();
2747
2748 int r = 0;
2749
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)
2754 {
2755 printf("failure 1\n");
2756 goto end;
2757 }
2758
2759 AppLayerProtoDetectPrepareState();
2760 if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2761 printf("failure 2\n");
2762 goto end;
2763 }
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)
2766 {
2767 printf("failure 3\n");
2768 goto end;
2769 }
2770 if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2771 printf("failure 4\n");
2772 goto end;
2773 }
2774 if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2775 printf("failure 5\n");
2776 goto end;
2777 }
2778 if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2779 printf("failure 6\n");
2780 goto end;
2781 }
2782
2783 r = 1;
2784
2785 end:
2786 AppLayerProtoDetectDeSetup();
2787 AppLayerProtoDetectUnittestCtxRestore();
2788 return r;
2789 }
2790
2791 /**
2792 * \test What about if we add some sigs only for udp but call for tcp?
2793 * It should not detect any proto
2794 */
2795 static int AppLayerProtoDetectTest13(void)
2796 {
2797 AppLayerProtoDetectUnittestCtxBackup();
2798 AppLayerProtoDetectSetup();
2799
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];
2803
2804 Flow f;
2805 memset(&f, 0x00, sizeof(f));
2806 f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2807
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);
2824
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();
2829
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);
2832
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);
2841
2842 memset(pm_results, 0, sizeof(pm_results));
2843 bool rdir = false;
2844 uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2845 &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2846 pm_results, &rdir);
2847 FAIL_IF(cnt != 0);
2848
2849 memset(pm_results, 0, sizeof(pm_results));
2850 cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2851 &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2852 pm_results, &rdir);
2853 FAIL_IF(cnt != 0);
2854
2855 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2856 AppLayerProtoDetectDeSetup();
2857 AppLayerProtoDetectUnittestCtxRestore();
2858 PASS;
2859 }
2860
2861 /**
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.
2865 */
2866 static int AppLayerProtoDetectTest14(void)
2867 {
2868 AppLayerProtoDetectUnittestCtxBackup();
2869 AppLayerProtoDetectSetup();
2870
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];
2874 uint32_t cnt;
2875 Flow f;
2876 memset(&f, 0x00, sizeof(f));
2877 f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2878
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);
2895
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);
2901
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);
2904
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);
2913
2914 memset(pm_results, 0, sizeof(pm_results));
2915 bool rdir = false;
2916 cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2917 &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2918 pm_results, &rdir);
2919 FAIL_IF(cnt != 1);
2920 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2921
2922 memset(pm_results, 0, sizeof(pm_results));
2923 cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2924 &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2925 pm_results, &rdir);
2926 FAIL_IF(cnt != 1);
2927 FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2928
2929 AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
2930 AppLayerProtoDetectDeSetup();
2931 AppLayerProtoDetectUnittestCtxRestore();
2932 PASS;
2933 }
2934
2935 typedef struct AppLayerProtoDetectPPTestDataElement_ {
2936 const char *alproto_name;
2937 AppProto alproto;
2938 uint16_t port;
2939 uint32_t alproto_mask;
2940 uint32_t min_depth;
2941 uint32_t max_depth;
2942 } AppLayerProtoDetectPPTestDataElement;
2943
2944 typedef struct AppLayerProtoDetectPPTestDataPort_ {
2945 uint16_t port;
2946 uint32_t alproto_mask;
2947 uint16_t dp_max_depth;
2948 uint16_t sp_max_depth;
2949
2950 AppLayerProtoDetectPPTestDataElement *toserver_element;
2951 AppLayerProtoDetectPPTestDataElement *toclient_element;
2952 int ts_no_of_element;
2953 int tc_no_of_element;
2954 } AppLayerProtoDetectPPTestDataPort;
2955
2956
2957 typedef struct AppLayerProtoDetectPPTestDataIPProto_ {
2958 uint8_t ipproto;
2959
2960 AppLayerProtoDetectPPTestDataPort *port;
2961 int no_of_port;
2962 } AppLayerProtoDetectPPTestDataIPProto;
2963
2964 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2965 AppLayerProtoDetectPPTestDataIPProto *ip_proto,
2966 int no_of_ip_proto)
2967 {
2968 int result = 0;
2969 int i = -1, j = -1 , k = -1;
2970 #ifdef DEBUG
2971 int dir = 0;
2972 #endif
2973 for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2974 if (pp->ipproto != ip_proto[i].ipproto)
2975 goto end;
2976
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)
2980 goto end;
2981 if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2982 goto end;
2983 if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2984 goto end;
2985 if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2986 goto end;
2987 if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2988 goto end;
2989
2990 AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2991 #ifdef DEBUG
2992 dir = 0;
2993 #endif
2994 for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2995 j++, pp_element = pp_element->next) {
2996
2997 if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2998 goto end;
2999 }
3000 if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
3001 goto end;
3002 }
3003 if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
3004 goto end;
3005 }
3006 if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
3007 goto end;
3008 }
3009 if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
3010 goto end;
3011 }
3012 } /* for */
3013 if (pp_element != NULL)
3014 goto end;
3015
3016 pp_element = pp_port->sp;
3017 #ifdef DEBUG
3018 dir = 1;
3019 #endif
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) {
3022 goto end;
3023 }
3024 if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
3025 goto end;
3026 }
3027 if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
3028 goto end;
3029 }
3030 if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
3031 goto end;
3032 }
3033 if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
3034 goto end;
3035 }
3036 } /* for */
3037 if (pp_element != NULL)
3038 goto end;
3039 }
3040 if (pp_port != NULL)
3041 goto end;
3042 }
3043 if (pp != NULL)
3044 goto end;
3045
3046 result = 1;
3047 end:
3048 #ifdef DEBUG
3049 printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
3050 #endif
3051 return result;
3052 }
3053
3054 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
3055 const uint8_t *input,
3056 uint32_t input_len, uint8_t *rdir)
3057 {
3058 return 0;
3059 }
3060
3061 static int AppLayerProtoDetectTest15(void)
3062 {
3063 AppLayerProtoDetectUnittestCtxBackup();
3064 AppLayerProtoDetectSetup();
3065
3066 int result = 0;
3067
3068 AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
3069 ProbingParserDummyForTesting, NULL);
3070 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3071 "80",
3072 ALPROTO_SMB,
3073 5, 6,
3074 STREAM_TOSERVER,
3075 ProbingParserDummyForTesting, NULL);
3076 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3077 "80",
3078 ALPROTO_FTP,
3079 7, 10,
3080 STREAM_TOSERVER,
3081 ProbingParserDummyForTesting, NULL);
3082
3083 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3084 "81",
3085 ALPROTO_DCERPC,
3086 9, 10,
3087 STREAM_TOSERVER,
3088 ProbingParserDummyForTesting, NULL);
3089 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3090 "81",
3091 ALPROTO_FTP,
3092 7, 15,
3093 STREAM_TOSERVER,
3094 ProbingParserDummyForTesting, NULL);
3095 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3096 "0",
3097 ALPROTO_SMTP,
3098 12, 0,
3099 STREAM_TOSERVER,
3100 ProbingParserDummyForTesting, NULL);
3101 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3102 "0",
3103 ALPROTO_TLS,
3104 12, 18,
3105 STREAM_TOSERVER,
3106 ProbingParserDummyForTesting, NULL);
3107
3108 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3109 "85",
3110 ALPROTO_DCERPC,
3111 9, 10,
3112 STREAM_TOSERVER,
3113 ProbingParserDummyForTesting, NULL);
3114 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3115 "85",
3116 ALPROTO_FTP,
3117 7, 15,
3118 STREAM_TOSERVER,
3119 ProbingParserDummyForTesting, NULL);
3120 result = 1;
3121
3122 AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3123 "85",
3124 ALPROTO_IMAP,
3125 12, 23,
3126 STREAM_TOSERVER,
3127 ProbingParserDummyForTesting, NULL);
3128
3129 /* toclient */
3130 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3131 "0",
3132 ALPROTO_JABBER,
3133 12, 23,
3134 STREAM_TOCLIENT,
3135 ProbingParserDummyForTesting, NULL);
3136 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3137 "0",
3138 ALPROTO_IRC,
3139 12, 14,
3140 STREAM_TOCLIENT,
3141 ProbingParserDummyForTesting, NULL);
3142
3143 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3144 "85",
3145 ALPROTO_DCERPC,
3146 9, 10,
3147 STREAM_TOCLIENT,
3148 ProbingParserDummyForTesting, NULL);
3149 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3150 "81",
3151 ALPROTO_FTP,
3152 7, 15,
3153 STREAM_TOCLIENT,
3154 ProbingParserDummyForTesting, NULL);
3155 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3156 "0",
3157 ALPROTO_TLS,
3158 12, 18,
3159 STREAM_TOCLIENT,
3160 ProbingParserDummyForTesting, NULL);
3161 AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3162 ProbingParserDummyForTesting, NULL);
3163 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3164 "81",
3165 ALPROTO_DCERPC,
3166 9, 10,
3167 STREAM_TOCLIENT,
3168 ProbingParserDummyForTesting, NULL);
3169 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3170 "90",
3171 ALPROTO_FTP,
3172 7, 15,
3173 STREAM_TOCLIENT,
3174 ProbingParserDummyForTesting, NULL);
3175 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3176 "80",
3177 ALPROTO_SMB,
3178 5, 6,
3179 STREAM_TOCLIENT,
3180 ProbingParserDummyForTesting, NULL);
3181 AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3182 "85",
3183 ALPROTO_IMAP,
3184 12, 23,
3185 STREAM_TOCLIENT,
3186 ProbingParserDummyForTesting, NULL);
3187 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3188 "0",
3189 ALPROTO_SMTP,
3190 12, 17,
3191 STREAM_TOCLIENT,
3192 ProbingParserDummyForTesting, NULL);
3193 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3194 "80",
3195 ALPROTO_FTP,
3196 7, 10,
3197 STREAM_TOCLIENT,
3198 ProbingParserDummyForTesting, NULL);
3199
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 },
3208 };
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 } };
3217
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 },
3225 };
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 }
3233 };
3234
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 },
3242 };
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 }
3249 };
3250
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 },
3256 };
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 }
3263 };
3264
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 },
3270 };
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 }
3276 };
3277
3278
3279 AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3280 { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3281 };
3282 AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3283 { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3284 };
3285
3286 AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3287 {
3288 80,
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)),
3295 23,
3296 element_ts_80,
3297 element_tc_80,
3298 sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3299 sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3300 },
3301 {
3302 81,
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)),
3307 23,
3308 element_ts_81,
3309 element_tc_81,
3310 sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3311 sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3312 },
3313 { 85,
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) },
3321 { 90,
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) },
3329 { 0,
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) }
3337 };
3338
3339 AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3340 { 85,
3341 (1 << ALPROTO_IMAP),
3342 (1 << ALPROTO_IMAP),
3343 23,
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),
3347 },
3348 };
3349
3350 AppLayerProtoDetectPPTestDataIPProto ip_proto[] = {
3351 { IPPROTO_TCP,
3352 ports_tcp,
3353 sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3354 },
3355 { IPPROTO_UDP,
3356 ports_udp,
3357 sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3358 },
3359 };
3360
3361
3362 if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3363 sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3364 goto end;
3365 }
3366 result = 1;
3367
3368 end:
3369 AppLayerProtoDetectDeSetup();
3370 AppLayerProtoDetectUnittestCtxRestore();
3371 return result;
3372 }
3373
3374
3375 /** \test test if the engine detect the proto and match with it */
3376 static int AppLayerProtoDetectTest16(void)
3377 {
3378 int result = 0;
3379 Flow *f = NULL;
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;
3385 TcpSession ssn;
3386 Packet *p = NULL;
3387 Signature *s = NULL;
3388 ThreadVars tv;
3389 DetectEngineThreadCtx *det_ctx = NULL;
3390 DetectEngineCtx *de_ctx = NULL;
3391 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3392
3393 memset(&tv, 0, sizeof(ThreadVars));
3394 memset(&ssn, 0, sizeof(TcpSession));
3395
3396 p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3397 if (p == NULL) {
3398 printf("packet setup failed: ");
3399 goto end;
3400 }
3401
3402 f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3403 if (f == NULL) {
3404 printf("flow setup failed: ");
3405 goto end;
3406 }
3407 f->protoctx = &ssn;
3408 f->proto = IPPROTO_TCP;
3409 p->flow = f;
3410
3411 p->flowflags |= FLOW_PKT_TOSERVER;
3412 p->flowflags |= FLOW_PKT_ESTABLISHED;
3413 p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
3414
3415 f->alproto = ALPROTO_HTTP1;
3416
3417 StreamTcpInitConfig(true);
3418
3419 de_ctx = DetectEngineCtxInit();
3420 if (de_ctx == NULL) {
3421 goto end;
3422 }
3423 de_ctx->flags |= DE_QUIET;
3424
3425 s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3426 "(msg:\"Test content option\"; "
3427 "sid:1;)");
3428 if (s == NULL) {
3429 goto end;
3430 }
3431
3432 SigGroupBuild(de_ctx);
3433 DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3434
3435 FLOWLOCK_WRLOCK(f);
3436 int r = AppLayerParserParse(
3437 NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3438 if (r != 0) {
3439 printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3440 FLOWLOCK_UNLOCK(f);
3441 goto end;
3442 }
3443 FLOWLOCK_UNLOCK(f);
3444
3445 http_state = f->alstate;
3446 if (http_state == NULL) {
3447 printf("no http state: ");
3448 goto end;
3449 }
3450
3451 /* do detect */
3452 SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3453
3454 if (!PacketAlertCheck(p, 1)) {
3455 printf("sig 1 didn't alert, but it should: ");
3456 goto end;
3457 }
3458 result = 1;
3459 end:
3460 if (alp_tctx != NULL)
3461 AppLayerParserThreadCtxFree(alp_tctx);
3462 if (det_ctx != NULL)
3463 DetectEngineThreadCtxDeinit(&tv, det_ctx);
3464 if (de_ctx != NULL)
3465 SigGroupCleanup(de_ctx);
3466 if (de_ctx != NULL)
3467 DetectEngineCtxFree(de_ctx);
3468
3469 StreamTcpFreeConfig(true);
3470
3471 UTHFreePackets(&p, 1);
3472 UTHFreeFlow(f);
3473 return result;
3474 }
3475
3476 /** \test test if the engine detect the proto on a non standar port
3477 * and match with it */
3478 static int AppLayerProtoDetectTest17(void)
3479 {
3480 int result = 0;
3481 Flow *f = NULL;
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;
3487 TcpSession ssn;
3488 Packet *p = NULL;
3489 Signature *s = NULL;
3490 ThreadVars tv;
3491 DetectEngineThreadCtx *det_ctx = NULL;
3492 DetectEngineCtx *de_ctx = NULL;
3493 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3494
3495 memset(&tv, 0, sizeof(ThreadVars));
3496 memset(&ssn, 0, sizeof(TcpSession));
3497
3498 p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3499
3500 f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3501 if (f == NULL)
3502 goto end;
3503 f->protoctx = &ssn;
3504 f->proto = IPPROTO_TCP;
3505 p->flow = f;
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;
3510
3511 StreamTcpInitConfig(true);
3512
3513 de_ctx = DetectEngineCtxInit();
3514 if (de_ctx == NULL) {
3515 goto end;
3516 }
3517 de_ctx->flags |= DE_QUIET;
3518
3519 s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3520 "(msg:\"http over non standar port\"; "
3521 "sid:1;)");
3522 if (s == NULL) {
3523 goto end;
3524 }
3525
3526 SigGroupBuild(de_ctx);
3527 DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3528
3529 FLOWLOCK_WRLOCK(f);
3530 int r = AppLayerParserParse(
3531 NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3532 if (r != 0) {
3533 printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3534 FLOWLOCK_UNLOCK(f);
3535 goto end;
3536 }
3537 FLOWLOCK_UNLOCK(f);
3538
3539 http_state = f->alstate;
3540 if (http_state == NULL) {
3541 printf("no http state: ");
3542 goto end;
3543 }
3544
3545 /* do detect */
3546 SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3547
3548 if (!PacketAlertCheck(p, 1)) {
3549 printf("sig 1 didn't alert, but it should: ");
3550 goto end;
3551 }
3552
3553 result = 1;
3554
3555 end:
3556 if (alp_tctx != NULL)
3557 AppLayerParserThreadCtxFree(alp_tctx);
3558 if (det_ctx != NULL)
3559 DetectEngineThreadCtxDeinit(&tv, det_ctx);
3560 if (de_ctx != NULL)
3561 SigGroupCleanup(de_ctx);
3562 if (de_ctx != NULL)
3563 DetectEngineCtxFree(de_ctx);
3564
3565 StreamTcpFreeConfig(true);
3566
3567 UTHFreePackets(&p, 1);
3568 UTHFreeFlow(f);
3569 return result;
3570 }
3571
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)
3575 {
3576 int result = 0;
3577 Flow *f = NULL;
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;
3583 TcpSession ssn;
3584 Packet *p = NULL;
3585 Signature *s = NULL;
3586 ThreadVars tv;
3587 DetectEngineThreadCtx *det_ctx = NULL;
3588 DetectEngineCtx *de_ctx = NULL;
3589 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3590
3591 memset(&tv, 0, sizeof(ThreadVars));
3592 memset(&ssn, 0, sizeof(TcpSession));
3593
3594 p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3595
3596 f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3597 if (f == NULL)
3598 goto end;
3599 f->protoctx = &ssn;
3600 f->proto = IPPROTO_TCP;
3601 p->flow = f;
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;
3606
3607 StreamTcpInitConfig(true);
3608
3609 de_ctx = DetectEngineCtxInit();
3610 if (de_ctx == NULL) {
3611 goto end;
3612 }
3613 de_ctx->flags |= DE_QUIET;
3614
3615 s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3616 "(msg:\"Test content option\"; "
3617 "sid:1;)");
3618 if (s == NULL) {
3619 goto end;
3620 }
3621
3622 SigGroupBuild(de_ctx);
3623 DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3624
3625 FLOWLOCK_WRLOCK(f);
3626 int r = AppLayerParserParse(
3627 NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3628 if (r != 0) {
3629 printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3630 FLOWLOCK_UNLOCK(f);
3631 goto end;
3632 }
3633 FLOWLOCK_UNLOCK(f);
3634
3635 http_state = f->alstate;
3636 if (http_state == NULL) {
3637 printf("no http state: ");
3638 goto end;
3639 }
3640
3641 /* do detect */
3642 SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3643
3644 if (PacketAlertCheck(p, 1)) {
3645 printf("sig 1 alerted, but it should not (it's not ftp): ");
3646 goto end;
3647 }
3648
3649 result = 1;
3650 end:
3651 if (alp_tctx != NULL)
3652 AppLayerParserThreadCtxFree(alp_tctx);
3653 if (det_ctx != NULL)
3654 DetectEngineThreadCtxDeinit(&tv, det_ctx);
3655 if (de_ctx != NULL)
3656 SigGroupCleanup(de_ctx);
3657 if (de_ctx != NULL)
3658 DetectEngineCtxFree(de_ctx);
3659
3660 StreamTcpFreeConfig(true);
3661
3662 UTHFreePackets(&p, 1);
3663 UTHFreeFlow(f);
3664 return result;
3665 }
3666
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)
3670 {
3671 int result = 0;
3672 Flow *f = NULL;
3673 uint8_t http_buf1[] = "MPUT one\r\n";
3674 uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3675 TcpSession ssn;
3676 Packet *p = NULL;
3677 Signature *s = NULL;
3678 ThreadVars tv;
3679 DetectEngineThreadCtx *det_ctx = NULL;
3680 DetectEngineCtx *de_ctx = NULL;
3681 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
3682
3683 memset(&tv, 0, sizeof(ThreadVars));
3684 memset(&ssn, 0, sizeof(TcpSession));
3685
3686 p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3687
3688 f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3689 if (f == NULL)
3690 goto end;
3691 f->protoctx = &ssn;
3692 f->proto = IPPROTO_TCP;
3693 p->flow = f;
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;
3698
3699 StreamTcpInitConfig(true);
3700
3701 de_ctx = DetectEngineCtxInit();
3702 if (de_ctx == NULL) {
3703 goto end;
3704 }
3705 de_ctx->flags |= DE_QUIET;
3706
3707 s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3708 "(msg:\"http over non standar port\"; "
3709 "sid:1;)");
3710 if (s == NULL) {
3711 goto end;
3712 }
3713
3714 SigGroupBuild(de_ctx);
3715 DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3716
3717 FLOWLOCK_WRLOCK(f);
3718 int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3719 STREAM_TOSERVER, http_buf1, http_buf1_len);
3720 if (r != 0) {
3721 printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3722 FLOWLOCK_UNLOCK(f);
3723 goto end;
3724 }
3725 FLOWLOCK_UNLOCK(f);
3726
3727 /* do detect */
3728 SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3729
3730 if (PacketAlertCheck(p, 1)) {
3731 printf("sig 1 alerted, but it should not (it's ftp): ");
3732 goto end;
3733 }
3734
3735 result = 1;
3736
3737 end:
3738 if (alp_tctx != NULL)
3739 AppLayerParserThreadCtxFree(alp_tctx);
3740 if (det_ctx != NULL)
3741 DetectEngineThreadCtxDeinit(&tv, det_ctx);
3742 if (de_ctx != NULL)
3743 SigGroupCleanup(de_ctx);
3744 if (de_ctx != NULL)
3745 DetectEngineCtxFree(de_ctx);
3746
3747 StreamTcpFreeConfig(true);
3748 UTHFreePackets(&p, 1);
3749 UTHFreeFlow(f);
3750 return result;
3751 }
3752
3753 void AppLayerProtoDetectUnittestsRegister(void)
3754 {
3755 SCEnter();
3756
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);
3776
3777 SCReturn;
3778 }
3779
3780 #endif /* UNITTESTS */