Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-krb5-sname.c
Line
Count
Source
1
/* Copyright (C) 2018-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 Pierre Chifflier <chifflier@wzdftpd.net>
22
 */
23
24
#include "suricata-common.h"
25
#include "util-unittest.h"
26
27
#include "detect-parse.h"
28
#include "detect-engine.h"
29
#include "detect-engine-mpm.h"
30
#include "detect-engine-state.h"
31
#include "detect-engine-prefilter.h"
32
#include "detect-engine-content-inspection.h"
33
34
#include "detect-krb5-sname.h"
35
36
#include "rust.h"
37
#include "app-layer-krb5.h"
38
#include "util-profiling.h"
39
40
static int g_krb5_sname_buffer_id = 0;
41
42
struct Krb5PrincipalNameDataArgs {
43
    uint32_t local_id; /**< used as index into thread inspect array */
44
    void *txv;
45
};
46
47
static int DetectKrb5SNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
48
1.70k
{
49
1.70k
    if (DetectBufferSetActiveList(de_ctx, s, g_krb5_sname_buffer_id) < 0)
50
68
        return -1;
51
52
1.64k
    if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
53
43
        return -1;
54
55
1.59k
    return 0;
56
1.64k
}
57
58
static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
59
        const DetectEngineTransforms *transforms, Flow *_f,
60
        const struct Krb5PrincipalNameDataArgs *cbdata, int list_id)
61
57
{
62
57
    SCEnter();
63
64
57
    InspectionBuffer *buffer =
65
57
            InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
66
57
    if (buffer == NULL)
67
0
        return NULL;
68
57
    if (buffer->initialized)
69
18
        return buffer;
70
71
39
    uint32_t b_len = 0;
72
39
    const uint8_t *b = NULL;
73
74
39
    if (rs_krb5_tx_get_sname(cbdata->txv, cbdata->local_id, &b, &b_len) != 1) {
75
13
        InspectionBufferSetupMultiEmpty(buffer);
76
13
        return NULL;
77
13
    }
78
26
    if (b == NULL || b_len == 0) {
79
0
        InspectionBufferSetupMultiEmpty(buffer);
80
0
        return NULL;
81
0
    }
82
83
26
    InspectionBufferSetupMulti(buffer, transforms, b, b_len);
84
85
26
    SCReturnPtr(buffer, "InspectionBuffer");
86
26
}
87
88
static uint8_t DetectEngineInspectKrb5SName(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
89
        const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
90
        void *alstate, void *txv, uint64_t tx_id)
91
9
{
92
9
    uint32_t local_id = 0;
93
94
9
    const DetectEngineTransforms *transforms = NULL;
95
9
    if (!engine->mpm) {
96
0
        transforms = engine->v2.transforms;
97
0
    }
98
99
18
    while (1) {
100
18
        struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
101
18
        InspectionBuffer *buffer =
102
18
                GetKrb5SNameData(det_ctx, transforms, f, &cbdata, engine->sm_list);
103
104
18
        if (buffer == NULL || buffer->inspect == NULL)
105
0
            break;
106
107
18
        det_ctx->buffer_offset = 0;
108
18
        det_ctx->discontinue_matching = 0;
109
18
        det_ctx->inspection_recursion_counter = 0;
110
111
18
        const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
112
18
                                              NULL, f,
113
18
                                              (uint8_t *)buffer->inspect,
114
18
                                              buffer->inspect_len,
115
18
                                              buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE,
116
18
                                              DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
117
18
        if (match == 1) {
118
9
            return DETECT_ENGINE_INSPECT_SIG_MATCH;
119
9
        }
120
9
        local_id++;
121
9
    }
122
123
0
    return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
124
9
}
125
126
typedef struct PrefilterMpmKrb5Name {
127
    int list_id;
128
    const MpmCtx *mpm_ctx;
129
    const DetectEngineTransforms *transforms;
130
} PrefilterMpmKrb5Name;
131
132
/** \brief Krb5SName Krb5SName Mpm prefilter callback
133
 *
134
 *  \param det_ctx detection engine thread ctx
135
 *  \param p packet to inspect
136
 *  \param f flow to inspect
137
 *  \param txv tx to inspect
138
 *  \param pectx inspection context
139
 */
140
static void PrefilterTxKrb5SName(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
141
        Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
142
13
{
143
13
    SCEnter();
144
145
13
    const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
146
13
    const MpmCtx *mpm_ctx = ctx->mpm_ctx;
147
13
    const int list_id = ctx->list_id;
148
149
13
    uint32_t local_id = 0;
150
151
39
    while(1) {
152
        // loop until we get a NULL
153
154
39
        struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
155
39
        InspectionBuffer *buffer = GetKrb5SNameData(det_ctx, ctx->transforms, f, &cbdata, list_id);
156
39
        if (buffer == NULL)
157
13
            break;
158
159
26
        if (buffer->inspect_len >= mpm_ctx->minlen) {
160
26
            (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
161
26
                    &det_ctx->mtcu, &det_ctx->pmq,
162
26
                    buffer->inspect, buffer->inspect_len);
163
26
            PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
164
26
        }
165
166
26
        local_id++;
167
26
    }
168
13
}
169
170
static void PrefilterMpmKrb5NameFree(void *ptr)
171
258
{
172
258
    SCFree(ptr);
173
258
}
174
175
static int PrefilterMpmKrb5SNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
176
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
177
258
{
178
258
    PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
179
258
    if (pectx == NULL)
180
0
        return -1;
181
258
    pectx->list_id = list_id;
182
258
    pectx->mpm_ctx = mpm_ctx;
183
258
    pectx->transforms = &mpm_reg->transforms;
184
185
258
    return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5SName,
186
258
            mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
187
258
            pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
188
258
}
189
190
void DetectKrb5SNameRegister(void)
191
73
{
192
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].name = "krb5.sname";
193
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].alias = "krb5_sname";
194
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].url = "/rules/kerberos-keywords.html#krb5-sname";
195
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].Setup = DetectKrb5SNameSetup;
196
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
197
73
    sigmatch_table[DETECT_AL_KRB5_SNAME].desc = "sticky buffer to match on Kerberos 5 server name";
198
199
73
    DetectAppLayerMpmRegister2("krb5_sname", SIG_FLAG_TOCLIENT, 2,
200
73
            PrefilterMpmKrb5SNameRegister, NULL,
201
73
            ALPROTO_KRB5, 1);
202
203
73
    DetectAppLayerInspectEngineRegister2("krb5_sname",
204
73
            ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
205
73
            DetectEngineInspectKrb5SName, NULL);
206
207
73
    DetectBufferTypeSetDescriptionByName("krb5_sname",
208
73
            "Kerberos 5 ticket server name");
209
210
73
    g_krb5_sname_buffer_id = DetectBufferTypeGetByName("krb5_sname");
211
212
73
    DetectBufferTypeSupportsMultiInstance("krb5_sname");
213
73
}