Coverage Report

Created: 2026-02-14 06:42

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
205k
{
197
205k
    SCEnter();
198
199
205k
    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
205k
    if (s->cd->depth > searchlen) {
205
2
        SCLogDebug("s->co->depth (%"PRIu16") > searchlen (%"PRIu16")",
206
2
                   s->cd->depth, searchlen);
207
2
        SCReturnUInt(ALPROTO_UNKNOWN);
208
2
    }
209
210
205k
    const uint8_t *sbuf = buf + s->cd->offset;
211
205k
    uint16_t ssearchlen = s->cd->depth - s->cd->offset;
212
205k
    SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
213
205k
               s->cd->offset, s->cd->depth);
214
215
205k
    uint8_t *found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx,
216
205k
            sbuf, ssearchlen);
217
205k
    if (found == NULL) {
218
10.5k
        SCReturnUInt(ALPROTO_UNKNOWN);
219
10.5k
    }
220
221
195k
    uint8_t direction = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
222
195k
    SCLogDebug("matching, s->direction %s, our dir %s",
223
195k
            (s->direction & STREAM_TOSERVER) ? "toserver" : "toclient",
224
195k
            (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
225
195k
    if (s->PPFunc == NULL) {
226
116k
        if (direction == s->direction) {
227
107k
            SCLogDebug("direction is correct");
228
107k
        } else {
229
9.11k
            SCLogDebug("direction is wrong, rflow = true");
230
9.11k
            *rflow = true;
231
9.11k
        }
232
    /* validate using Probing Parser */
233
116k
    } else {
234
78.5k
        if (s->pp_min_depth > buflen) {
235
7.04k
            SCLogDebug("PP can't be run yet as pp_min_depth %u > buflen %u",
236
7.04k
                    s->pp_min_depth, buflen);
237
7.04k
            SCReturnInt(ALPROTO_UNKNOWN);
238
7.04k
        }
239
240
71.4k
        uint8_t rdir = 0;
241
71.4k
        AppProto r = s->PPFunc(f, flags, buf, buflen, &rdir);
242
71.4k
        if (r == s->alproto) {
243
53.1k
            SCLogDebug("found %s/%u, rdir %02x reverse_flow? %s",
244
53.1k
                    AppProtoToString(r), r, rdir,
245
53.1k
                    (rdir && direction != rdir) ? "true" : "false");
246
53.1k
            *rflow = (rdir && direction != rdir);
247
53.1k
            SCReturnUInt(s->alproto);
248
53.1k
        } else if (r == ALPROTO_FAILED) {
249
18.3k
            SCReturnUInt(ALPROTO_FAILED);
250
18.3k
        } 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
71.4k
    }
259
195k
    SCReturnUInt(s->alproto);
260
195k
}
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.33M
{
270
1.33M
    int pm_matches = 0;
271
272
    // maxdepth is u16, so minimum is u16
273
1.33M
    uint16_t searchlen = (uint16_t)MIN(buflen, pm_ctx->mpm_ctx.maxdepth);
274
1.33M
    SCLogDebug("searchlen %u buflen %u", searchlen, buflen);
275
276
    /* do the mpm search */
277
1.33M
    uint32_t search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(
278
1.33M
            &pm_ctx->mpm_ctx, mpm_tctx, &tctx->pmq,
279
1.33M
            buf, searchlen);
280
1.33M
    if (search_cnt == 0) {
281
1.13M
        if (buflen >= pm_ctx->mpm_ctx.maxdepth)
282
580k
            return -1;
283
551k
        return 0;
284
1.13M
    }
285
286
    /* alproto bit field */
287
205k
    uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
288
205k
    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
411k
    for (uint32_t cnt = 0; cnt < tctx->pmq.rule_id_array_cnt; cnt++) {
294
205k
        const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.rule_id_array[cnt]];
295
411k
        while (s != NULL) {
296
205k
            AppProto proto = AppLayerProtoDetectPMMatchSignature(
297
205k
                    s, tctx, f, flags, buf, buflen, searchlen, rflow);
298
299
            /* store each unique proto once */
300
205k
            if (AppProtoIsValid(proto) &&
301
170k
                !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
302
170k
            {
303
170k
                pm_results[pm_matches++] = proto;
304
170k
                pm_results_bf[proto / 8] |= 1 << (proto % 8);
305
170k
            }
306
205k
            s = s->next;
307
205k
        }
308
205k
    }
309
205k
    if (pm_matches == 0 && buflen >= pm_ctx->pp_max_len) {
310
16.1k
        pm_matches = -2;
311
16.1k
    }
312
205k
    PmqReset(&tctx->pmq);
313
205k
    return pm_matches;
314
1.33M
}
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.37M
{
323
1.37M
    SCEnter();
324
325
1.37M
    pm_results[0] = ALPROTO_UNKNOWN;
326
327
1.37M
    AppLayerProtoDetectPMCtx *pm_ctx;
328
1.37M
    MpmThreadCtx *mpm_tctx;
329
1.37M
    int m = -1;
330
331
1.37M
    if (f->protomap >= FLOW_PROTO_DEFAULT) {
332
13
        pm_results[0] = ALPROTO_FAILED;
333
13
        SCReturnUInt(1);
334
13
    }
335
336
1.37M
    if (flags & STREAM_TOSERVER) {
337
798k
        pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
338
798k
        mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
339
798k
    } else {
340
580k
        pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
341
580k
        mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
342
580k
    }
343
1.37M
    if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
344
755k
        m = PMGetProtoInspect(tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
345
755k
    }
346
    /* pattern found, yay */
347
1.37M
    if (m > 0) {
348
160k
        FLOW_SET_PM_DONE(f, flags);
349
160k
        SCReturnUInt((uint16_t)m);
350
351
    /* handle non-found in non-midstream case */
352
1.21M
    } else if (!stream_config.midstream) {
353
        /* we can give up if mpm gave no results and its search depth
354
         * was reached. */
355
635k
        if (m < 0) {
356
633k
            FLOW_SET_PM_DONE(f, flags);
357
633k
            SCReturnUInt(0);
358
633k
        } else if (m == 0) {
359
2.85k
            SCReturnUInt(0);
360
2.85k
        }
361
635k
        SCReturnUInt((uint16_t)m);
362
363
    /* handle non-found in midstream case */
364
635k
    } else if (m <= 0) {
365
582k
        if (flags & STREAM_TOSERVER) {
366
339k
            pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
367
339k
            mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
368
339k
        } else {
369
243k
            pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
370
243k
            mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
371
243k
        }
372
582k
        SCLogDebug("no matches and in midstream mode, lets try the "
373
582k
                   "*patterns for the other side");
374
375
582k
        int om = -1;
376
582k
        if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
377
582k
            om = PMGetProtoInspect(
378
582k
                    tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
379
582k
        }
380
        /* found! */
381
582k
        if (om > 0) {
382
9.14k
            FLOW_SET_PM_DONE(f, flags);
383
9.14k
            SCReturnUInt((uint16_t)om);
384
385
        /* both sides failed */
386
573k
        } else if (om < 0 && m && m < 0) {
387
251k
            FLOW_SET_PM_DONE(f, flags);
388
251k
            SCReturnUInt(0);
389
390
        /* one side still uncertain */
391
322k
        } else if (om == 0 || m == 0) {
392
322k
            SCReturnUInt(0);
393
322k
        }
394
582k
    }
395
1.37M
    SCReturnUInt(0);
396
1.37M
}
397
398
static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectGetProbingParser(
399
        AppLayerProtoDetectProbingParser *pp, uint8_t ipproto, AppProto alproto)
400
174k
{
401
174k
    AppLayerProtoDetectProbingParserElement *pp_elem = NULL;
402
174k
    AppLayerProtoDetectProbingParserPort *pp_port = NULL;
403
404
198k
    while (pp != NULL) {
405
198k
        if (pp->ipproto == ipproto)
406
174k
            break;
407
23.8k
        pp = pp->next;
408
23.8k
    }
409
174k
    if (pp == NULL)
410
0
        return NULL;
411
412
174k
    pp_port = pp->port;
413
1.92M
    while (pp_port != NULL) {
414
1.87M
        if (pp_port->dp != NULL && pp_port->dp->alproto == alproto) {
415
125k
            pp_elem = pp_port->dp;
416
125k
            break;
417
125k
        }
418
1.74M
        if (pp_port->sp != NULL && pp_port->sp->alproto == alproto) {
419
0
            pp_elem = pp_port->sp;
420
0
            break;
421
0
        }
422
1.74M
        pp_port = pp_port->next;
423
1.74M
    }
424
425
174k
    SCReturnPtr(pp_elem, "AppLayerProtoDetectProbingParserElement *");
426
174k
}
427
428
static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
429
                                                                                  uint8_t ipproto,
430
                                                                                  uint16_t port)
431
2.23M
{
432
2.23M
    AppLayerProtoDetectProbingParserPort *pp_port = NULL;
433
434
2.32M
    while (pp != NULL) {
435
2.32M
        if (pp->ipproto == ipproto)
436
2.23M
            break;
437
438
92.1k
        pp = pp->next;
439
92.1k
    }
440
441
2.23M
    if (pp == NULL)
442
4
        goto end;
443
444
2.23M
    pp_port = pp->port;
445
25.1M
    while (pp_port != NULL) {
446
24.0M
        if (pp_port->port == port || pp_port->port == 0) {
447
1.10M
            break;
448
1.10M
        }
449
22.9M
        pp_port = pp_port->next;
450
22.9M
    }
451
452
2.23M
 end:
453
2.23M
    SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
454
2.23M
}
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
638k
{
463
638k
    AppProto alproto = ALPROTO_UNKNOWN;
464
465
638k
    SCLogDebug("expectation check for %p (dir %d)", f, flags);
466
638k
    FLOW_SET_PE_DONE(f, flags);
467
468
638k
    alproto = AppLayerExpectationHandle(f, flags);
469
470
638k
    return alproto;
471
638k
}
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.55M
{
476
3.24M
    while (pe != NULL) {
477
1.01M
        if ((buflen < pe->min_depth)  ||
478
1.00M
            (alproto_masks[0] & pe->alproto_mask)) {
479
109k
            pe = pe->next;
480
109k
            continue;
481
109k
        }
482
483
906k
        AppProto alproto = ALPROTO_UNKNOWN;
484
906k
        if (flags & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
485
495k
            alproto = pe->ProbingParserTs(f, flags, buf, buflen, rdir);
486
495k
        } else if (flags & STREAM_TOCLIENT && pe->ProbingParserTc != NULL) {
487
384k
            alproto = pe->ProbingParserTc(f, flags, buf, buflen, rdir);
488
384k
        }
489
906k
        if (AppProtoIsValid(alproto)) {
490
323k
            SCReturnUInt(alproto);
491
323k
        }
492
582k
        if (alproto == ALPROTO_FAILED ||
493
546k
            (pe->max_depth != 0 && buflen > pe->max_depth)) {
494
315k
            alproto_masks[0] |= pe->alproto_mask;
495
315k
        }
496
582k
        pe = pe->next;
497
582k
    }
498
499
2.55M
    SCReturnUInt(ALPROTO_UNKNOWN);
500
2.55M
}
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
889k
{
512
889k
    const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
513
889k
    const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
514
889k
    const AppLayerProtoDetectProbingParserElement *pe0 = NULL;
515
889k
    const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
516
889k
    const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
517
889k
    AppProto alproto = ALPROTO_UNKNOWN;
518
889k
    uint32_t *alproto_masks = NULL;
519
889k
    uint32_t mask = 0;
520
889k
    uint8_t idir = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
521
889k
    uint8_t dir = idir;
522
889k
    uint16_t dp = f->protodetect_dp ? f->protodetect_dp : FLOW_GET_DP(f);
523
889k
    uint16_t sp = FLOW_GET_SP(f);
524
889k
    bool probe_is_found = false;
525
526
1.11M
again_midstream:
527
1.11M
    if (idir != dir) {
528
227k
        SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
529
227k
    }
530
1.11M
    SCLogDebug("%u->%u %s", sp, dp,
531
1.11M
            (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
532
533
1.11M
    if (dir == STREAM_TOSERVER) {
534
        /* first try the destination port */
535
596k
        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
536
596k
        alproto_masks = &f->probing_parser_toserver_alproto_masks;
537
596k
        if (pp_port_dp != NULL) {
538
481k
            SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);
539
540
            /* found based on destination port, so use dp registration */
541
481k
            pe1 = pp_port_dp->dp;
542
481k
        } else {
543
114k
            SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
544
114k
        }
545
546
596k
        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
547
596k
        if (pp_port_sp != NULL) {
548
109k
            SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);
549
550
            /* found based on source port, so use sp registration */
551
109k
            pe2 = pp_port_sp->sp;
552
486k
        } else {
553
486k
            SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
554
486k
        }
555
596k
    } else {
556
        /* first try the destination port */
557
521k
        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
558
521k
        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
394k
            alproto_masks = &f->probing_parser_toclient_alproto_masks;
562
394k
        }
563
521k
        if (pp_port_dp != NULL) {
564
393k
            SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);
565
566
            /* found based on destination port, so use dp registration */
567
393k
            pe1 = pp_port_dp->dp;
568
393k
        } else {
569
127k
            SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
570
127k
        }
571
572
521k
        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
573
521k
        if (pp_port_sp != NULL) {
574
122k
            SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);
575
576
122k
            pe2 = pp_port_sp->sp;
577
399k
        } else {
578
399k
            SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
579
399k
        }
580
521k
    }
581
582
1.11M
    if (dir == STREAM_TOSERVER && f->alproto_tc != ALPROTO_UNKNOWN) {
583
23.5k
        pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_tc);
584
1.09M
    } else if (dir == STREAM_TOCLIENT && f->alproto_ts != ALPROTO_UNKNOWN) {
585
50.4k
        pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_ts);
586
50.4k
    }
587
588
1.11M
    if (pe1 == NULL && pe2 == NULL && pe0 == NULL) {
589
154k
        SCLogDebug("%s - No probing parsers found for either port",
590
154k
                (dir == STREAM_TOSERVER) ? "toserver":"toclient");
591
154k
        goto noparsers;
592
963k
    } else {
593
963k
        probe_is_found = true;
594
963k
    }
595
596
    /* run the parser(s): always call with original direction */
597
963k
    uint8_t rdir = 0;
598
963k
    alproto = PPGetProto(pe0, f, flags, buf, buflen, alproto_masks, &rdir);
599
963k
    if (AppProtoIsValid(alproto))
600
9.86k
        goto end;
601
953k
    alproto = PPGetProto(pe1, f, flags, buf, buflen, alproto_masks, &rdir);
602
953k
    if (AppProtoIsValid(alproto))
603
313k
        goto end;
604
639k
    alproto = PPGetProto(pe2, f, flags, buf, buflen, alproto_masks, &rdir);
605
639k
    if (AppProtoIsValid(alproto))
606
0
        goto end;
607
608
    /* get the mask we need for this direction */
609
639k
    if (dir == idir) {
610
460k
        if (pp_port_dp && pp_port_sp)
611
24.4k
            mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
612
435k
        else if (pp_port_dp)
613
425k
            mask = pp_port_dp->alproto_mask;
614
10.1k
        else if (pp_port_sp)
615
9.69k
            mask = pp_port_sp->alproto_mask;
616
617
460k
        if ((alproto_masks[0] & mask) == mask) {
618
299k
            FLOW_SET_PP_DONE(f, dir);
619
299k
            SCLogDebug("%s, mask is now %08x, needed %08x, so done",
620
299k
                    (dir == STREAM_TOSERVER) ? "toserver":"toclient",
621
299k
                    alproto_masks[0], mask);
622
299k
        } else {
623
160k
            SCLogDebug("%s, mask is now %08x, need %08x",
624
160k
                    (dir == STREAM_TOSERVER) ? "toserver":"toclient",
625
160k
                    alproto_masks[0], mask);
626
160k
        }
627
460k
    }
628
629
793k
noparsers:
630
793k
    if (stream_config.midstream && idir == dir) {
631
227k
        if (idir == STREAM_TOSERVER) {
632
126k
            dir = STREAM_TOCLIENT;
633
126k
        } else {
634
100k
            dir = STREAM_TOSERVER;
635
100k
        }
636
227k
        SCLogDebug("no match + midstream, retry the other direction %s",
637
227k
                (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
638
227k
        goto again_midstream;
639
566k
    } else if (!probe_is_found) {
640
32.5k
        FLOW_SET_PP_DONE(f, idir);
641
32.5k
    }
642
643
889k
 end:
644
889k
    if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
645
49.1k
        SCLogDebug("PP found %u, is reverse flow", alproto);
646
49.1k
        *reverse_flow = true;
647
49.1k
    }
648
649
889k
    SCLogDebug("%s, mask is now %08x",
650
889k
            (idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
651
889k
    SCReturnUInt(alproto);
652
793k
}
653
654
/***** Static Internal Calls: PP registration *****/
655
656
static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
657
                                             uint8_t *ipprotos)
658
1.97M
{
659
1.97M
    SCEnter();
660
661
1.97M
    const AppLayerProtoDetectProbingParser *pp;
662
1.97M
    const AppLayerProtoDetectProbingParserPort *pp_port;
663
1.97M
    const AppLayerProtoDetectProbingParserElement *pp_pe;
664
665
5.91M
    for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
666
71.5M
        for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
667
135M
            for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
668
67.5M
                if (alproto == pp_pe->alproto)
669
1.89M
                    ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
670
67.5M
            }
671
67.5M
            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
67.5M
        }
676
3.94M
    }
677
678
1.97M
    SCReturn;
679
1.97M
}
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.46k
{
694
2.46k
    SCEnter();
695
696
2.46k
    AppLayerProtoDetectProbingParserElement *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement));
697
2.46k
    if (unlikely(p == NULL)) {
698
0
        exit(EXIT_FAILURE);
699
0
    }
700
2.46k
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
701
702
2.46k
    SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
703
2.46k
}
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.45k
{
715
2.45k
    SCEnter();
716
717
2.45k
    AppLayerProtoDetectProbingParserPort *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort));
718
2.45k
    if (unlikely(p == NULL)) {
719
0
        exit(EXIT_FAILURE);
720
0
    }
721
2.45k
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
722
723
2.45k
    SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
724
2.45k
}
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
148
{
753
148
    SCEnter();
754
755
148
    AppLayerProtoDetectProbingParser *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParser));
756
148
    if (unlikely(p == NULL)) {
757
0
        exit(EXIT_FAILURE);
758
0
    }
759
148
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
760
761
148
    SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
762
148
}
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.46k
{
786
2.46k
    AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
787
788
2.46k
    pe->alproto = alproto;
789
2.46k
    pe->port = port;
790
2.46k
    pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
791
2.46k
    pe->min_depth = min_depth;
792
2.46k
    pe->max_depth = max_depth;
793
2.46k
    pe->next = NULL;
794
795
2.46k
    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.46k
    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.46k
    SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
808
0
 error:
809
0
    AppLayerProtoDetectProbingParserElementFree(pe);
810
0
    SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
811
2.46k
}
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
148
{
941
148
    SCEnter();
942
943
148
    if (*head_pp == NULL) {
944
74
        *head_pp = new_pp;
945
74
        goto end;
946
74
    }
947
948
74
    AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
949
74
    while (temp_pp->next != NULL)
950
0
        temp_pp = temp_pp->next;
951
74
    temp_pp->next = new_pp;
952
953
148
 end:
954
148
    SCReturn;
955
74
}
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.97M
{
1168
1.97M
    SCEnter();
1169
1170
7.89M
    for (uint8_t i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1171
5.91M
        uint8_t ipproto = FlowGetReverseProtoMapping(i);
1172
17.7M
        for (int j = 0; j < 2; j++) {
1173
11.8M
            AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1174
1175
263M
            for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1176
251M
                const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1177
251M
                if (s->alproto == alproto)
1178
31.3M
                    ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1179
251M
            }
1180
11.8M
        }
1181
5.91M
    }
1182
1183
1.97M
    SCReturn;
1184
1.97M
}
1185
1186
static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1187
438
{
1188
438
    SCEnter();
1189
1190
438
    typedef struct TempContainer_ {
1191
438
        PatIntId id;
1192
438
        uint16_t content_len;
1193
438
        uint8_t *content;
1194
438
    } TempContainer;
1195
1196
438
    AppLayerProtoDetectPMSignature *s = NULL;
1197
438
    uint32_t struct_total_size = 0;
1198
438
    uint32_t content_total_size = 0;
1199
    /* array hash buffer */
1200
438
    uint8_t *ahb = NULL;
1201
438
    uint8_t *content = NULL;
1202
438
    uint16_t content_len = 0;
1203
438
    PatIntId max_id = 0;
1204
438
    TempContainer *struct_offset = NULL;
1205
438
    uint8_t *content_offset = NULL;
1206
438
    int ret = 0;
1207
1208
438
    if (ctx->head == NULL)
1209
146
        goto end;
1210
1211
9.31k
    for (s = ctx->head; s != NULL; s = s->next) {
1212
9.02k
        struct_total_size += sizeof(TempContainer);
1213
9.02k
        content_total_size += s->cd->content_len;
1214
9.02k
        ctx->max_sig_id++;
1215
9.02k
    }
1216
1217
292
    ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1218
292
    if (unlikely(ahb == NULL))
1219
0
        goto error;
1220
1221
292
    struct_offset = (TempContainer *)ahb;
1222
292
    content_offset = ahb + struct_total_size;
1223
9.31k
    for (s = ctx->head; s != NULL; s = s->next) {
1224
9.02k
        TempContainer *tcdup = (TempContainer *)ahb;
1225
9.02k
        content = s->cd->content;
1226
9.02k
        content_len = s->cd->content_len;
1227
1228
310k
        for (; tcdup != struct_offset; tcdup++) {
1229
301k
            if (tcdup->content_len != content_len ||
1230
34.1k
                SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1231
301k
            {
1232
301k
                continue;
1233
301k
            }
1234
0
            break;
1235
301k
        }
1236
1237
9.02k
        if (tcdup != struct_offset) {
1238
0
            s->cd->id = tcdup->id;
1239
0
            continue;
1240
0
        }
1241
1242
9.02k
        struct_offset->content_len = content_len;
1243
9.02k
        struct_offset->content = content_offset;
1244
9.02k
        content_offset += content_len;
1245
9.02k
        memcpy(struct_offset->content, content, content_len);
1246
9.02k
        struct_offset->id = max_id++;
1247
9.02k
        s->cd->id = struct_offset->id;
1248
1249
9.02k
        struct_offset++;
1250
9.02k
    }
1251
1252
292
    ctx->max_pat_id = max_id;
1253
1254
292
    goto end;
1255
0
 error:
1256
0
    ret = -1;
1257
438
 end:
1258
438
    if (ahb != NULL)
1259
292
        SCFree(ahb);
1260
438
    SCReturnInt(ret);
1261
0
}
1262
1263
static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1264
292
{
1265
292
    SCEnter();
1266
1267
292
    int ret = 0;
1268
292
    AppLayerProtoDetectPMSignature *s, *next_s;
1269
292
    int mpm_ret;
1270
292
    SigIntId id = 0;
1271
1272
292
    ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1273
292
    if (ctx->map == NULL)
1274
0
        goto error;
1275
292
    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.31k
    for (s = ctx->head; s != NULL; ) {
1279
9.02k
        next_s = s->next;
1280
9.02k
        s->id = id++;
1281
9.02k
        SCLogDebug("s->id %u offset %u depth %u",
1282
9.02k
                s->id, s->cd->offset, s->cd->depth);
1283
1284
9.02k
        if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1285
5.53k
            mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1286
5.53k
                    s->cd->content, s->cd->content_len,
1287
5.53k
                    s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1288
5.53k
            if (mpm_ret < 0)
1289
0
                goto error;
1290
5.53k
        } else {
1291
3.48k
            mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1292
3.48k
                    s->cd->content, s->cd->content_len,
1293
3.48k
                    s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1294
3.48k
            if (mpm_ret < 0)
1295
0
                goto error;
1296
3.48k
        }
1297
1298
9.02k
        ctx->map[s->id] = s;
1299
9.02k
        s->next = NULL;
1300
9.02k
        s = next_s;
1301
9.02k
    }
1302
292
    ctx->head = NULL;
1303
1304
292
    goto end;
1305
0
 error:
1306
0
    ret = -1;
1307
292
 end:
1308
292
    SCReturnInt(ret);
1309
0
}
1310
1311
static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1312
292
{
1313
292
    SCEnter();
1314
1315
292
    int ret = 0;
1316
292
    MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1317
1318
292
    if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1319
0
        goto error;
1320
1321
292
    goto end;
1322
292
 error:
1323
0
    ret = -1;
1324
292
 end:
1325
292
    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.13k
{
1344
9.13k
    SCEnter();
1345
1346
9.13k
    AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1347
9.13k
    if (unlikely(s == NULL))
1348
0
        SCReturnInt(-1);
1349
1350
9.13k
    s->alproto = alproto;
1351
9.13k
    s->direction = direction;
1352
9.13k
    s->cd = cd;
1353
9.13k
    s->PPFunc = PPFunc;
1354
9.13k
    s->pp_min_depth = pp_min_depth;
1355
9.13k
    s->pp_max_depth = pp_max_depth;
1356
1357
    /* prepend to the list */
1358
9.13k
    s->next = ctx->head;
1359
9.13k
    ctx->head = s;
1360
1361
9.13k
    SCReturnInt(0);
1362
9.13k
}
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.13k
{
1372
9.13k
    SCEnter();
1373
1374
9.13k
    AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1375
9.13k
    AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1376
9.13k
    int ret = 0;
1377
1378
9.13k
    DetectContentData *cd = DetectContentParseEncloseQuotes(
1379
9.13k
            alpd_ctx.spm_global_thread_ctx, pattern);
1380
9.13k
    if (cd == NULL)
1381
0
        goto error;
1382
9.13k
    cd->depth = depth;
1383
9.13k
    cd->offset = offset;
1384
9.13k
    if (!is_cs) {
1385
        /* Rebuild as nocase */
1386
5.60k
        SpmDestroyCtx(cd->spm_ctx);
1387
5.60k
        cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1388
5.60k
                                 alpd_ctx.spm_global_thread_ctx);
1389
5.60k
        if (cd->spm_ctx == NULL) {
1390
0
            goto error;
1391
0
        }
1392
5.60k
        cd->flags |= DETECT_CONTENT_NOCASE;
1393
5.60k
    }
1394
9.13k
    if (depth < cd->content_len)
1395
0
        goto error;
1396
1397
9.13k
    if (direction & STREAM_TOSERVER)
1398
7.06k
        ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1399
2.06k
    else
1400
2.06k
        ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1401
1402
9.13k
    if (pp_max_depth > ctx_pm->pp_max_len)
1403
222
        ctx_pm->pp_max_len = pp_max_depth;
1404
9.13k
    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.13k
    AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1409
9.13k
            PPFunc, pp_min_depth, pp_max_depth);
1410
1411
9.13k
    goto end;
1412
0
 error:
1413
0
    DetectContentFree(NULL, cd);
1414
0
    ret = -1;
1415
9.13k
 end:
1416
9.13k
    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.07M
{
1424
1.07M
    SCEnter();
1425
1.07M
    SCLogDebug("buflen %u for %s direction", buflen,
1426
1.07M
            (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1427
1428
1.07M
    AppProto alproto = ALPROTO_UNKNOWN;
1429
1.07M
    AppProto pm_alproto = ALPROTO_UNKNOWN;
1430
1431
1.07M
    if (!FLOW_IS_PM_DONE(f, flags)) {
1432
951k
        AppProto pm_results[ALPROTO_MAX];
1433
951k
        uint16_t pm_matches = AppLayerProtoDetectPMGetProto(
1434
951k
                tctx, f, buf, buflen, flags, pm_results, reverse_flow);
1435
951k
        if (pm_matches > 0) {
1436
73.1k
            DEBUG_VALIDATE_BUG_ON(pm_matches > 1);
1437
73.1k
            alproto = pm_results[0];
1438
1439
            // rerun probing parser for other direction if it is unknown
1440
73.1k
            uint8_t reverse_dir = (flags & STREAM_TOSERVER) ? STREAM_TOCLIENT : STREAM_TOSERVER;
1441
73.1k
            if (FLOW_IS_PP_DONE(f, reverse_dir)) {
1442
3.39k
                AppProto rev_alproto = (flags & STREAM_TOSERVER) ? f->alproto_tc : f->alproto_ts;
1443
3.39k
                if (rev_alproto == ALPROTO_UNKNOWN) {
1444
3.31k
                    FLOW_RESET_PP_DONE(f, reverse_dir);
1445
3.31k
                }
1446
3.39k
            }
1447
1448
            /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1449
             * to avoid misdetecting DNS as DCERPC. */
1450
73.1k
            if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1451
73.0k
                goto end;
1452
1453
58
            pm_alproto = alproto;
1454
1455
            /* fall through */
1456
58
        }
1457
951k
    }
1458
1459
1.00M
    if (!FLOW_IS_PP_DONE(f, flags)) {
1460
889k
        bool rflow = false;
1461
889k
        alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1462
889k
        if (AppProtoIsValid(alproto)) {
1463
323k
            if (rflow) {
1464
49.1k
                *reverse_flow = true;
1465
49.1k
            }
1466
323k
            goto end;
1467
323k
        }
1468
889k
    }
1469
1470
    /* Look if flow can be found in expectation list */
1471
676k
    if (!FLOW_IS_PE_DONE(f, flags)) {
1472
480k
        alproto = AppLayerProtoDetectPEGetProto(f, ipproto, flags);
1473
480k
    }
1474
1475
1.07M
 end:
1476
1.07M
    if (!AppProtoIsValid(alproto))
1477
676k
        alproto = pm_alproto;
1478
1479
1.07M
    SCReturnUInt(alproto);
1480
676k
}
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
73
{
1526
73
    SCEnter();
1527
1528
73
    AppLayerProtoDetectPMCtx *ctx_pm;
1529
73
    int i, j;
1530
73
    int ret = 0;
1531
1532
292
    for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1533
657
        for (j = 0; j < 2; j++) {
1534
438
            ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1535
1536
438
            if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1537
0
                goto error;
1538
1539
438
            if (ctx_pm->max_sig_id == 0)
1540
146
                continue;
1541
1542
292
            if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1543
0
                goto error;
1544
292
            if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1545
0
                goto error;
1546
292
        }
1547
219
    }
1548
1549
#ifdef DEBUG
1550
    if (SCLogDebugEnabled()) {
1551
        AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1552
    }
1553
#endif
1554
1555
73
    goto end;
1556
73
 error:
1557
0
    ret = -1;
1558
73
 end:
1559
73
    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
74
{
1797
74
    SCEnter();
1798
1799
74
    AppLayerProtoDetectAliases *new_alias = SCMalloc(sizeof(AppLayerProtoDetectAliases));
1800
74
    if (unlikely(new_alias == NULL)) {
1801
0
        exit(EXIT_FAILURE);
1802
0
    }
1803
1804
74
    new_alias->proto_name = proto_name;
1805
74
    new_alias->proto_alias = proto_alias;
1806
74
    new_alias->next = NULL;
1807
1808
74
    if (alpda_ctx == NULL) {
1809
74
        alpda_ctx = new_alias;
1810
74
    } 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
74
    SCReturn;
1819
74
}
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
9.20k
{
1837
9.20k
    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
2.40k
        return false;
1842
2.40k
    }
1843
6.79k
    FlowSetChangeProtoFlag(f);
1844
6.79k
    f->protodetect_dp = dp;
1845
6.79k
    f->alproto_expect = expect_proto;
1846
6.79k
    DEBUG_VALIDATE_BUG_ON(f->alproto == ALPROTO_UNKNOWN);
1847
6.79k
    f->alproto_orig = f->alproto;
1848
    // If one side is unknown yet, set it to the other known side
1849
6.79k
    if (f->alproto_ts == ALPROTO_UNKNOWN) {
1850
507
        f->alproto_ts = f->alproto;
1851
507
    }
1852
6.79k
    if (f->alproto_tc == ALPROTO_UNKNOWN) {
1853
573
        f->alproto_tc = f->alproto;
1854
573
    }
1855
6.79k
    return true;
1856
6.79k
}
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
788
{
1868
788
    return AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
1869
788
}
1870
1871
void AppLayerProtoDetectReset(Flow *f)
1872
636k
{
1873
636k
    FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1874
636k
    FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1875
636k
    FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1876
636k
    FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1877
636k
    FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1878
636k
    FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1879
636k
    f->probing_parser_toserver_alproto_masks = 0;
1880
636k
    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
636k
    f->alparser = NULL;
1885
636k
    f->alproto    = ALPROTO_UNKNOWN;
1886
636k
    f->alproto_ts = ALPROTO_UNKNOWN;
1887
636k
    f->alproto_tc = ALPROTO_UNKNOWN;
1888
636k
}
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
799k
{
2047
799k
    SCEnter();
2048
2049
    // Custom case for only signature-only protocol so far
2050
799k
    if (alproto == ALPROTO_HTTP) {
2051
127k
        AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP1, ipprotos);
2052
127k
        AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP2, ipprotos);
2053
671k
    } else {
2054
671k
        AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2055
671k
        AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2056
671k
        AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2057
671k
    }
2058
2059
799k
    SCReturn;
2060
799k
}
2061
2062
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
2063
1.66M
{
2064
1.66M
    SCEnter();
2065
2066
1.66M
    AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2067
3.33M
    while (cur_alias != NULL) {
2068
1.66M
        if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2069
1.47k
            alproto_name = cur_alias->proto_name;
2070
1.47k
        }
2071
2072
1.66M
        cur_alias = cur_alias->next;
2073
1.66M
    }
2074
2075
1.66M
    AppProto a;
2076
1.66M
    AppProto b = StringToAppProto(alproto_name);
2077
27.0M
    for (a = 0; a < ALPROTO_MAX; a++) {
2078
26.9M
        if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2079
            // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2080
1.57M
            SCReturnCT(b, "AppProto");
2081
1.57M
        }
2082
26.9M
    }
2083
2084
1.66M
    SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2085
1.66M
}
2086
2087
const char *AppLayerProtoDetectGetProtoName(AppProto alproto)
2088
1.73M
{
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.73M
    if (alproto == ALPROTO_HTTP) {
2093
249k
        if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2094
249k
            if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2095
249k
                return "http";
2096
249k
            } // else
2097
0
            return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2098
249k
        } // else
2099
30
        return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2100
249k
    }
2101
1.48M
    return alpd_ctx.alproto_names[alproto];
2102
1.73M
}
2103
2104
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
2105
77
{
2106
77
    SCEnter();
2107
2108
77
    memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2109
2110
77
    int alproto;
2111
2112
2.98k
    for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2113
2.90k
        if (alpd_ctx.alproto_names[alproto] != NULL)
2114
2.51k
            alprotos[alproto] = 1;
2115
2.90k
    }
2116
2117
77
    SCReturn;
2118
77
}
2119
2120
uint8_t expectation_proto[ALPROTO_MAX];
2121
2122
static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2123
                                             uint8_t *ipprotos)
2124
671k
{
2125
671k
    if (expectation_proto[alproto] == IPPROTO_TCP) {
2126
1.57k
        ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2127
1.57k
    }
2128
671k
    if (expectation_proto[alproto] == IPPROTO_UDP) {
2129
0
        ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2130
0
    }
2131
671k
}
2132
2133
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
2134
74
{
2135
74
    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
74
    expectation_proto[alproto] = proto;
2141
74
}
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 */