Coverage Report

Created: 2026-08-14 07:34

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
649
{
49
649
    if (DetectBufferSetActiveList(de_ctx, s, g_krb5_sname_buffer_id) < 0)
50
2
        return -1;
51
52
647
    if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
53
51
        return -1;
54
55
596
    return 0;
56
647
}
57
58
static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
59
        const DetectEngineTransforms *transforms, Flow *_f,
60
        const struct Krb5PrincipalNameDataArgs *cbdata, int list_id)
61
46
{
62
46
    SCEnter();
63
64
46
    InspectionBuffer *buffer =
65
46
            InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
66
46
    if (buffer == NULL)
67
0
        return NULL;
68
46
    if (buffer->initialized)
69
16
        return buffer;
70
71
30
    uint32_t b_len = 0;
72
30
    const uint8_t *b = NULL;
73
74
30
    if (rs_krb5_tx_get_sname(cbdata->txv, cbdata->local_id, &b, &b_len) != 1) {
75
10
        InspectionBufferSetupMultiEmpty(buffer);
76
10
        return NULL;
77
10
    }
78
20
    if (b == NULL || b_len == 0) {
79
0
        InspectionBufferSetupMultiEmpty(buffer);
80
0
        return NULL;
81
0
    }
82
83
20
    InspectionBufferSetupMulti(buffer, transforms, b, b_len);
84
85
20
    SCReturnPtr(buffer, "InspectionBuffer");
86
20
}
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
8
{
92
8
    uint32_t local_id = 0;
93
94
8
    const DetectEngineTransforms *transforms = NULL;
95
8
    if (!engine->mpm) {
96
0
        transforms = engine->v2.transforms;
97
0
    }
98
99
16
    while (1) {
100
16
        struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
101
16
        InspectionBuffer *buffer =
102
16
                GetKrb5SNameData(det_ctx, transforms, f, &cbdata, engine->sm_list);
103
104
16
        if (buffer == NULL || buffer->inspect == NULL)
105
0
            break;
106
107
16
        det_ctx->buffer_offset = 0;
108
16
        det_ctx->discontinue_matching = 0;
109
16
        det_ctx->inspection_recursion_counter = 0;
110
111
16
        const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
112
16
                                              NULL, f,
113
16
                                              (uint8_t *)buffer->inspect,
114
16
                                              buffer->inspect_len,
115
16
                                              buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE,
116
16
                                              DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
117
16
        if (match == 1) {
118
8
            return DETECT_ENGINE_INSPECT_SIG_MATCH;
119
8
        }
120
8
        local_id++;
121
8
    }
122
123
0
    return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
124
8
}
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
10
{
143
10
    SCEnter();
144
145
10
    const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
146
10
    const MpmCtx *mpm_ctx = ctx->mpm_ctx;
147
10
    const int list_id = ctx->list_id;
148
149
10
    uint32_t local_id = 0;
150
151
30
    while(1) {
152
        // loop until we get a NULL
153
154
30
        struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
155
30
        InspectionBuffer *buffer = GetKrb5SNameData(det_ctx, ctx->transforms, f, &cbdata, list_id);
156
30
        if (buffer == NULL)
157
10
            break;
158
159
20
        if (buffer->inspect_len >= mpm_ctx->minlen) {
160
20
            (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
161
20
                    &det_ctx->mtcu, &det_ctx->pmq,
162
20
                    buffer->inspect, buffer->inspect_len);
163
20
            PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
164
20
        }
165
166
20
        local_id++;
167
20
    }
168
10
}
169
170
static void PrefilterMpmKrb5NameFree(void *ptr)
171
457
{
172
457
    SCFree(ptr);
173
457
}
174
175
static int PrefilterMpmKrb5SNameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
176
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
177
457
{
178
457
    PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
179
457
    if (pectx == NULL)
180
0
        return -1;
181
457
    pectx->list_id = list_id;
182
457
    pectx->mpm_ctx = mpm_ctx;
183
457
    pectx->transforms = &mpm_reg->transforms;
184
185
457
    return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5SName,
186
457
            mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
187
457
            pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
188
457
}
189
190
void DetectKrb5SNameRegister(void)
191
34
{
192
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].name = "krb5.sname";
193
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].alias = "krb5_sname";
194
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].url = "/rules/kerberos-keywords.html#krb5-sname";
195
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].Setup = DetectKrb5SNameSetup;
196
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
197
34
    sigmatch_table[DETECT_AL_KRB5_SNAME].desc = "sticky buffer to match on Kerberos 5 server name";
198
199
34
    DetectAppLayerMpmRegister2("krb5_sname", SIG_FLAG_TOCLIENT, 2,
200
34
            PrefilterMpmKrb5SNameRegister, NULL,
201
34
            ALPROTO_KRB5, 1);
202
203
34
    DetectAppLayerInspectEngineRegister2("krb5_sname",
204
34
            ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
205
34
            DetectEngineInspectKrb5SName, NULL);
206
207
34
    DetectBufferTypeSetDescriptionByName("krb5_sname",
208
34
            "Kerberos 5 ticket server name");
209
210
34
    g_krb5_sname_buffer_id = DetectBufferTypeGetByName("krb5_sname");
211
212
34
    DetectBufferTypeSupportsMultiInstance("krb5_sname");
213
34
}