Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/clients/ksu/ccache.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright (c) 1994 by the University of Southern California
4
*
5
* EXPORT OF THIS SOFTWARE from the United States of America may
6
* require a specific license from the United States Government.
7
* It is the responsibility of any person or organization contemplating
8
* export to obtain such a license before exporting.
9
*
10
* WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute
11
* this software and its documentation in source and binary forms is
12
* hereby granted, provided that any documentation or other materials
13
* related to such distribution or use acknowledge that the software
14
* was developed by the University of Southern California.
15
*
16
* DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The
17
* University of Southern California MAKES NO REPRESENTATIONS OR
18
* WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
19
* limitation, the University of Southern California MAKES NO
20
* REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
21
* PARTICULAR PURPOSE. The University of Southern
22
* California shall not be held liable for any liability nor for any
23
* direct, indirect, or consequential damages with respect to any
24
* claim by the user or distributor of the ksu software.
25
*
26
* KSU was written by: Ari Medvinsky, [email protected]
27
*/
28
29
#include "ksu.h"
30
#include "k5-base64.h"
31
#include "adm_proto.h"
32
#include <sys/types.h>
33
#include <sys/stat.h>
34
35
/******************************************************************
36
krb5_cache_copy
37
38
gets rid of any expired tickets in the secondary cache,
39
copies the default cache into the secondary cache,
40
41
************************************************************************/
42
43
static void
44
free_creds_list(krb5_context context, krb5_creds **list)
45
{
46
size_t i;
47
48
if (list == NULL)
49
return;
50
for (i = 0; list[i]; i++)
51
krb5_free_creds(context, list[i]);
52
free(list);
53
}
54
55
void show_credential(krb5_context, krb5_creds *, krb5_ccache);
56
57
/* modifies only the cc_other, the algorithm may look a bit funny,
58
but I had to do it this way, since remove function did not come
59
with k5 beta 3 release.
60
*/
61
62
krb5_error_code
63
krb5_ccache_copy(krb5_context context, krb5_ccache cc_def,
64
krb5_principal target_principal, krb5_ccache cc_target,
65
krb5_boolean restrict_creds, krb5_principal primary_principal,
66
krb5_boolean *stored)
67
{
68
krb5_error_code retval=0;
69
krb5_creds ** cc_def_creds_arr = NULL;
70
krb5_creds ** cc_other_creds_arr = NULL;
71
72
if (ks_ccache_is_initialized(context, cc_def)) {
73
retval = krb5_get_nonexp_tkts(context, cc_def, &cc_def_creds_arr);
74
if (retval)
75
goto cleanup;
76
}
77
78
retval = krb5_cc_initialize(context, cc_target, target_principal);
79
if (retval)
80
goto cleanup;
81
82
if (restrict_creds) {
83
retval = krb5_store_some_creds(context, cc_target, cc_def_creds_arr,
84
cc_other_creds_arr, primary_principal,
85
stored);
86
} else {
87
*stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr,
88
primary_principal);
89
retval = krb5_store_all_creds(context, cc_target, cc_def_creds_arr,
90
cc_other_creds_arr);
91
}
92
93
cleanup:
94
free_creds_list(context, cc_def_creds_arr);
95
free_creds_list(context, cc_other_creds_arr);
96
return retval;
97
}
98
99
100
krb5_error_code
101
krb5_store_all_creds(krb5_context context, krb5_ccache cc,
102
krb5_creds **creds_def, krb5_creds **creds_other)
103
{
104
105
int i = 0;
106
krb5_error_code retval = 0;
107
krb5_creds ** temp_creds= NULL;
108
109
110
if ((creds_def == NULL) && (creds_other == NULL))
111
return 0;
112
113
if ((creds_def == NULL) && (creds_other != NULL))
114
temp_creds = creds_other;
115
116
if ((creds_def != NULL) && (creds_other == NULL))
117
temp_creds = creds_def;
118
119
120
if (temp_creds){
121
while(temp_creds[i]){
122
if ((retval= krb5_cc_store_cred(context, cc,
123
temp_creds[i]))){
124
return retval;
125
}
126
i++;
127
}
128
}
129
else { /* both arrays have elements in them */
130
131
return KRB5KRB_ERR_GENERIC;
132
133
/************ while(creds_other[i]){
134
cmp = FALSE;
135
j = 0;
136
while(creds_def[j]){
137
cmp = compare_creds(creds_other[i],creds_def[j]);
138
139
if( cmp == TRUE) break;
140
141
j++;
142
}
143
if (cmp == FALSE){
144
if (retval= krb5_cc_store_cred(context, cc,
145
creds_other[i])){
146
return retval;
147
}
148
}
149
i ++;
150
}
151
152
i=0;
153
while(creds_def[i]){
154
if (retval= krb5_cc_store_cred(context, cc,
155
creds_def[i])){
156
return retval;
157
}
158
i++;
159
}
160
161
**************/
162
}
163
return 0;
164
}
165
166
krb5_boolean
167
compare_creds(krb5_context context, krb5_creds *cred1, krb5_creds *cred2)
168
{
169
krb5_boolean retval;
170
171
retval = krb5_principal_compare (context, cred1->client, cred2->client);
172
173
if (retval == TRUE)
174
retval = krb5_principal_compare (context, cred1->server, cred2->server);
175
176
return retval;
177
}
178
179
krb5_error_code
180
krb5_get_nonexp_tkts(krb5_context context, krb5_ccache cc,
181
krb5_creds ***creds_array)
182
{
183
184
krb5_creds creds, temp_tktq, temp_tkt;
185
krb5_creds **temp_creds = NULL;
186
krb5_error_code retval=0;
187
krb5_cc_cursor cur;
188
int count = 0;
189
int chunk_count = 1;
190
191
temp_creds = xcalloc(CHUNK, sizeof(*temp_creds));
192
memset(&temp_tktq, 0, sizeof(temp_tktq));
193
memset(&temp_tkt, 0, sizeof(temp_tkt));
194
memset(&creds, 0, sizeof(creds));
195
196
/* initialize the cursor */
197
retval = krb5_cc_start_seq_get(context, cc, &cur);
198
if (retval)
199
goto cleanup;
200
201
while (!(retval = krb5_cc_next_cred(context, cc, &cur, &creds))){
202
203
if (!krb5_is_config_principal(context, creds.server) &&
204
(retval = krb5_check_exp(context, creds.times))){
205
krb5_free_cred_contents(context, &creds);
206
if (retval != KRB5KRB_AP_ERR_TKT_EXPIRED){
207
goto cleanup;
208
}
209
if (auth_debug){
210
fprintf(stderr,"krb5_ccache_copy: CREDS EXPIRED:\n");
211
fputs(" Valid starting Expires Service principal\n",stdout);
212
show_credential(context, &creds, cc);
213
fprintf(stderr,"\n");
214
}
215
}
216
else { /* these credentials didn't expire */
217
retval = krb5_copy_creds(context, &creds, &temp_creds[count]);
218
krb5_free_cred_contents(context, &creds);
219
temp_creds[count+1] = NULL;
220
if (retval)
221
goto cleanup;
222
count ++;
223
224
if (count == (chunk_count * CHUNK -1)){
225
chunk_count ++;
226
227
temp_creds = xrealloc(temp_creds,
228
chunk_count * CHUNK *
229
sizeof(*temp_creds));
230
}
231
}
232
233
}
234
235
temp_creds[count] = NULL;
236
*creds_array = temp_creds;
237
temp_creds = NULL;
238
239
if (retval == KRB5_CC_END) {
240
retval = krb5_cc_end_seq_get(context, cc, &cur);
241
}
242
243
cleanup:
244
free_creds_list(context, temp_creds);
245
return retval;
246
}
247
248
krb5_error_code
249
krb5_check_exp(krb5_context context, krb5_ticket_times tkt_time)
250
{
251
krb5_error_code retval =0;
252
krb5_timestamp currenttime;
253
254
if ((retval = krb5_timeofday (context, &currenttime))){
255
return retval;
256
}
257
if (auth_debug){
258
fprintf(stderr,"krb5_check_exp: the krb5_clockskew is %d \n",
259
context->clockskew);
260
261
fprintf(stderr,"krb5_check_exp: currenttime - endtime %d \n",
262
ts_delta(currenttime, tkt_time.endtime));
263
264
}
265
266
if (ts_after(currenttime, ts_incr(tkt_time.endtime, context->clockskew))) {
267
retval = KRB5KRB_AP_ERR_TKT_EXPIRED ;
268
return retval;
269
}
270
271
return 0;
272
}
273
274
char *
275
flags_string(krb5_creds *cred)
276
{
277
static char buf[32];
278
int i = 0;
279
280
if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
281
buf[i++] = 'F';
282
if (cred->ticket_flags & TKT_FLG_FORWARDED)
283
buf[i++] = 'f';
284
if (cred->ticket_flags & TKT_FLG_PROXIABLE)
285
buf[i++] = 'P';
286
if (cred->ticket_flags & TKT_FLG_PROXY)
287
buf[i++] = 'p';
288
if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
289
buf[i++] = 'D';
290
if (cred->ticket_flags & TKT_FLG_POSTDATED)
291
buf[i++] = 'd';
292
if (cred->ticket_flags & TKT_FLG_INVALID)
293
buf[i++] = 'i';
294
if (cred->ticket_flags & TKT_FLG_RENEWABLE)
295
buf[i++] = 'R';
296
if (cred->ticket_flags & TKT_FLG_INITIAL)
297
buf[i++] = 'I';
298
if (cred->ticket_flags & TKT_FLG_HW_AUTH)
299
buf[i++] = 'H';
300
if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
301
buf[i++] = 'A';
302
buf[i] = '\0';
303
return(buf);
304
}
305
306
void
307
printtime(krb5_timestamp ts)
308
{
309
char fmtbuf[18], fill = ' ';
310
311
if (!krb5_timestamp_to_sfstring(ts, fmtbuf, sizeof(fmtbuf), &fill))
312
printf("%s", fmtbuf);
313
}
314
315
void
316
show_credential(krb5_context context, krb5_creds *cred, krb5_ccache cc)
317
{
318
krb5_error_code retval;
319
char *name = NULL, *sname = NULL, *defname = NULL, *flags;
320
int first = 1;
321
krb5_principal princ = NULL;
322
int show_flags =1;
323
324
retval = krb5_unparse_name(context, cred->client, &name);
325
if (retval) {
326
com_err(prog_name, retval, _("while unparsing client name"));
327
goto cleanup;
328
}
329
retval = krb5_unparse_name(context, cred->server, &sname);
330
if (retval) {
331
com_err(prog_name, retval, _("while unparsing server name"));
332
goto cleanup;
333
}
334
335
if ((retval = krb5_cc_get_principal(context, cc, &princ))) {
336
com_err(prog_name, retval, _("while retrieving principal name"));
337
goto cleanup;
338
}
339
if ((retval = krb5_unparse_name(context, princ, &defname))) {
340
com_err(prog_name, retval, _("while unparsing principal name"));
341
goto cleanup;
342
}
343
344
if (!cred->times.starttime)
345
cred->times.starttime = cred->times.authtime;
346
347
printtime(cred->times.starttime);
348
putchar(' '); putchar(' ');
349
printtime(cred->times.endtime);
350
putchar(' '); putchar(' ');
351
352
printf("%s\n", sname);
353
354
if (strcmp(name, defname)) {
355
printf(_("\tfor client %s"), name);
356
first = 0;
357
}
358
359
if (cred->times.renew_till) {
360
if (first)
361
fputs("\t",stdout);
362
else
363
fputs(", ",stdout);
364
fputs(_("renew until "), stdout);
365
printtime(cred->times.renew_till);
366
}
367
if (show_flags) {
368
flags = flags_string(cred);
369
if (flags && *flags) {
370
if (first)
371
fputs("\t",stdout);
372
else
373
fputs(", ",stdout);
374
printf(_("Flags: %s"), flags);
375
first = 0;
376
}
377
}
378
putchar('\n');
379
380
cleanup:
381
free(name);
382
free(sname);
383
free(defname);
384
krb5_free_principal(context, princ);
385
}
386
387
/* Create a random string suitable for a filename extension. */
388
krb5_error_code
389
gen_sym(krb5_context context, char **sym_out)
390
{
391
krb5_error_code retval;
392
char bytes[6], *p, *sym;
393
krb5_data data = make_data(bytes, sizeof(bytes));
394
395
*sym_out = NULL;
396
retval = krb5_c_random_make_octets(context, &data);
397
if (retval)
398
return retval;
399
sym = k5_base64_encode(data.data, data.length);
400
if (sym == NULL)
401
return ENOMEM;
402
/* Tweak the output alphabet just a bit. */
403
while ((p = strchr(sym, '/')) != NULL)
404
*p = '_';
405
while ((p = strchr(sym, '+')) != NULL)
406
*p = '-';
407
*sym_out = sym;
408
return 0;
409
}
410
411
krb5_error_code
412
krb5_ccache_overwrite(krb5_context context, krb5_ccache ccs, krb5_ccache cct,
413
krb5_principal primary_principal)
414
{
415
krb5_error_code retval=0;
416
krb5_principal defprinc = NULL, princ;
417
krb5_creds ** ccs_creds_arr = NULL;
418
419
if (ks_ccache_is_initialized(context, ccs)) {
420
retval = krb5_get_nonexp_tkts(context, ccs, &ccs_creds_arr);
421
if (retval)
422
goto cleanup;
423
}
424
425
retval = krb5_cc_get_principal(context, cct, &defprinc);
426
princ = (retval == 0) ? defprinc : primary_principal;
427
retval = krb5_cc_initialize(context, cct, princ);
428
if (retval)
429
goto cleanup;
430
431
retval = krb5_store_all_creds(context, cct, ccs_creds_arr, NULL);
432
433
cleanup:
434
free_creds_list(context, ccs_creds_arr);
435
krb5_free_principal(context, defprinc);
436
return retval;
437
}
438
439
krb5_error_code
440
krb5_store_some_creds(krb5_context context, krb5_ccache cc,
441
krb5_creds **creds_def, krb5_creds **creds_other,
442
krb5_principal prst, krb5_boolean *stored)
443
{
444
445
int i = 0;
446
krb5_error_code retval = 0;
447
krb5_creds ** temp_creds= NULL;
448
krb5_boolean temp_stored = FALSE;
449
450
451
if ((creds_def == NULL) && (creds_other == NULL))
452
return 0;
453
454
if ((creds_def == NULL) && (creds_other != NULL))
455
temp_creds = creds_other;
456
457
if ((creds_def != NULL) && (creds_other == NULL))
458
temp_creds = creds_def;
459
460
461
if (temp_creds){
462
while(temp_creds[i]){
463
if (krb5_principal_compare(context,
464
temp_creds[i]->client,
465
prst)== TRUE) {
466
467
if ((retval = krb5_cc_store_cred(context,
468
cc,temp_creds[i]))){
469
return retval;
470
}
471
temp_stored = TRUE;
472
}
473
474
i++;
475
}
476
}
477
else { /* both arrays have elements in them */
478
return KRB5KRB_ERR_GENERIC;
479
}
480
481
*stored = temp_stored;
482
return 0;
483
}
484
485
krb5_error_code
486
krb5_ccache_filter(krb5_context context, krb5_ccache cc, krb5_principal prst)
487
{
488
489
krb5_error_code retval=0;
490
krb5_principal temp_principal = NULL;
491
krb5_creds ** cc_creds_arr = NULL;
492
const char * cc_name;
493
krb5_boolean stored;
494
495
if (!ks_ccache_is_initialized(context, cc))
496
return 0;
497
498
if (auth_debug) {
499
cc_name = krb5_cc_get_name(context, cc);
500
fprintf(stderr, "putting cache %s through a filter for -z option\n",
501
cc_name);
502
}
503
504
retval = krb5_get_nonexp_tkts(context, cc, &cc_creds_arr);
505
if (retval)
506
goto cleanup;
507
508
retval = krb5_cc_get_principal(context, cc, &temp_principal);
509
if (retval)
510
goto cleanup;
511
512
retval = krb5_cc_initialize(context, cc, temp_principal);
513
if (retval)
514
goto cleanup;
515
516
retval = krb5_store_some_creds(context, cc, cc_creds_arr, NULL, prst,
517
&stored);
518
519
cleanup:
520
free_creds_list(context, cc_creds_arr);
521
krb5_free_principal(context, temp_principal);
522
return retval;
523
}
524
525
krb5_boolean
526
krb5_find_princ_in_cred_list(krb5_context context, krb5_creds **creds_list,
527
krb5_principal princ)
528
{
529
530
int i = 0;
531
krb5_boolean temp_stored = FALSE;
532
533
if (creds_list){
534
while(creds_list[i]){
535
if (krb5_principal_compare(context,
536
creds_list[i]->client,
537
princ)== TRUE){
538
temp_stored = TRUE;
539
break;
540
}
541
542
i++;
543
}
544
}
545
546
return temp_stored;
547
}
548
549
krb5_error_code
550
krb5_find_princ_in_cache(krb5_context context, krb5_ccache cc,
551
krb5_principal princ, krb5_boolean *found)
552
{
553
krb5_error_code retval = 0;
554
krb5_creds ** creds_list = NULL;
555
556
if (ks_ccache_is_initialized(context, cc)) {
557
retval = krb5_get_nonexp_tkts(context, cc, &creds_list);
558
if (retval)
559
goto cleanup;
560
}
561
562
*found = krb5_find_princ_in_cred_list(context, creds_list, princ);
563
564
cleanup:
565
free_creds_list(context, creds_list);
566
return retval;
567
}
568
569
krb5_boolean
570
ks_ccache_name_is_initialized(krb5_context context, const char *cctag)
571
{
572
krb5_boolean result;
573
krb5_ccache cc;
574
575
if (krb5_cc_resolve(context, cctag, &cc) != 0)
576
return FALSE;
577
result = ks_ccache_is_initialized(context, cc);
578
krb5_cc_close(context, cc);
579
580
return result;
581
}
582
583
krb5_boolean
584
ks_ccache_is_initialized(krb5_context context, krb5_ccache cc)
585
{
586
krb5_principal princ;
587
krb5_error_code retval;
588
589
if (cc == NULL)
590
return FALSE;
591
592
retval = krb5_cc_get_principal(context, cc, &princ);
593
if (retval == 0)
594
krb5_free_principal(context, princ);
595
596
return retval == 0;
597
}
598
599