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