/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 | } |