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