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