Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/windows/leash/KrbListTickets.cpp
34890 views
1
#include "stdafx.h"
2
#include "lglobals.h"
3
#include "krb5.h"
4
5
static void
6
FreeTicketList(TicketList** ticketList)
7
{
8
TicketList* tempList = *ticketList, *killList;
9
10
while (tempList) {
11
killList = tempList;
12
tempList = tempList->next;
13
free(killList->service);
14
if (killList->encTypes)
15
free(killList->encTypes);
16
free(killList);
17
}
18
19
*ticketList = NULL;
20
}
21
22
void
23
LeashKRB5FreeTicketInfo(TICKETINFO *ticketinfo)
24
{
25
if (ticketinfo->principal) {
26
free(ticketinfo->principal);
27
ticketinfo->principal = NULL;
28
}
29
if (ticketinfo->ccache_name) {
30
pkrb5_free_string(NULL, ticketinfo->ccache_name);
31
ticketinfo->ccache_name = NULL;
32
}
33
if (ticketinfo->ticket_list)
34
FreeTicketList(&ticketinfo->ticket_list);
35
}
36
37
void
38
LeashKRB5FreeTickets(TICKETINFO **ticketinfolist)
39
{
40
TICKETINFO *ticketinfo = *ticketinfolist, *next;
41
while (ticketinfo) {
42
next = ticketinfo->next;
43
LeashKRB5FreeTicketInfo(ticketinfo);
44
free(ticketinfo);
45
ticketinfo = next;
46
}
47
*ticketinfolist = NULL;
48
}
49
50
/*
51
* LeashKRB5Error()
52
*/
53
int
54
LeashKRB5Error(krb5_error_code rc, LPCSTR FailedFunctionName)
55
{
56
#ifdef USE_MESSAGE_BOX
57
char message[256];
58
const char *errText;
59
60
errText = perror_message(rc);
61
_snprintf(message, sizeof(message),
62
"%s\n(Kerberos error %ld)\n\n%s failed",
63
errText,
64
rc,
65
FailedFunctionName);
66
message[sizeof(message)-1] = 0;
67
68
MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
69
MB_TASKMODAL |
70
MB_SETFOREGROUND);
71
#endif /* USE_MESSAGE_BOX */
72
return rc;
73
}
74
75
76
static void
77
etype_string(krb5_enctype enctype, char *buf, size_t buflen)
78
{
79
krb5_error_code retval;
80
81
if ((retval = pkrb5_enctype_to_name(enctype, FALSE, buf, buflen))) {
82
/* XXX if there's an error != EINVAL, I should probably report it */
83
sprintf_s(buf, buflen, "etype %d", enctype);
84
}
85
}
86
87
88
static void
89
CredToTicketInfo(krb5_creds KRBv5Credentials, TICKETINFO *ticketinfo)
90
{
91
ticketinfo->issued = (DWORD)KRBv5Credentials.times.starttime;
92
ticketinfo->valid_until = (DWORD)KRBv5Credentials.times.endtime;
93
ticketinfo->renew_until = KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ?
94
(DWORD)KRBv5Credentials.times.renew_till : (DWORD)0;
95
_tzset();
96
if ( ticketinfo->valid_until - time(0) <= 0L )
97
ticketinfo->btickets = EXPD_TICKETS;
98
else
99
ticketinfo->btickets = GOOD_TICKETS;
100
}
101
102
static int
103
CredToTicketList(krb5_context ctx, krb5_creds KRBv5Credentials,
104
char *PrincipalName, TicketList ***ticketListTail)
105
{
106
krb5_error_code code = 0;
107
krb5_ticket *tkt=NULL;
108
char *sServerName = NULL;
109
char Buffer[256], sestype[100], tkttype[100];
110
char *functionName = NULL;
111
TicketList *list = NULL;
112
113
functionName = "krb5_unparse_name()";
114
code = (*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName);
115
if (code)
116
goto cleanup;
117
118
if (!KRBv5Credentials.times.starttime)
119
KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;
120
121
memset(Buffer, '\0', sizeof(Buffer));
122
123
// @fixme: calloc for ptr init
124
list = (TicketList *)calloc(1, sizeof(TicketList));
125
if (!list) {
126
code = ENOMEM;
127
functionName = "calloc()";
128
goto cleanup;
129
}
130
list->service = strdup(sServerName);
131
if (!list->service) {
132
code = ENOMEM;
133
functionName = "calloc()";
134
goto cleanup;
135
}
136
list->issued = (DWORD)KRBv5Credentials.times.starttime;
137
list->valid_until = (DWORD)KRBv5Credentials.times.endtime;
138
if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE)
139
list->renew_until = (DWORD)KRBv5Credentials.times.renew_till;
140
else
141
list->renew_until = 0;
142
143
etype_string(KRBv5Credentials.keyblock.enctype, sestype, sizeof(sestype));
144
if (!pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
145
etype_string(tkt->enc_part.enctype, tkttype, sizeof(tkttype));
146
wsprintf(Buffer, "Session Key: %s Ticket: %s", sestype, tkttype);
147
pkrb5_free_ticket(ctx, tkt);
148
tkt = NULL;
149
} else {
150
wsprintf(Buffer, "Session Key: %s", sestype);
151
}
152
153
list->encTypes = (char *)calloc(1, strlen(Buffer)+1);
154
if (!list->encTypes) {
155
functionName = "calloc()";
156
code = ENOMEM;
157
goto cleanup;
158
}
159
strcpy(list->encTypes, Buffer);
160
161
list->flags = KRBv5Credentials.ticket_flags;
162
cleanup:
163
if (code) {
164
LeashKRB5Error(code, functionName);
165
if (list)
166
FreeTicketList(&list);
167
} else {
168
**ticketListTail = list;
169
*ticketListTail = &list->next;
170
}
171
172
if (sServerName != NULL)
173
(*pkrb5_free_unparsed_name)(ctx, sServerName);
174
175
return code;
176
}
177
178
// return 0 if ticketinfo was successfully appended to list, 1 otherwise
179
int
180
do_ccache(krb5_context ctx,
181
krb5_ccache cache,
182
TICKETINFO **ticketInfoTail)
183
{
184
krb5_cc_cursor cur;
185
krb5_creds creds;
186
krb5_principal princ = NULL;
187
krb5_flags flags;
188
krb5_error_code code;
189
char *defname = NULL;
190
char *functionName = NULL;
191
TicketList **ticketListTail;
192
TICKETINFO *ticketinfo = NULL;
193
int retval = 1;
194
195
// Don't need the actual ticket.
196
flags = KRB5_TC_NOTICKET;
197
code = pkrb5_cc_set_flags(ctx, cache, flags);
198
if (code) {
199
if (code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND) {
200
// Normal behavior; skip cache but suppress error message box
201
code = 0;
202
} else {
203
functionName = "krb5_cc_set_flags";
204
}
205
goto cleanup;
206
}
207
code = pkrb5_cc_get_principal(ctx, cache, &princ);
208
if (code) {
209
// Normal behavior; skip cache but suppress error message box
210
code = 0;
211
goto cleanup;
212
}
213
code = pkrb5_unparse_name(ctx, princ, &defname);
214
if (code) {
215
functionName = "krb5_unparse_name";
216
goto cleanup;
217
}
218
code = pkrb5_cc_start_seq_get(ctx, cache, &cur);
219
if (code) {
220
// MSLSA errors here if no TGT is found; suppress error message box
221
code = 0;
222
goto cleanup;
223
}
224
if (*ticketInfoTail)
225
ticketinfo = *ticketInfoTail;
226
else
227
// @fixme: calloc to init pointers
228
ticketinfo = (TICKETINFO *)calloc(1, sizeof(TICKETINFO));
229
230
if (ticketinfo == NULL) {
231
functionName = "calloc";
232
code = ENOMEM;
233
goto cleanup;
234
}
235
ticketinfo->next = NULL;
236
ticketinfo->ticket_list = NULL;
237
ticketinfo->principal = strdup(defname);
238
if (ticketinfo->principal == NULL) {
239
functionName = "strdup";
240
code = ENOMEM;
241
goto cleanup;
242
}
243
code = pkrb5_cc_get_full_name(ctx, cache, &ticketinfo->ccache_name);
244
if (code) {
245
functionName = "krb5_cc_get_full_name";
246
goto cleanup;
247
}
248
*ticketInfoTail = ticketinfo;
249
ticketListTail = &ticketinfo->ticket_list;
250
while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) {
251
if (!pkrb5_is_config_principal(ctx, creds.server)) {
252
CredToTicketList(ctx, creds, defname, &ticketListTail);
253
CredToTicketInfo(creds, ticketinfo);
254
}
255
pkrb5_free_cred_contents(ctx, &creds);
256
}
257
if (code == KRB5_CC_END) {
258
code = pkrb5_cc_end_seq_get(ctx, cache, &cur);
259
if (code) {
260
functionName = "krb5_cc_end_seq_get";
261
goto cleanup;
262
}
263
flags = 0;
264
code = pkrb5_cc_set_flags(ctx, cache, flags);
265
if (code) {
266
functionName = "krb5_cc_set_flags";
267
goto cleanup;
268
}
269
} else {
270
functionName = "krb5_cc_next_cred";
271
goto cleanup;
272
}
273
cleanup:
274
if (code)
275
LeashKRB5Error(code, functionName);
276
if (ticketinfo) {
277
if (ticketinfo == *ticketInfoTail)
278
retval = 0;
279
else
280
LeashKRB5FreeTickets(&ticketinfo);
281
}
282
if (defname)
283
pkrb5_free_unparsed_name(ctx, defname);
284
if (princ)
285
pkrb5_free_principal(ctx, princ);
286
return retval;
287
}
288
289
290
//
291
// Returns 0 for success, 1 for failure
292
//
293
int
294
do_all_ccaches(krb5_context ctx, TICKETINFO **ticketinfotail)
295
{
296
krb5_error_code code;
297
krb5_ccache cache;
298
krb5_cccol_cursor cursor;
299
int retval = 1;
300
char *functionName = NULL;
301
302
code = pkrb5_cccol_cursor_new(ctx, &cursor);
303
if (code) {
304
functionName = "krb5_cccol_cursor_new";
305
goto cleanup;
306
}
307
retval = 0;
308
while (!(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) &&
309
cache != NULL) {
310
// Note that ticketinfotail will be updated here to point to the tail
311
// of the list but the caller of this function will remain with a
312
// pointer to the head.
313
if (do_ccache(ctx, cache, ticketinfotail) == 0)
314
ticketinfotail = &((*ticketinfotail)->next);
315
pkrb5_cc_close(ctx, cache);
316
}
317
if (code)
318
functionName = "krb5_cccol_cursor_next";
319
pkrb5_cccol_cursor_free(ctx, &cursor);
320
cleanup:
321
if (code)
322
LeashKRB5Error(code, functionName);
323
return retval;
324
}
325
326
void
327
LeashKRB5ListDefaultTickets(TICKETINFO *ticketinfo)
328
{
329
krb5_error_code code;
330
krb5_context ctx = 0;
331
krb5_ccache cache = 0;
332
char *functionName = NULL;
333
334
ticketinfo->btickets = NO_TICKETS;
335
ticketinfo->principal = NULL;
336
ticketinfo->ccache_name = NULL;
337
ticketinfo->next = NULL;
338
ticketinfo->ticket_list = NULL;
339
ticketinfo->renew_until = 0;
340
ticketinfo->valid_until = 0;
341
ticketinfo->issued = 0;
342
343
code = pkrb5_init_context(&ctx);
344
if (code) {
345
functionName = "krb5_init_context";
346
goto cleanup;
347
}
348
349
code = pkrb5_cc_default(ctx, &cache);
350
if (code) {
351
functionName = "krb5_cc_default";
352
goto cleanup;
353
}
354
if (cache != NULL)
355
do_ccache(ctx, cache, &ticketinfo);
356
cleanup:
357
if (code)
358
LeashKRB5Error(code, functionName);
359
if (cache)
360
pkrb5_cc_close(ctx, cache);
361
if (ctx)
362
pkrb5_free_context(ctx);
363
}
364
365
366
/*
367
* LeashKRB5ListAllTickets()
368
*/
369
370
void
371
LeashKRB5ListAllTickets(TICKETINFO **ticketinfo)
372
{
373
krb5_error_code code;
374
krb5_context ctx = 0;
375
char *functionName = NULL;
376
377
code = pkrb5_init_context(&ctx);
378
if (code) {
379
functionName = "krb5_init_context";
380
goto cleanup;
381
}
382
383
do_all_ccaches(ctx, ticketinfo);
384
cleanup:
385
if (code)
386
LeashKRB5Error(code, functionName);
387
if (ctx)
388
pkrb5_free_context(ctx);
389
}
390
391