Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/kdc/kdc_audit.c
34879 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* kdc_audit.c - Interface for KDC audit plugins. */
3
/*
4
* Copyright (C) 2013 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
*
14
* * Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in
16
* the documentation and/or other materials provided with the
17
* distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30
* OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include "k5-int.h"
34
#include "kdc_util.h"
35
#include "kdc_audit.h"
36
/* for krb5_klog_syslog */
37
#include <syslog.h>
38
#include "adm_proto.h"
39
40
struct audit_module_handle_st {
41
struct krb5_audit_vtable_st vt;
42
krb5_audit_moddata auctx;
43
};
44
typedef struct audit_module_handle_st *audit_module_handle;
45
46
static audit_module_handle *handles = NULL;
47
48
static void
49
free_handles(audit_module_handle *list)
50
{
51
audit_module_handle *hp, hdl;
52
53
if (list == NULL)
54
return;
55
56
for (hp = list; *hp != NULL; hp++) {
57
hdl = *hp;
58
if (hdl->vt.close != NULL)
59
hdl->vt.close(hdl->auctx);
60
free(hdl);
61
}
62
free(list);
63
}
64
65
/*
66
* Load all available audit plugin modules and prepare for logging. The list of
67
* modules is stored as an array in handles. Use unload_audit_modules() to free
68
* resources allocated by this function.
69
*/
70
krb5_error_code
71
load_audit_modules(krb5_context context)
72
{
73
krb5_error_code ret = 0;
74
krb5_plugin_initvt_fn *modules = NULL, *mod;
75
struct krb5_audit_vtable_st vtable;
76
audit_module_handle *list = NULL, hdl = NULL;
77
krb5_audit_moddata auctx;
78
int count = 0;
79
80
if (context == NULL || handles != NULL)
81
return EINVAL;
82
83
/* Get audit plugin vtable. */
84
ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_AUDIT, &modules);
85
if (ret)
86
return ret;
87
88
/* Allocate handle, initialize vtable. */
89
for (count = 0; modules[count] != NULL; count++);
90
list = k5calloc(count + 1, sizeof(*list), &ret);
91
if (list == NULL)
92
goto cleanup;
93
count = 0;
94
for (mod = modules; *mod != NULL; mod++) {
95
hdl = k5alloc(sizeof(*hdl), &ret);
96
if (hdl == NULL)
97
goto cleanup;
98
ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&hdl->vt);
99
if (ret) {
100
free(hdl);
101
hdl = NULL;
102
continue;
103
}
104
105
vtable = hdl->vt;
106
if (vtable.open != NULL) {
107
ret = vtable.open(&auctx);
108
if (ret) {
109
krb5_klog_syslog(LOG_ERR,
110
_("audit plugin %s failed to open. error=%i"),
111
vtable.name, ret);
112
goto cleanup;
113
}
114
hdl->auctx = auctx;
115
}
116
list[count++] = hdl;
117
list[count] = NULL;
118
hdl = NULL;
119
}
120
list[count] = NULL;
121
handles = list;
122
list = NULL;
123
ret = 0;
124
125
cleanup:
126
free(hdl);
127
k5_plugin_free_modules(context, modules);
128
free_handles(list);
129
return ret;
130
}
131
132
/* Free resources allocated by load_audit_modules() function. */
133
void
134
unload_audit_modules(krb5_context context)
135
{
136
free_handles(handles);
137
}
138
139
/*
140
* Write the output ticket ID into newly-allocated buffer.
141
* Returns 0 on success.
142
*/
143
krb5_error_code
144
kau_make_tkt_id(krb5_context context,
145
const krb5_ticket *ticket, char **out)
146
{
147
krb5_error_code ret = 0;
148
char *hash = NULL, *ptr;
149
uint8_t hashbytes[K5_SHA256_HASHLEN];
150
unsigned int i;
151
152
*out = NULL;
153
154
if (ticket == NULL)
155
return EINVAL;
156
157
ret = k5_sha256(&ticket->enc_part.ciphertext, 1, hashbytes);
158
if (ret)
159
return ret;
160
161
hash = k5alloc(sizeof(hashbytes) * 2 + 1, &ret);
162
if (hash == NULL)
163
return ret;
164
165
for (i = 0, ptr = hash; i < sizeof(hashbytes); i++, ptr += 2)
166
snprintf(ptr, 3, "%02X", hashbytes[i]);
167
*ptr = '\0';
168
*out = hash;
169
170
return 0;
171
}
172
173
/*
174
* Create and initialize krb5_audit_state structure.
175
* Returns 0 on success.
176
*/
177
krb5_error_code
178
kau_init_kdc_req(krb5_context context,
179
krb5_kdc_req *request, const struct sockaddr *from,
180
krb5_audit_state **state_out)
181
{
182
krb5_error_code ret = 0;
183
krb5_audit_state *state = NULL;
184
krb5_address addr;
185
const krb5_address unknown_addr = { KV5M_ADDRESS, 0, 0, NULL };
186
187
state = k5calloc(1, sizeof(*state), &ret);
188
if (state == NULL)
189
return ret;
190
191
ret = k5_sockaddr_to_address(from, TRUE, &addr);
192
if (ret)
193
addr = unknown_addr;
194
ret = krb5_copy_addr(context, &addr, &state->cl_addr);
195
if (ret)
196
goto cleanup;
197
state->request = request;
198
state->cl_port = sa_getport(from);
199
state->stage = AUTHN_REQ_CL;
200
ret = krb5int_random_string(context, state->req_id,
201
sizeof(state->req_id));
202
if (ret)
203
goto cleanup;
204
*state_out = state;
205
state = NULL;
206
207
cleanup:
208
kau_free_kdc_req(state);
209
return ret;
210
}
211
212
/* Free resources allocated by kau_init_kdc_req() and kau_make_tkt_id()
213
* routines. */
214
void
215
kau_free_kdc_req(krb5_audit_state *state)
216
{
217
if (state == NULL)
218
return;
219
free(state->tkt_in_id);
220
free(state->tkt_out_id);
221
free(state->evid_tkt_id);
222
krb5_free_address(NULL, state->cl_addr);
223
free(state);
224
}
225
226
/* Call the KDC start/stop audit plugin entry points. */
227
228
void
229
kau_kdc_stop(krb5_context context, const krb5_boolean ev_success)
230
{
231
audit_module_handle *hp, hdl;
232
233
if (handles == NULL)
234
return;
235
236
for (hp = handles; *hp != NULL; hp++) {
237
hdl = *hp;
238
if (hdl->vt.kdc_stop != NULL)
239
hdl->vt.kdc_stop(hdl->auctx, ev_success);
240
}
241
}
242
243
void
244
kau_kdc_start(krb5_context context, const krb5_boolean ev_success)
245
{
246
audit_module_handle *hp, hdl;
247
248
if (handles == NULL)
249
return;
250
251
for (hp = handles; *hp != NULL; hp++) {
252
hdl = *hp;
253
if (hdl->vt.kdc_start != NULL)
254
hdl->vt.kdc_start(hdl->auctx, ev_success);
255
}
256
}
257
258
/* Call the AS-REQ audit plugin entry point. */
259
void
260
kau_as_req(krb5_context context, const krb5_boolean ev_success,
261
krb5_audit_state *state)
262
{
263
audit_module_handle *hp, hdl;
264
265
if (handles == NULL)
266
return;
267
268
for (hp = handles; *hp != NULL; hp++) {
269
hdl = *hp;
270
if (hdl->vt.as_req != NULL)
271
hdl->vt.as_req(hdl->auctx, ev_success, state);
272
}
273
}
274
275
/* Call the TGS-REQ audit plugin entry point. */
276
void
277
kau_tgs_req(krb5_context context, const krb5_boolean ev_success,
278
krb5_audit_state *state)
279
{
280
audit_module_handle *hp, hdl;
281
282
if (handles == NULL)
283
return;
284
285
for (hp = handles; *hp != NULL; hp++) {
286
hdl = *hp;
287
if (hdl->vt.tgs_req != NULL)
288
hdl->vt.tgs_req(hdl->auctx, ev_success, state);
289
}
290
}
291
292
/* Call the S4U2Self audit plugin entry point. */
293
void
294
kau_s4u2self(krb5_context context, const krb5_boolean ev_success,
295
krb5_audit_state *state)
296
{
297
audit_module_handle *hp, hdl;
298
299
if (handles == NULL)
300
return;
301
302
for (hp = handles; *hp != NULL; hp++) {
303
hdl = *hp;
304
if (hdl->vt.tgs_s4u2self != NULL)
305
hdl->vt.tgs_s4u2self(hdl->auctx, ev_success, state);
306
}
307
}
308
309
/* Call the S4U2Proxy audit plugin entry point. */
310
void
311
kau_s4u2proxy(krb5_context context,const krb5_boolean ev_success,
312
krb5_audit_state *state)
313
{
314
audit_module_handle *hp, hdl;
315
316
if (handles == NULL)
317
return;
318
319
for (hp = handles; *hp != NULL; hp++) {
320
hdl = *hp;
321
if (hdl->vt.tgs_s4u2proxy != NULL)
322
hdl->vt.tgs_s4u2proxy(hdl->auctx, ev_success, state);
323
}
324
}
325
326
/* Call the U2U audit plugin entry point. */
327
void
328
kau_u2u(krb5_context context, const krb5_boolean ev_success,
329
krb5_audit_state *state)
330
{
331
audit_module_handle *hp, hdl;
332
333
if (handles == NULL)
334
return;
335
336
for (hp = handles; *hp != NULL; hp++) {
337
hdl = *hp;
338
if (hdl->vt.tgs_u2u != NULL)
339
hdl->vt.tgs_u2u(hdl->auctx, ev_success, state);
340
}
341
}
342
343