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