Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/kuser/klist.c
34876 views
1
/*
2
* Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
*
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
*
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
*
19
* 3. Neither the name of the Institute nor the names of its contributors
20
* may be used to endorse or promote products derived from this software
21
* without specific prior written permission.
22
*
23
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
* SUCH DAMAGE.
34
*/
35
36
#include "kuser_locl.h"
37
#include "rtbl.h"
38
#include "parse_units.h"
39
#include "kcc-commands.h"
40
41
static char*
42
printable_time_internal(time_t t, int x)
43
{
44
static char s[128];
45
char *p;
46
47
if ((p = ctime(&t)) == NULL)
48
strlcpy(s, "?", sizeof(s));
49
else
50
strlcpy(s, p + 4, sizeof(s));
51
s[x] = 0;
52
return s;
53
}
54
55
static char*
56
printable_time(time_t t)
57
{
58
return printable_time_internal(t, 20);
59
}
60
61
static char*
62
printable_time_long(time_t t)
63
{
64
return printable_time_internal(t, 20);
65
}
66
67
#define COL_ISSUED NP_(" Issued","")
68
#define COL_EXPIRES NP_(" Expires", "")
69
#define COL_FLAGS NP_("Flags", "")
70
#define COL_NAME NP_(" Name", "")
71
#define COL_PRINCIPAL NP_(" Principal", "in klist output")
72
#define COL_PRINCIPAL_KVNO NP_(" Principal (kvno)", "in klist output")
73
#define COL_CACHENAME NP_(" Cache name", "name in klist output")
74
#define COL_DEFCACHE NP_("", "")
75
76
static void
77
print_cred(krb5_context context, krb5_creds *cred, rtbl_t ct, int do_flags)
78
{
79
char *str;
80
krb5_error_code ret;
81
krb5_timestamp sec;
82
83
krb5_timeofday (context, &sec);
84
85
86
if(cred->times.starttime)
87
rtbl_add_column_entry(ct, COL_ISSUED,
88
printable_time(cred->times.starttime));
89
else
90
rtbl_add_column_entry(ct, COL_ISSUED,
91
printable_time(cred->times.authtime));
92
93
if(cred->times.endtime > sec)
94
rtbl_add_column_entry(ct, COL_EXPIRES,
95
printable_time(cred->times.endtime));
96
else
97
rtbl_add_column_entry(ct, COL_EXPIRES, N_(">>>Expired<<<", ""));
98
ret = krb5_unparse_name (context, cred->server, &str);
99
if (ret)
100
krb5_err(context, 1, ret, "krb5_unparse_name");
101
rtbl_add_column_entry(ct, COL_PRINCIPAL, str);
102
if(do_flags) {
103
char s[16], *sp = s;
104
if(cred->flags.b.forwardable)
105
*sp++ = 'F';
106
if(cred->flags.b.forwarded)
107
*sp++ = 'f';
108
if(cred->flags.b.proxiable)
109
*sp++ = 'P';
110
if(cred->flags.b.proxy)
111
*sp++ = 'p';
112
if(cred->flags.b.may_postdate)
113
*sp++ = 'D';
114
if(cred->flags.b.postdated)
115
*sp++ = 'd';
116
if(cred->flags.b.renewable)
117
*sp++ = 'R';
118
if(cred->flags.b.initial)
119
*sp++ = 'I';
120
if(cred->flags.b.invalid)
121
*sp++ = 'i';
122
if(cred->flags.b.pre_authent)
123
*sp++ = 'A';
124
if(cred->flags.b.hw_authent)
125
*sp++ = 'H';
126
*sp = '\0';
127
rtbl_add_column_entry(ct, COL_FLAGS, s);
128
}
129
free(str);
130
}
131
132
static void
133
print_cred_verbose(krb5_context context, krb5_creds *cred)
134
{
135
size_t j;
136
char *str;
137
krb5_error_code ret;
138
krb5_timestamp sec;
139
140
krb5_timeofday (context, &sec);
141
142
ret = krb5_unparse_name(context, cred->server, &str);
143
if(ret)
144
exit(1);
145
printf(N_("Server: %s\n", ""), str);
146
free (str);
147
148
ret = krb5_unparse_name(context, cred->client, &str);
149
if(ret)
150
exit(1);
151
printf(N_("Client: %s\n", ""), str);
152
free (str);
153
154
{
155
Ticket t;
156
size_t len;
157
char *s;
158
159
decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
160
ret = krb5_enctype_to_string(context, t.enc_part.etype, &s);
161
printf(N_("Ticket etype: ", ""));
162
if (ret == 0) {
163
printf("%s", s);
164
free(s);
165
} else {
166
printf(N_("unknown-enctype(%d)", ""), t.enc_part.etype);
167
}
168
if(t.enc_part.kvno)
169
printf(N_(", kvno %d", ""), *t.enc_part.kvno);
170
printf("\n");
171
if(cred->session.keytype != t.enc_part.etype) {
172
ret = krb5_enctype_to_string(context, cred->session.keytype, &str);
173
if(ret)
174
krb5_warn(context, ret, "session keytype");
175
else {
176
printf(N_("Session key: %s\n", "enctype"), str);
177
free(str);
178
}
179
}
180
free_Ticket(&t);
181
printf(N_("Ticket length: %lu\n", ""),
182
(unsigned long)cred->ticket.length);
183
}
184
printf(N_("Auth time: %s\n", ""),
185
printable_time_long(cred->times.authtime));
186
if(cred->times.authtime != cred->times.starttime)
187
printf(N_("Start time: %s\n", ""),
188
printable_time_long(cred->times.starttime));
189
printf(N_("End time: %s", ""),
190
printable_time_long(cred->times.endtime));
191
if(sec > cred->times.endtime)
192
printf(N_(" (expired)", ""));
193
printf("\n");
194
if(cred->flags.b.renewable)
195
printf(N_("Renew till: %s\n", ""),
196
printable_time_long(cred->times.renew_till));
197
{
198
char flags[1024];
199
unparse_flags(TicketFlags2int(cred->flags.b),
200
asn1_TicketFlags_units(),
201
flags, sizeof(flags));
202
printf(N_("Ticket flags: %s\n", ""), flags);
203
}
204
printf(N_("Addresses: ", ""));
205
if (cred->addresses.len != 0) {
206
for(j = 0; j < cred->addresses.len; j++){
207
char buf[128];
208
size_t len;
209
if(j) printf(", ");
210
ret = krb5_print_address(&cred->addresses.val[j],
211
buf, sizeof(buf), &len);
212
213
if(ret == 0)
214
printf("%s", buf);
215
}
216
} else {
217
printf(N_("addressless", ""));
218
}
219
printf("\n\n");
220
}
221
222
/*
223
* Print all tickets in `ccache' on stdout, verbosily iff do_verbose.
224
*/
225
226
static void
227
print_tickets (krb5_context context,
228
krb5_ccache ccache,
229
krb5_principal principal,
230
int do_verbose,
231
int do_flags,
232
int do_hidden)
233
{
234
krb5_error_code ret;
235
char *str, *name;
236
krb5_cc_cursor cursor;
237
krb5_creds creds;
238
krb5_deltat sec;
239
240
rtbl_t ct = NULL;
241
242
ret = krb5_unparse_name (context, principal, &str);
243
if (ret)
244
krb5_err (context, 1, ret, "krb5_unparse_name");
245
246
printf ("%17s: %s:%s\n",
247
N_("Credentials cache", ""),
248
krb5_cc_get_type(context, ccache),
249
krb5_cc_get_name(context, ccache));
250
printf ("%17s: %s\n", N_("Principal", ""), str);
251
252
ret = krb5_cc_get_friendly_name(context, ccache, &name);
253
if (ret == 0) {
254
if (strcmp(name, str) != 0)
255
printf ("%17s: %s\n", N_("Friendly name", ""), name);
256
free(name);
257
}
258
free (str);
259
260
if(do_verbose) {
261
printf ("%17s: %d\n", N_("Cache version", ""),
262
krb5_cc_get_version(context, ccache));
263
} else {
264
krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET);
265
}
266
267
ret = krb5_cc_get_kdc_offset(context, ccache, &sec);
268
269
if (ret == 0 && do_verbose && sec != 0) {
270
char buf[BUFSIZ];
271
int val;
272
int sig;
273
274
val = sec;
275
sig = 1;
276
if (val < 0) {
277
sig = -1;
278
val = -val;
279
}
280
281
unparse_time (val, buf, sizeof(buf));
282
283
printf ("%17s: %s%s\n", N_("KDC time offset", ""),
284
sig == -1 ? "-" : "", buf);
285
}
286
287
printf("\n");
288
289
ret = krb5_cc_start_seq_get (context, ccache, &cursor);
290
if (ret)
291
krb5_err(context, 1, ret, "krb5_cc_start_seq_get");
292
293
if(!do_verbose) {
294
ct = rtbl_create();
295
rtbl_add_column(ct, COL_ISSUED, 0);
296
rtbl_add_column(ct, COL_EXPIRES, 0);
297
if(do_flags)
298
rtbl_add_column(ct, COL_FLAGS, 0);
299
rtbl_add_column(ct, COL_PRINCIPAL, 0);
300
rtbl_set_separator(ct, " ");
301
}
302
while ((ret = krb5_cc_next_cred (context,
303
ccache,
304
&cursor,
305
&creds)) == 0) {
306
if (!do_hidden && krb5_is_config_principal(context, creds.server)) {
307
;
308
}else if(do_verbose){
309
print_cred_verbose(context, &creds);
310
}else{
311
print_cred(context, &creds, ct, do_flags);
312
}
313
krb5_free_cred_contents (context, &creds);
314
}
315
if(ret != KRB5_CC_END)
316
krb5_err(context, 1, ret, "krb5_cc_get_next");
317
ret = krb5_cc_end_seq_get (context, ccache, &cursor);
318
if (ret)
319
krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
320
if(!do_verbose) {
321
rtbl_format(ct, stdout);
322
rtbl_destroy(ct);
323
}
324
}
325
326
/*
327
* Check if there's a tgt for the realm of `principal' and ccache and
328
* if so return 0, else 1
329
*/
330
331
static int
332
check_for_tgt (krb5_context context,
333
krb5_ccache ccache,
334
krb5_principal principal,
335
time_t *expiration)
336
{
337
krb5_error_code ret;
338
krb5_creds pattern;
339
krb5_creds creds;
340
krb5_const_realm client_realm;
341
int expired;
342
343
krb5_cc_clear_mcred(&pattern);
344
345
client_realm = krb5_principal_get_realm(context, principal);
346
347
ret = krb5_make_principal (context, &pattern.server,
348
client_realm, KRB5_TGS_NAME, client_realm, NULL);
349
if (ret)
350
krb5_err (context, 1, ret, "krb5_make_principal");
351
pattern.client = principal;
352
353
ret = krb5_cc_retrieve_cred (context, ccache, 0, &pattern, &creds);
354
krb5_free_principal (context, pattern.server);
355
if (ret) {
356
if (ret == KRB5_CC_END)
357
return 1;
358
krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");
359
}
360
361
expired = time(NULL) > creds.times.endtime;
362
363
if (expiration)
364
*expiration = creds.times.endtime;
365
366
krb5_free_cred_contents (context, &creds);
367
368
return expired;
369
}
370
371
/*
372
* Print a list of all AFS tokens
373
*/
374
375
#ifndef NO_AFS
376
377
static void
378
display_tokens(int do_verbose)
379
{
380
uint32_t i;
381
unsigned char t[4096];
382
struct ViceIoctl parms;
383
384
parms.in = (void *)&i;
385
parms.in_size = sizeof(i);
386
parms.out = (void *)t;
387
parms.out_size = sizeof(t);
388
389
for (i = 0;; i++) {
390
int32_t size_secret_tok, size_public_tok;
391
unsigned char *cell;
392
struct ClearToken ct;
393
unsigned char *r = t;
394
struct timeval tv;
395
char buf1[20], buf2[20];
396
397
if(k_pioctl(NULL, VIOCGETTOK, &parms, 0) < 0) {
398
if(errno == EDOM)
399
break;
400
continue;
401
}
402
if(parms.out_size > sizeof(t))
403
continue;
404
if(parms.out_size < sizeof(size_secret_tok))
405
continue;
406
t[min(parms.out_size,sizeof(t)-1)] = 0;
407
memcpy(&size_secret_tok, r, sizeof(size_secret_tok));
408
/* dont bother about the secret token */
409
r += size_secret_tok + sizeof(size_secret_tok);
410
if (parms.out_size < (r - t) + sizeof(size_public_tok))
411
continue;
412
memcpy(&size_public_tok, r, sizeof(size_public_tok));
413
r += sizeof(size_public_tok);
414
if (parms.out_size < (r - t) + size_public_tok + sizeof(int32_t))
415
continue;
416
memcpy(&ct, r, size_public_tok);
417
r += size_public_tok;
418
/* there is a int32_t with length of cellname, but we dont read it */
419
r += sizeof(int32_t);
420
cell = r;
421
422
gettimeofday (&tv, NULL);
423
strlcpy (buf1, printable_time(ct.BeginTimestamp),
424
sizeof(buf1));
425
if (do_verbose || tv.tv_sec < ct.EndTimestamp)
426
strlcpy (buf2, printable_time(ct.EndTimestamp),
427
sizeof(buf2));
428
else
429
strlcpy (buf2, N_(">>> Expired <<<", ""), sizeof(buf2));
430
431
printf("%s %s ", buf1, buf2);
432
433
if ((ct.EndTimestamp - ct.BeginTimestamp) & 1)
434
printf(N_("User's (AFS ID %d) tokens for %s", ""), ct.ViceId, cell);
435
else
436
printf(N_("Tokens for %s", ""), cell);
437
if (do_verbose)
438
printf(" (%d)", ct.AuthHandle);
439
putchar('\n');
440
}
441
}
442
#endif
443
444
/*
445
* display the ccache in `cred_cache'
446
*/
447
448
static int
449
display_v5_ccache (krb5_context context, krb5_ccache ccache,
450
int do_test, int do_verbose,
451
int do_flags, int do_hidden)
452
{
453
krb5_error_code ret;
454
krb5_principal principal;
455
int exit_status = 0;
456
457
458
ret = krb5_cc_get_principal (context, ccache, &principal);
459
if (ret) {
460
if(ret == ENOENT) {
461
if (!do_test)
462
krb5_warnx(context, N_("No ticket file: %s", ""),
463
krb5_cc_get_name(context, ccache));
464
return 1;
465
} else
466
krb5_err (context, 1, ret, "krb5_cc_get_principal");
467
}
468
if (do_test)
469
exit_status = check_for_tgt (context, ccache, principal, NULL);
470
else
471
print_tickets (context, ccache, principal, do_verbose,
472
do_flags, do_hidden);
473
474
ret = krb5_cc_close (context, ccache);
475
if (ret)
476
krb5_err (context, 1, ret, "krb5_cc_close");
477
478
krb5_free_principal (context, principal);
479
480
return exit_status;
481
}
482
483
/*
484
*
485
*/
486
487
static int
488
list_caches(krb5_context context)
489
{
490
krb5_cc_cache_cursor cursor;
491
const char *cdef_name;
492
char *def_name;
493
krb5_error_code ret;
494
krb5_ccache id;
495
rtbl_t ct;
496
497
cdef_name = krb5_cc_default_name(context);
498
if (cdef_name == NULL)
499
krb5_errx(context, 1, "krb5_cc_default_name");
500
def_name = strdup(cdef_name);
501
502
ret = krb5_cc_cache_get_first (context, NULL, &cursor);
503
if (ret == KRB5_CC_NOSUPP)
504
return 0;
505
else if (ret)
506
krb5_err (context, 1, ret, "krb5_cc_cache_get_first");
507
508
ct = rtbl_create();
509
rtbl_add_column(ct, COL_NAME, 0);
510
rtbl_add_column(ct, COL_CACHENAME, 0);
511
rtbl_add_column(ct, COL_EXPIRES, 0);
512
rtbl_add_column(ct, COL_DEFCACHE, 0);
513
rtbl_set_prefix(ct, " ");
514
rtbl_set_column_prefix(ct, COL_NAME, "");
515
516
while (krb5_cc_cache_next (context, cursor, &id) == 0) {
517
krb5_principal principal = NULL;
518
int expired = 0;
519
char *name;
520
time_t t;
521
522
ret = krb5_cc_get_principal(context, id, &principal);
523
if (ret)
524
continue;
525
526
expired = check_for_tgt (context, id, principal, &t);
527
528
ret = krb5_cc_get_friendly_name(context, id, &name);
529
if (ret == 0) {
530
const char *str;
531
char *fname;
532
rtbl_add_column_entry(ct, COL_NAME, name);
533
rtbl_add_column_entry(ct, COL_CACHENAME,
534
krb5_cc_get_name(context, id));
535
if (expired)
536
str = N_(">>> Expired <<<", "");
537
else
538
str = printable_time(t);
539
rtbl_add_column_entry(ct, COL_EXPIRES, str);
540
free(name);
541
542
ret = krb5_cc_get_full_name(context, id, &fname);
543
if (ret)
544
krb5_err (context, 1, ret, "krb5_cc_get_full_name");
545
546
if (strcmp(fname, def_name) == 0)
547
rtbl_add_column_entry(ct, COL_DEFCACHE, "*");
548
else
549
rtbl_add_column_entry(ct, COL_DEFCACHE, "");
550
551
krb5_xfree(fname);
552
}
553
krb5_cc_close(context, id);
554
555
krb5_free_principal(context, principal);
556
}
557
558
krb5_cc_cache_end_seq_get(context, cursor);
559
560
free(def_name);
561
rtbl_format(ct, stdout);
562
rtbl_destroy(ct);
563
564
return 0;
565
}
566
567
/*
568
*
569
*/
570
571
int
572
klist(struct klist_options *opt, int argc, char **argv)
573
{
574
krb5_error_code ret;
575
int exit_status = 0;
576
577
int do_verbose =
578
opt->verbose_flag ||
579
opt->a_flag ||
580
opt->n_flag;
581
int do_test =
582
opt->test_flag ||
583
opt->s_flag;
584
585
if (opt->list_all_flag) {
586
exit_status = list_caches(kcc_context);
587
return exit_status;
588
}
589
590
if (opt->v5_flag) {
591
krb5_ccache id;
592
593
if (opt->all_content_flag) {
594
krb5_cc_cache_cursor cursor;
595
596
ret = krb5_cc_cache_get_first(kcc_context, NULL, &cursor);
597
if (ret)
598
krb5_err(kcc_context, 1, ret, "krb5_cc_cache_get_first");
599
600
601
while (krb5_cc_cache_next(kcc_context, cursor, &id) == 0) {
602
exit_status |= display_v5_ccache(kcc_context, id, do_test,
603
do_verbose, opt->flags_flag,
604
opt->hidden_flag);
605
printf("\n\n");
606
}
607
krb5_cc_cache_end_seq_get(kcc_context, cursor);
608
609
} else {
610
if(opt->cache_string) {
611
ret = krb5_cc_resolve(kcc_context, opt->cache_string, &id);
612
if (ret)
613
krb5_err(kcc_context, 1, ret, "%s", opt->cache_string);
614
} else {
615
ret = krb5_cc_default(kcc_context, &id);
616
if (ret)
617
krb5_err(kcc_context, 1, ret, "krb5_cc_resolve");
618
}
619
exit_status = display_v5_ccache(kcc_context, id, do_test,
620
do_verbose, opt->flags_flag,
621
opt->hidden_flag);
622
}
623
}
624
625
if (!do_test) {
626
#ifndef NO_AFS
627
if (opt->tokens_flag && k_hasafs()) {
628
if (opt->v5_flag)
629
printf("\n");
630
display_tokens(opt->verbose_flag);
631
}
632
#endif
633
}
634
635
return exit_status;
636
}
637
638