Coverage Report

Created: 2026-08-14 07:34

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