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