]>
Commit | Line | Data |
---|---|---|
d6b9c029 PC |
1 | /* Copyright (C) 2018 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-cname.h" | |
35 | ||
d6b9c029 PC |
36 | #include "rust.h" |
37 | #include "app-layer-krb5.h" | |
d6b9c029 PC |
38 | |
39 | static int g_krb5_cname_buffer_id = 0; | |
40 | ||
41 | struct Krb5PrincipalNameDataArgs { | |
7d0a3941 | 42 | uint32_t local_id; /**< used as index into thread inspect array */ |
d6b9c029 PC |
43 | void *txv; |
44 | }; | |
45 | ||
46 | static int DetectKrb5CNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) | |
47 | { | |
b2638f71 VJ |
48 | if (DetectBufferSetActiveList(s, g_krb5_cname_buffer_id) < 0) |
49 | return -1; | |
d6b9c029 PC |
50 | |
51 | if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0) | |
52 | return -1; | |
53 | ||
54 | return 0; | |
55 | } | |
56 | ||
d6b9c029 PC |
57 | static InspectionBuffer *GetKrb5CNameData(DetectEngineThreadCtx *det_ctx, |
58 | const DetectEngineTransforms *transforms, | |
59 | Flow *_f, const struct Krb5PrincipalNameDataArgs *cbdata, | |
60 | int list_id, bool first) | |
61 | { | |
62 | SCEnter(); | |
63 | ||
3dc50322 VJ |
64 | InspectionBuffer *buffer = |
65 | InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id); | |
d6b9c029 PC |
66 | if (buffer == NULL) |
67 | return NULL; | |
68 | if (!first && buffer->inspect != NULL) | |
69 | return buffer; | |
70 | ||
71 | uint32_t b_len = 0; | |
429ca858 | 72 | const uint8_t *b = NULL; |
d6b9c029 | 73 | |
7d0a3941 | 74 | if (rs_krb5_tx_get_cname(cbdata->txv, cbdata->local_id, &b, &b_len) != 1) |
d6b9c029 PC |
75 | return NULL; |
76 | if (b == NULL || b_len == 0) | |
77 | return NULL; | |
78 | ||
3dc50322 | 79 | InspectionBufferSetupMulti(buffer, transforms, b, b_len); |
d6b9c029 PC |
80 | |
81 | SCReturnPtr(buffer, "InspectionBuffer"); | |
82 | } | |
83 | ||
84 | static int DetectEngineInspectKrb5CName( | |
85 | DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, | |
86 | const DetectEngineAppInspectionEngine *engine, | |
87 | const Signature *s, | |
88 | Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id) | |
89 | { | |
7d0a3941 | 90 | uint32_t local_id = 0; |
d6b9c029 PC |
91 | |
92 | const DetectEngineTransforms *transforms = NULL; | |
93 | if (!engine->mpm) { | |
94 | transforms = engine->v2.transforms; | |
95 | } | |
96 | ||
97 | while (1) { | |
98 | struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, }; | |
99 | InspectionBuffer *buffer = GetKrb5CNameData(det_ctx, | |
100 | transforms, f, &cbdata, engine->sm_list, false); | |
101 | ||
102 | if (buffer == NULL || buffer->inspect == NULL) | |
103 | break; | |
104 | ||
105 | det_ctx->buffer_offset = 0; | |
106 | det_ctx->discontinue_matching = 0; | |
107 | det_ctx->inspection_recursion_counter = 0; | |
108 | ||
109 | const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, | |
32fb7d77 | 110 | NULL, f, |
d6b9c029 PC |
111 | (uint8_t *)buffer->inspect, |
112 | buffer->inspect_len, | |
113 | buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE, | |
32fb7d77 | 114 | DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); |
d6b9c029 PC |
115 | if (match == 1) { |
116 | return DETECT_ENGINE_INSPECT_SIG_MATCH; | |
117 | } | |
118 | local_id++; | |
119 | } | |
120 | ||
121 | return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; | |
122 | } | |
123 | ||
124 | typedef struct PrefilterMpmKrb5Name { | |
125 | int list_id; | |
126 | const MpmCtx *mpm_ctx; | |
127 | const DetectEngineTransforms *transforms; | |
128 | } PrefilterMpmKrb5Name; | |
129 | ||
130 | /** \brief Krb5CName Krb5CName Mpm prefilter callback | |
131 | * | |
132 | * \param det_ctx detection engine thread ctx | |
133 | * \param p packet to inspect | |
134 | * \param f flow to inspect | |
135 | * \param txv tx to inspect | |
136 | * \param pectx inspection context | |
137 | */ | |
138 | static void PrefilterTxKrb5CName(DetectEngineThreadCtx *det_ctx, | |
139 | const void *pectx, | |
140 | Packet *p, Flow *f, void *txv, | |
141 | const uint64_t idx, const uint8_t flags) | |
142 | { | |
143 | SCEnter(); | |
144 | ||
145 | const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx; | |
146 | const MpmCtx *mpm_ctx = ctx->mpm_ctx; | |
147 | const int list_id = ctx->list_id; | |
148 | ||
7d0a3941 | 149 | uint32_t local_id = 0; |
d6b9c029 PC |
150 | |
151 | while(1) { | |
152 | // loop until we get a NULL | |
153 | ||
154 | struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv }; | |
155 | InspectionBuffer *buffer = GetKrb5CNameData(det_ctx, ctx->transforms, | |
156 | f, &cbdata, list_id, true); | |
157 | if (buffer == NULL) | |
158 | break; | |
159 | ||
160 | if (buffer->inspect_len >= mpm_ctx->minlen) { | |
161 | (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, | |
162 | &det_ctx->mtcu, &det_ctx->pmq, | |
163 | buffer->inspect, buffer->inspect_len); | |
164 | } | |
165 | ||
166 | local_id++; | |
167 | } | |
168 | } | |
169 | ||
170 | static void PrefilterMpmKrb5NameFree(void *ptr) | |
171 | { | |
172 | SCFree(ptr); | |
173 | } | |
174 | ||
175 | static int PrefilterMpmKrb5CNameRegister(DetectEngineCtx *de_ctx, | |
176 | SigGroupHead *sgh, MpmCtx *mpm_ctx, | |
4dff903b | 177 | const DetectBufferMpmRegistery *mpm_reg, int list_id) |
d6b9c029 PC |
178 | { |
179 | PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx)); | |
180 | if (pectx == NULL) | |
181 | return -1; | |
182 | pectx->list_id = list_id; | |
183 | pectx->mpm_ctx = mpm_ctx; | |
4dff903b | 184 | pectx->transforms = &mpm_reg->transforms; |
d6b9c029 PC |
185 | |
186 | return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5CName, | |
4dff903b | 187 | mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress, |
d6b9c029 PC |
188 | pectx, PrefilterMpmKrb5NameFree, mpm_reg->name); |
189 | } | |
190 | ||
191 | void DetectKrb5CNameRegister(void) | |
192 | { | |
b2638f71 VJ |
193 | sigmatch_table[DETECT_AL_KRB5_CNAME].name = "krb5.cname"; |
194 | sigmatch_table[DETECT_AL_KRB5_CNAME].alias = "krb5_cname"; | |
26bcc975 | 195 | sigmatch_table[DETECT_AL_KRB5_CNAME].url = "/rules/kerberos-keywords.html#krb5-cname"; |
d6b9c029 | 196 | sigmatch_table[DETECT_AL_KRB5_CNAME].Setup = DetectKrb5CNameSetup; |
b2638f71 | 197 | sigmatch_table[DETECT_AL_KRB5_CNAME].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER; |
d801c3e5 | 198 | sigmatch_table[DETECT_AL_KRB5_CNAME].desc = "sticky buffer to match on Kerberos 5 client name"; |
d6b9c029 PC |
199 | |
200 | DetectAppLayerMpmRegister2("krb5_cname", SIG_FLAG_TOCLIENT, 2, | |
201 | PrefilterMpmKrb5CNameRegister, NULL, | |
202 | ALPROTO_KRB5, 1); | |
203 | ||
204 | DetectAppLayerInspectEngineRegister2("krb5_cname", | |
205 | ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0, | |
206 | DetectEngineInspectKrb5CName, NULL); | |
207 | ||
208 | DetectBufferTypeSetDescriptionByName("krb5_cname", | |
209 | "Kerberos 5 ticket client name"); | |
210 | ||
211 | g_krb5_cname_buffer_id = DetectBufferTypeGetByName("krb5_cname"); | |
212 | } |